diff --git a/.gitignore b/.gitignore deleted file mode 100644 index 77c01ba..0000000 --- a/.gitignore +++ /dev/null @@ -1,9 +0,0 @@ -.gradle/ -.idea/ -build/ -web/ - -*.swp -*.swo - -*.db diff --git a/LICENSE b/LICENSE index 17a5346..00d9714 100644 --- a/LICENSE +++ b/LICENSE @@ -1,5 +1,5 @@ MIT License -Copyright (c) 2019 Lars Westermann +Copyright (c) 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. diff --git a/README.md b/README.md index 3b91bef..e1cfe44 100644 --- a/README.md +++ b/README.md @@ -1,16 +1,3 @@ # portal -Webportal for everything and stuff - -## Usage - -The server can be started directly via: -```bash -./gradlew run -``` - -Or create a shadow jar: -```bash -./gradlew jar -java -jar build/libs/portal.jar -``` +Webportal for everything and stuff \ No newline at end of file diff --git a/build.gradle b/build.gradle deleted file mode 100644 index 58e9f96..0000000 --- a/build.gradle +++ /dev/null @@ -1,183 +0,0 @@ -import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar - -buildscript { - repositories { - jcenter() - - maven { - url "https://plugins.gradle.org/m2/" - } - } -} - -plugins { - id 'kotlin-multiplatform' version '1.3.20' - id 'kotlinx-serialization' version '1.3.20' - id "org.kravemir.gradle.sass" version "1.2.2" - id "com.github.johnrengelman.shadow" version "4.0.4" -} - -group "de.kif" -version "0.1.0" - -repositories { - jcenter() - maven { url "http://dl.bintray.com/kotlin/ktor" } - maven { url "https://kotlin.bintray.com/kotlinx" } - mavenCentral() -} -def ktor_version = '1.1.2' -def serialization_version = '0.10.0' - -kotlin { - jvm() { - compilations.all { - kotlinOptions { - freeCompilerArgs += [ - "-Xuse-experimental=io.ktor.locations.KtorExperimentalLocationsAPI", - "-Xuse-experimental=io.ktor.util.KtorExperimentalAPI" - ] - } - } - } - js() { - compilations.all { - kotlinOptions { - moduleKind = "umd" - sourceMap = true - metaInfo = true - } - } - } - sourceSets { - commonMain { - dependencies { - implementation kotlin('stdlib-common') - - implementation "org.jetbrains.kotlinx:kotlinx-serialization-runtime-common:$serialization_version" - } - } - commonTest { - dependencies { - implementation kotlin('test-common') - implementation kotlin('test-annotations-common') - } - } - jvmMain { - dependencies { - implementation kotlin('stdlib-jdk8') - - implementation "org.jetbrains.kotlinx:kotlinx-serialization-runtime:$serialization_version" - - implementation "io.ktor:ktor-server-netty:$ktor_version" - implementation "io.ktor:ktor-auth:$ktor_version" - implementation "io.ktor:ktor-locations:$ktor_version" - //implementation "io.ktor:ktor-websockets:$ktor_version" - - implementation "io.ktor:ktor-html-builder:$ktor_version" - - implementation 'org.xerial:sqlite-jdbc:3.25.2' - implementation 'org.jetbrains.exposed:exposed:0.12.2' - - implementation 'org.mindrot:jbcrypt:0.4' - - api 'io.github.microutils:kotlin-logging:1.6.23' - api 'ch.qos.logback:logback-classic:1.2.3' - api 'org.fusesource.jansi:jansi:1.8' - } - } - jvmTest { - dependencies { - implementation kotlin('test') - implementation kotlin('test-junit') - } - } - jsMain { - dependencies { - implementation kotlin('stdlib-js') - - implementation "org.jetbrains.kotlinx:kotlinx-serialization-runtime-js:$serialization_version" - - implementation "de.westermann:KObserve-js:0.8.0" - } - } - jsTest { - dependencies { - implementation kotlin('test-js') - } - } - } -} - -sass { - main { - srcDir = file("$projectDir/src/jsMain/resources/style") - outDir = file("$buildDir/processedResources/js/main/style") - - exclude = "**/*.css" - } -} - - -def webFolder = new File(project.buildDir, "../web") -def jsCompilations = kotlin.targets.js.compilations - -task populateWebFolder(dependsOn: [jsMainClasses, sass]) { - doLast { - copy { - from jsCompilations.main.output - from kotlin.sourceSets.jsMain.resources.srcDirs - jsCompilations.test.runtimeDependencyFiles.each { - if (it.exists() && !it.isDirectory()) { - from zipTree(it.absolutePath).matching { - include '*.js' - exclude '*.meta.js' - } - } - } - into webFolder - } - } -} - -jsJar.dependsOn(populateWebFolder) - -def mainClassName = 'de.kif.backend.Main' - -task run(type: JavaExec, dependsOn: [jvmMainClasses, jsJar]) { - main = mainClassName - classpath { - [ - kotlin.targets.jvm.compilations.main.output.allOutputs.files, - configurations.jvmRuntimeClasspath, - ] - } - args = [] -} - -clean.doFirst { - delete webFolder -} - -task jar(type: ShadowJar, dependsOn: [jvmMainClasses, jsMainClasses, sass]) { - from kotlin.targets.jvm.compilations.main.output - - from(kotlin.targets.js.compilations.main.output) { - into "web" - exclude '*.meta.js' - } - from(kotlin.sourceSets.jsMain.resources.srcDirs) { - into "web" - exclude '*.meta.js' - } - - configurations = [kotlin.targets.jvm.compilations.main.compileDependencyFiles] - - baseName = rootProject.name - classifier = null - version = null - - manifest { - attributes 'Main-Class': mainClassName - } -} diff --git a/gradle.properties b/gradle.properties deleted file mode 100644 index 29e08e8..0000000 --- a/gradle.properties +++ /dev/null @@ -1 +0,0 @@ -kotlin.code.style=official \ No newline at end of file diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar deleted file mode 100644 index 87b738c..0000000 Binary files a/gradle/wrapper/gradle-wrapper.jar and /dev/null differ diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties deleted file mode 100644 index 7cae24e..0000000 --- a/gradle/wrapper/gradle-wrapper.properties +++ /dev/null @@ -1,6 +0,0 @@ -#Tue Feb 05 15:31:59 CET 2019 -distributionBase=GRADLE_USER_HOME -distributionPath=wrapper/dists -zipStoreBase=GRADLE_USER_HOME -zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-5.1.1-all.zip diff --git a/gradlew b/gradlew deleted file mode 100644 index af6708f..0000000 --- a/gradlew +++ /dev/null @@ -1,172 +0,0 @@ -#!/usr/bin/env sh - -############################################################################## -## -## Gradle start up script for UN*X -## -############################################################################## - -# Attempt to set APP_HOME -# Resolve links: $0 may be a link -PRG="$0" -# Need this for relative symlinks. -while [ -h "$PRG" ] ; do - ls=`ls -ld "$PRG"` - link=`expr "$ls" : '.*-> \(.*\)$'` - if expr "$link" : '/.*' > /dev/null; then - PRG="$link" - else - PRG=`dirname "$PRG"`"/$link" - fi -done -SAVED="`pwd`" -cd "`dirname \"$PRG\"`/" >/dev/null -APP_HOME="`pwd -P`" -cd "$SAVED" >/dev/null - -APP_NAME="Gradle" -APP_BASE_NAME=`basename "$0"` - -# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -DEFAULT_JVM_OPTS='"-Xmx64m"' - -# Use the maximum available, or set MAX_FD != -1 to use that value. -MAX_FD="maximum" - -warn () { - echo "$*" -} - -die () { - echo - echo "$*" - echo - exit 1 -} - -# OS specific support (must be 'true' or 'false'). -cygwin=false -msys=false -darwin=false -nonstop=false -case "`uname`" in - CYGWIN* ) - cygwin=true - ;; - Darwin* ) - darwin=true - ;; - MINGW* ) - msys=true - ;; - NONSTOP* ) - nonstop=true - ;; -esac - -CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar - -# Determine the Java command to use to start the JVM. -if [ -n "$JAVA_HOME" ] ; then - if [ -x "$JAVA_HOME/jre/sh/java" ] ; then - # IBM's JDK on AIX uses strange locations for the executables - JAVACMD="$JAVA_HOME/jre/sh/java" - else - JAVACMD="$JAVA_HOME/bin/java" - fi - if [ ! -x "$JAVACMD" ] ; then - die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME - -Please set the JAVA_HOME variable in your environment to match the -location of your Java installation." - fi -else - JAVACMD="java" - which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. - -Please set the JAVA_HOME variable in your environment to match the -location of your Java installation." -fi - -# Increase the maximum file descriptors if we can. -if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then - MAX_FD_LIMIT=`ulimit -H -n` - if [ $? -eq 0 ] ; then - if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then - MAX_FD="$MAX_FD_LIMIT" - fi - ulimit -n $MAX_FD - if [ $? -ne 0 ] ; then - warn "Could not set maximum file descriptor limit: $MAX_FD" - fi - else - warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" - fi -fi - -# For Darwin, add options to specify how the application appears in the dock -if $darwin; then - GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" -fi - -# For Cygwin, switch paths to Windows format before running java -if $cygwin ; then - APP_HOME=`cygpath --path --mixed "$APP_HOME"` - CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` - JAVACMD=`cygpath --unix "$JAVACMD"` - - # We build the pattern for arguments to be converted via cygpath - ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` - SEP="" - for dir in $ROOTDIRSRAW ; do - ROOTDIRS="$ROOTDIRS$SEP$dir" - SEP="|" - done - OURCYGPATTERN="(^($ROOTDIRS))" - # Add a user-defined pattern to the cygpath arguments - if [ "$GRADLE_CYGPATTERN" != "" ] ; then - OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" - fi - # Now convert the arguments - kludge to limit ourselves to /bin/sh - i=0 - for arg in "$@" ; do - CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` - CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option - - if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition - eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` - else - eval `echo args$i`="\"$arg\"" - fi - i=$((i+1)) - done - case $i in - (0) set -- ;; - (1) set -- "$args0" ;; - (2) set -- "$args0" "$args1" ;; - (3) set -- "$args0" "$args1" "$args2" ;; - (4) set -- "$args0" "$args1" "$args2" "$args3" ;; - (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; - (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; - (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; - (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; - (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; - esac -fi - -# Escape application args -save () { - for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done - echo " " -} -APP_ARGS=$(save "$@") - -# Collect all arguments for the java command, following the shell quoting and substitution rules -eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" - -# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong -if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then - cd "$(dirname "$0")" -fi - -exec "$JAVACMD" "$@" diff --git a/gradlew.bat b/gradlew.bat deleted file mode 100644 index 0f8d593..0000000 --- a/gradlew.bat +++ /dev/null @@ -1,84 +0,0 @@ -@if "%DEBUG%" == "" @echo off -@rem ########################################################################## -@rem -@rem Gradle startup script for Windows -@rem -@rem ########################################################################## - -@rem Set local scope for the variables with windows NT shell -if "%OS%"=="Windows_NT" setlocal - -set DIRNAME=%~dp0 -if "%DIRNAME%" == "" set DIRNAME=. -set APP_BASE_NAME=%~n0 -set APP_HOME=%DIRNAME% - -@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -set DEFAULT_JVM_OPTS="-Xmx64m" - -@rem Find java.exe -if defined JAVA_HOME goto findJavaFromJavaHome - -set JAVA_EXE=java.exe -%JAVA_EXE% -version >NUL 2>&1 -if "%ERRORLEVEL%" == "0" goto init - -echo. -echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. - -goto fail - -:findJavaFromJavaHome -set JAVA_HOME=%JAVA_HOME:"=% -set JAVA_EXE=%JAVA_HOME%/bin/java.exe - -if exist "%JAVA_EXE%" goto init - -echo. -echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. - -goto fail - -:init -@rem Get command-line arguments, handling Windows variants - -if not "%OS%" == "Windows_NT" goto win9xME_args - -:win9xME_args -@rem Slurp the command line arguments. -set CMD_LINE_ARGS= -set _SKIP=2 - -:win9xME_args_slurp -if "x%~1" == "x" goto execute - -set CMD_LINE_ARGS=%* - -:execute -@rem Setup the command line - -set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar - -@rem Execute Gradle -"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% - -:end -@rem End local scope for the variables with windows NT shell -if "%ERRORLEVEL%"=="0" goto mainEnd - -:fail -rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of -rem the _cmd.exe /c_ return code! -if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 -exit /b 1 - -:mainEnd -if "%OS%"=="Windows_NT" endlocal - -:omega diff --git a/settings.gradle b/settings.gradle deleted file mode 100644 index 0c780ba..0000000 --- a/settings.gradle +++ /dev/null @@ -1,13 +0,0 @@ -pluginManagement { - resolutionStrategy { - eachPlugin { - if (requested.id.id == "kotlin-multiplatform") { - useModule("org.jetbrains.kotlin:kotlin-gradle-plugin:${requested.version}") - } - if (requested.id.id == "kotlinx-serialization") { - useModule("org.jetbrains.kotlin:kotlin-serialization:${requested.version}") - } - } - } -} -rootProject.name = 'portal' diff --git a/src/jsMain/kotlin/de/kif/frontend/calendar/Calendar.kt b/src/jsMain/kotlin/de/kif/frontend/calendar/Calendar.kt deleted file mode 100644 index 3a3f790..0000000 --- a/src/jsMain/kotlin/de/kif/frontend/calendar/Calendar.kt +++ /dev/null @@ -1,11 +0,0 @@ -package de.kif.frontend.calendar - -import de.westermann.kwebview.View -import de.westermann.kwebview.ViewCollection -import de.westermann.kwebview.createHtmlView - -class Calendar : ViewCollection(createHtmlView()) { - init { - - } -} \ No newline at end of file diff --git a/src/jsMain/kotlin/de/kif/frontend/main.kt b/src/jsMain/kotlin/de/kif/frontend/main.kt deleted file mode 100644 index cb72995..0000000 --- a/src/jsMain/kotlin/de/kif/frontend/main.kt +++ /dev/null @@ -1,19 +0,0 @@ -package de.kif.frontend - -import de.kif.frontend.calendar.Calendar -import de.westermann.kwebview.components.boxView -import de.westermann.kwebview.components.h1 -import de.westermann.kwebview.components.init - -fun main() = init { - clear() - h1("Test") - boxView { - style { - width = "600px" - height = "400px" - margin = "10px" - } - +Calendar() - } -} diff --git a/src/jsMain/kotlin/de/westermann/kwebview/AttributeDelegate.kt b/src/jsMain/kotlin/de/westermann/kwebview/AttributeDelegate.kt deleted file mode 100644 index 2c8a3e7..0000000 --- a/src/jsMain/kotlin/de/westermann/kwebview/AttributeDelegate.kt +++ /dev/null @@ -1,25 +0,0 @@ -package de.westermann.kwebview - -import kotlin.reflect.KProperty - -/** - * Delegate to easily access html attributes. - * - * @author lars - */ -class AttributeDelegate( - private val paramName: String? = null -) { - - private fun getParamName(property: KProperty<*>): String = paramName ?: property.name.toLowerCase() - - operator fun getValue(container: View, property: KProperty<*>) = container.html.getAttribute(getParamName(property)) - - operator fun setValue(container: View, property: KProperty<*>, value: String?) { - if (value == null) { - container.html.removeAttribute(getParamName(property)) - } else { - container.html.setAttribute(getParamName(property), value.toString()) - } - } -} \ No newline at end of file diff --git a/src/jsMain/kotlin/de/westermann/kwebview/ClassDelegate.kt b/src/jsMain/kotlin/de/westermann/kwebview/ClassDelegate.kt deleted file mode 100644 index e61e796..0000000 --- a/src/jsMain/kotlin/de/westermann/kwebview/ClassDelegate.kt +++ /dev/null @@ -1,49 +0,0 @@ -package de.westermann.kwebview - -import de.westermann.kobserve.Property -import de.westermann.kobserve.basic.property -import kotlin.reflect.KProperty - -/** - * Delegate to easily set css classes as boolean attributes. - * - * @author lars - */ -class ClassDelegate( - className: String? = null -) { - - private lateinit var container: View - private lateinit var paramName: String - private lateinit var classProperty: Property - - operator fun getValue(container: View, property: KProperty<*>): Property { - if (!this::container.isInitialized) { - this.container = container - } - - if (!this::paramName.isInitialized) { - var name = property.name.toDashCase() - if (name.endsWith("-property")) { - name = name.replace("-property", "") - } - paramName = name - } - - if (!this::classProperty.isInitialized) { - classProperty = property(container.html.classList.contains(paramName)) - - classProperty.onChange { - container.html.classList.toggle(paramName, classProperty.value) - } - } - - return classProperty - } - - init { - if (className != null) { - this.paramName = className - } - } -} \ No newline at end of file diff --git a/src/jsMain/kotlin/de/westermann/kwebview/ClassList.kt b/src/jsMain/kotlin/de/westermann/kwebview/ClassList.kt deleted file mode 100644 index 4921668..0000000 --- a/src/jsMain/kotlin/de/westermann/kwebview/ClassList.kt +++ /dev/null @@ -1,119 +0,0 @@ -package de.westermann.kwebview - -import de.westermann.kobserve.ListenerReference -import de.westermann.kobserve.Property -import de.westermann.kobserve.ReadOnlyProperty -import org.w3c.dom.DOMTokenList - -/** - * Represents the css classes of an html element. - * - * @author lars - */ -class ClassList( - private val list: DOMTokenList -) : Iterable { - - private val bound: MutableMap = mutableMapOf() - - - /** - * Add css class. - */ - fun add(clazz: String) { - if (clazz in bound) { - val p = bound[clazz] ?: return - if (p.property is Property) { - p.property.value = true - } else { - throw IllegalStateException("The given class is bound and cannot be modified manually!") - } - } else { - list.add(clazz) - } - } - - /** - * Add css class. - */ - operator fun plusAssign(clazz: String) = add(clazz) - - /** - * Add css class. - */ - fun remove(clazz: String) { - if (clazz in bound) { - val p = bound[clazz] ?: return - if (p.property is Property) { - p.property.value = false - } else { - throw IllegalStateException("The given class is bound and cannot be modified manually!") - } - } else { - list.remove(clazz) - } - } - - /** - * Remove css class. - */ - operator fun minusAssign(clazz: String) = remove(clazz) - - /** - * Check if css class exits. - */ - operator fun get(clazz: String): Boolean = list.contains(clazz) - - /** - * Check if css class exits. - */ - operator fun contains(clazz: String): Boolean = list.contains(clazz) - - /** - * Set css class present. - */ - operator fun set(clazz: String, present: Boolean) = - if (present) { - add(clazz) - } else { - remove(clazz) - } - - /** - * Toggle css class. - */ - fun toggle(clazz: String, force: Boolean? = null) = set(clazz, force ?: !contains(clazz)) - - fun bind(clazz: String, property: ReadOnlyProperty) { - if (clazz in bound) { - throw IllegalArgumentException("Class is already bound!") - } - - set(clazz, property.value) - bound[clazz] = Bound(property, - property.onChange.reference { - list.toggle(clazz, property.value) - } - ) - } - - fun unbind(clazz: String) { - if (clazz !in bound) { - throw IllegalArgumentException("Class is not bound!") - } - - bound[clazz]?.reference?.remove() - bound -= clazz - } - - override fun iterator(): Iterator { - return toString().split(" +".toRegex()).iterator() - } - - override fun toString(): String = list.value - - private data class Bound( - val property: ReadOnlyProperty, - val reference: ListenerReference? - ) -} \ No newline at end of file diff --git a/src/jsMain/kotlin/de/westermann/kwebview/DataSet.kt b/src/jsMain/kotlin/de/westermann/kwebview/DataSet.kt deleted file mode 100644 index 5103d75..0000000 --- a/src/jsMain/kotlin/de/westermann/kwebview/DataSet.kt +++ /dev/null @@ -1,128 +0,0 @@ -package de.westermann.kwebview - -import de.westermann.kobserve.ListenerReference -import de.westermann.kobserve.Property -import de.westermann.kobserve.ReadOnlyProperty -import org.w3c.dom.DOMStringMap -import org.w3c.dom.get -import org.w3c.dom.set - -/** - * Represents the css classes of an html element. - * - * @author lars - */ -class DataSet( - private val map: DOMStringMap -) { - - private val bound: MutableMap = mutableMapOf() - - /** - * Add css class. - */ - operator fun plusAssign(entry: Pair) { - if (entry.first in bound) { - bound[entry.first]?.set(entry.second) - } else { - map[entry.first] = entry.second - } - } - - /** - * Remove css class. - */ - operator fun minusAssign(key: String) { - if (key in bound) { - bound[key]?.set(null) - } else { - delete(map, key) - } - } - - /** - * Check if css class exits. - */ - operator fun get(key: String): String? = map[key] - - /** - * Set css class present. - */ - operator fun set(key: String, value: String?) = - if (value == null) { - this -= key - } else { - this += key to value - } - - fun bind(key: String, property: ReadOnlyProperty) { - if (key in bound) { - throw IllegalArgumentException("Class is already bound!") - } - - bound[key] = Bound(key, null, property) - } - - fun bind(key: String, property: ReadOnlyProperty) { - if (key in bound) { - throw IllegalArgumentException("Class is already bound!") - } - - bound[key] = Bound(key, property, null) - } - - fun unbind(key: String) { - if (key !in bound) { - throw IllegalArgumentException("Class is not bound!") - } - - bound[key]?.reference?.remove() - bound -= key - } - - private inner class Bound( - val key: String, - val propertyNullable: ReadOnlyProperty?, - val property: ReadOnlyProperty? - ) { - - var reference: ListenerReference? = null - - fun set(value: String?) { - if (propertyNullable != null && propertyNullable is Property) { - propertyNullable.value = value - } else if (property != null && property is Property && value != null) { - property.value = value - } else { - throw IllegalStateException("The given class is bound and cannot be modified manually!") - } - } - - init { - if (propertyNullable != null) { - reference = propertyNullable.onChange.reference { - val value = propertyNullable.value - if (value == null) { - delete(map, key) - } else { - map[key] = value - } - } - - val value = propertyNullable.value - if (value == null) { - delete(map, key) - } else { - map[key] = value - } - } else if (property != null) { - reference = property.onChange.reference { - map[key] = property.value - } - - map[key] = property.value - } - - } - } -} \ No newline at end of file diff --git a/src/jsMain/kotlin/de/westermann/kwebview/Dimension.kt b/src/jsMain/kotlin/de/westermann/kwebview/Dimension.kt deleted file mode 100644 index 72c39fb..0000000 --- a/src/jsMain/kotlin/de/westermann/kwebview/Dimension.kt +++ /dev/null @@ -1,62 +0,0 @@ -package de.westermann.kwebview - -import kotlin.math.abs -import kotlin.math.min - -/** - * @author lars - */ -data class Dimension( - val left: Double, - val top: Double, - val width: Double = 0.0, - val height: Double = 0.0 -) { - - constructor(position: Point, size: Point = Point.ZERO) : this(position.x, position.y, size.x, size.y) - - val position: Point - get() = Point(left, top) - - val size: Point - get() = Point(width, height) - - val right: Double - get() = left + width - - val bottom: Double - get() = top + height - - val edges: Set - get() = setOf( - Point(left, top), - Point(right, top), - Point(left, bottom), - Point(right, bottom) - ) - - val normalized: Dimension - get() { - val l = min(left, right) - val t = min(top, bottom) - return Dimension(l, t, abs(width), abs(width)) - } - - operator fun contains(other: Dimension): Boolean = !(other.left > right || - other.right < left || - other.top > bottom || - other.bottom < top) - - - operator fun contains(other: Point): Boolean { - val n = normalized - return (n.left <= other.x && (n.left + width) >= other.x) - && (n.top <= other.y && (n.top + height) >= other.y) - } - - operator fun plus(point: Point) = copy(left + point.x, top + point.y) - - companion object { - val ZERO = Dimension(0.0, 0.0) - } -} \ No newline at end of file diff --git a/src/jsMain/kotlin/de/westermann/kwebview/KWebViewDsl.kt b/src/jsMain/kotlin/de/westermann/kwebview/KWebViewDsl.kt deleted file mode 100644 index 43502bb..0000000 --- a/src/jsMain/kotlin/de/westermann/kwebview/KWebViewDsl.kt +++ /dev/null @@ -1,4 +0,0 @@ -package de.westermann.kwebview - -@DslMarker -annotation class KWebViewDsl diff --git a/src/jsMain/kotlin/de/westermann/kwebview/Point.kt b/src/jsMain/kotlin/de/westermann/kwebview/Point.kt deleted file mode 100644 index 2d41d0f..0000000 --- a/src/jsMain/kotlin/de/westermann/kwebview/Point.kt +++ /dev/null @@ -1,50 +0,0 @@ -package de.westermann.kwebview - -import kotlin.math.max -import kotlin.math.min -import kotlin.math.sqrt - -/** - * @author lars - */ -data class Point( - val x: Double, - val y: Double -) { - constructor(x: Int, y: Int) : this(x.toDouble(), y.toDouble()) - - operator fun plus(number: Int) = Point(x + number, y + number) - operator fun plus(number: Double) = Point(x + number, y + number) - operator fun plus(point: Point) = Point(x + point.x, y + point.y) - - operator fun minus(number: Int) = Point(x - number, y - number) - operator fun minus(number: Double) = Point(x - number, y - number) - operator fun minus(point: Point) = Point(x - point.x, y - point.y) - - operator fun times(number: Int) = Point(x * number, y * number) - operator fun times(number: Double) = Point(x * number, y * number) - operator fun times(point: Point) = Point(x * point.x, y * point.y) - - operator fun div(number: Int) = Point(x / number, y / number) - operator fun div(number: Double) = Point(x / number, y / number) - operator fun div(point: Point) = Point(x / point.x, y / point.y) - - operator fun unaryMinus(): Point = Point(-x, -y) - - fun min(): Double = min(x, y) - fun max(): Double = max(x, y) - - val isZero: Boolean - get() = x == 0.0 && y == 0.0 - - companion object { - val ZERO = Point(0.0, 0.0) - } - - val asPx: String - get() = "${x}px, ${y}px" - - fun distance(): Double = sqrt(x * x + y * y) - - infix fun distance(other: Point) = (this - other).distance() -} diff --git a/src/jsMain/kotlin/de/westermann/kwebview/View.kt b/src/jsMain/kotlin/de/westermann/kwebview/View.kt deleted file mode 100644 index 7090b93..0000000 --- a/src/jsMain/kotlin/de/westermann/kwebview/View.kt +++ /dev/null @@ -1,124 +0,0 @@ -package de.westermann.kwebview - -import de.westermann.kobserve.EventHandler -import org.w3c.dom.HTMLElement -import org.w3c.dom.css.CSSStyleDeclaration -import org.w3c.dom.events.FocusEvent -import org.w3c.dom.events.KeyboardEvent -import org.w3c.dom.events.MouseEvent -import org.w3c.dom.events.WheelEvent - -abstract class View(view: HTMLElement = createHtmlView()) { - - open val html: HTMLElement = view.also { view -> - this::class.simpleName?.let { name -> - view.classList.add(name.toDashCase()) - } - } - - val classList = ClassList(view.classList) - val dataset = DataSet(view.dataset) - - var id by AttributeDelegate() - - val clientLeft: Int - get() = html.clientLeft - val clientTop: Int - get() = html.clientTop - val clientWidth: Int - get() = html.clientWidth - val clientHeight: Int - get() = html.clientHeight - - val offsetLeft: Int - get() = html.offsetLeft - val offsetTop: Int - get() = html.offsetTop - val offsetWidth: Int - get() = html.offsetWidth - val offsetHeight: Int - get() = html.offsetHeight - - val offsetLeftTotal: Int - get() { - var element: HTMLElement? = html - var offset = 0 - while (element != null) { - offset += element.offsetLeft - element = element.offsetParent as? HTMLElement - } - return offset - } - val offsetTopTotal: Int - get() { - var element: HTMLElement? = html - var offset = 0 - while (element != null) { - offset += element.offsetTop - element = element.offsetParent as? HTMLElement - } - return offset - } - - val dimension: Dimension - get() = html.getBoundingClientRect().toDimension() - - var title by AttributeDelegate() - - val style = view.style - fun style(block: CSSStyleDeclaration.() -> Unit) { - block(style) - } - - fun focus() { - html.focus() - } - - fun blur() { - html.blur() - } - - fun click() { - html.click() - } - - val onClick = EventHandler() - val onDblClick = EventHandler() - val onContext = EventHandler() - - val onMouseDown = EventHandler() - val onMouseMove = EventHandler() - val onMouseUp = EventHandler() - val onMouseEnter = EventHandler() - val onMouseLeave = EventHandler() - - val onWheel = EventHandler() - - val onKeyDown = EventHandler() - val onKeyPress = EventHandler() - val onKeyUp = EventHandler() - - val onFocus = EventHandler() - val onBlur = EventHandler() - - init { - onClick.bind(view, "click") - onDblClick.bind(view, "dblclick") - onContext.bind(view, "contextmenu") - - onMouseDown.bind(view, "mousedown") - onMouseMove.bind(view, "mousemove") - onMouseUp.bind(view, "mouseup") - onMouseEnter.bind(view, "mouseenter") - onMouseLeave.bind(view, "mouseleave") - - onWheel.bind(view, "wheel") - - onKeyDown.bind(view, "keydown") - onKeyPress.bind(view, "keypress") - onKeyUp.bind(view, "keyup") - - onFocus.bind(view, "focus") - onBlur.bind(view, "blur") - } -} diff --git a/src/jsMain/kotlin/de/westermann/kwebview/ViewCollection.kt b/src/jsMain/kotlin/de/westermann/kwebview/ViewCollection.kt deleted file mode 100644 index 44e4d43..0000000 --- a/src/jsMain/kotlin/de/westermann/kwebview/ViewCollection.kt +++ /dev/null @@ -1,69 +0,0 @@ -package de.westermann.kwebview - -import org.w3c.dom.HTMLElement -import kotlin.dom.clear - -/** - * @author lars - */ -abstract class ViewCollection(view: HTMLElement = createHtmlView()) : View(view), Iterable { - - private val children: MutableList = mutableListOf() - - fun append(view: V) { - children += view - html.appendChild(view.html) - } - - operator fun plusAssign(view: V) = append(view) - - fun prepand(view: V) { - children.add(0, view) - html.insertBefore(view.html, html.firstChild) - } - - fun remove(view: V) { - if (children.contains(view)) { - children -= view - html.removeChild(view.html) - } - } - - fun toForeground(view: V) { - if (view in children && children.indexOf(view) < children.size - 1) { - remove(view) - append(view) - } - } - - fun toBackground(view: V) { - if (view in children && children.indexOf(view) > 0) { - remove(view) - prepand(view) - } - } - - fun first(): V = children.first() - fun last(): V = children.last() - - operator fun minusAssign(view: V) = remove(view) - - val isEmpty: Boolean - get() = children.isEmpty() - - fun clear() { - children.clear() - html.clear() - } - - override fun iterator(): Iterator = children.iterator() - - val size: Int - get() = children.size - - operator fun contains(view: V) = children.contains(view) - - operator fun V.unaryPlus() { - append(this) - } -} diff --git a/src/jsMain/kotlin/de/westermann/kwebview/ViewForLabel.kt b/src/jsMain/kotlin/de/westermann/kwebview/ViewForLabel.kt deleted file mode 100644 index 88330e8..0000000 --- a/src/jsMain/kotlin/de/westermann/kwebview/ViewForLabel.kt +++ /dev/null @@ -1,57 +0,0 @@ -package de.westermann.kwebview - -import de.westermann.kwebview.components.Label -import org.w3c.dom.HTMLInputElement -import kotlin.math.abs -import kotlin.random.Random - -abstract class ViewForLabel : View(createHtmlView()) { - override val html = super.html as HTMLInputElement - - private var label: Label? = null - - fun setLabel(label: Label) { - if (this.label != null) { - throw IllegalStateException("Label already set!") - } - - this.label = label - - val id = id - if (id?.isNotBlank() == true) { - label.html.htmlFor = id - } else { - val newId = this::class.simpleName?.toDashCase() + "-" + generateId() - this.id = newId - label.html.htmlFor = newId - } - } - - private var requiredInternal by AttributeDelegate("required") - var required: Boolean - get() = requiredInternal != null - set(value) { - requiredInternal = if (value) "required" else null - } - private var readonlyInternal by AttributeDelegate("readonly") - var readonly: Boolean - get() = readonlyInternal != null - set(value) { - readonlyInternal = if (value) "readonly" else null - } - - var tabindex by AttributeDelegate() - fun preventTabStop() { - tabindex = "-1" - } - - companion object { - fun generateId(length: Int = 16): String { - var str = "" - while (str.length <= length) { - str += abs(Random.nextLong()).toString(36) - } - return str.take(length) - } - } -} diff --git a/src/jsMain/kotlin/de/westermann/kwebview/components/Body.kt b/src/jsMain/kotlin/de/westermann/kwebview/components/Body.kt deleted file mode 100644 index 766467d..0000000 --- a/src/jsMain/kotlin/de/westermann/kwebview/components/Body.kt +++ /dev/null @@ -1,42 +0,0 @@ -package de.westermann.kwebview.components - -import de.westermann.kwebview.KWebViewDsl -import de.westermann.kwebview.View -import de.westermann.kwebview.ViewCollection -import de.westermann.kwebview.i18n -import org.w3c.dom.DocumentReadyState -import org.w3c.dom.HTMLBodyElement -import org.w3c.dom.LOADING -import kotlin.browser.document -import kotlin.browser.window - -object Body : ViewCollection(document.body - ?: throw NullPointerException("Access to body before body was loaded")) { - override val html = super.html as HTMLBodyElement -} - -@KWebViewDsl -fun init(language: String? = null, block: Body.() -> Unit) { - var done = if (language == null) 1 else 2 - if (document.readyState == DocumentReadyState.LOADING) { - window.onload = { - done -= 1 - if (done <= 0) { - block(Body) - } - } - } else { - done -= 1 - if (done <= 0) { - block(Body) - } - } - if (language != null) { - i18n.load(language) { - done -= 1 - if (done <= 0) { - block(Body) - } - } - } -} \ No newline at end of file diff --git a/src/jsMain/kotlin/de/westermann/kwebview/components/BoxView.kt b/src/jsMain/kotlin/de/westermann/kwebview/components/BoxView.kt deleted file mode 100644 index 983a187..0000000 --- a/src/jsMain/kotlin/de/westermann/kwebview/components/BoxView.kt +++ /dev/null @@ -1,22 +0,0 @@ -package de.westermann.kwebview.components - -import de.westermann.kwebview.KWebViewDsl -import de.westermann.kwebview.View -import de.westermann.kwebview.ViewCollection -import de.westermann.kwebview.createHtmlView -import org.w3c.dom.HTMLDivElement - -class BoxView() : ViewCollection(createHtmlView()) { - override val html = super.html as HTMLDivElement -} - -@KWebViewDsl -fun ViewCollection.boxView(vararg classes: String, init: BoxView.() -> Unit = {}): BoxView { - val view = BoxView() - for (c in classes) { - view.classList += c - } - append(view) - init(view) - return view -} diff --git a/src/jsMain/kotlin/de/westermann/kwebview/components/Button.kt b/src/jsMain/kotlin/de/westermann/kwebview/components/Button.kt deleted file mode 100644 index 5094ab9..0000000 --- a/src/jsMain/kotlin/de/westermann/kwebview/components/Button.kt +++ /dev/null @@ -1,53 +0,0 @@ -package de.westermann.kwebview.components - -import de.westermann.kobserve.Property -import de.westermann.kobserve.ReadOnlyProperty -import de.westermann.kobserve.basic.property -import de.westermann.kwebview.KWebViewDsl -import de.westermann.kwebview.View -import de.westermann.kwebview.ViewCollection -import de.westermann.kwebview.createHtmlView -import org.w3c.dom.HTMLButtonElement - -/** - * Represents a html span element. - * - * @author lars - */ -class Button() : ViewCollection(createHtmlView()) { - - constructor(text: String) : this() { - this.text = text - } - - override val html = super.html as HTMLButtonElement - - fun bind(property: ReadOnlyProperty) { - textProperty.bind(property) - } - - fun unbind() { - textProperty.unbind() - } - - var text: String - get() = html.textContent ?: "" - set(value) { - html.textContent = value - textProperty.invalidate() - } - - val textProperty: Property = property(this::text) -} - -@KWebViewDsl -fun ViewCollection.button(text: String = "", init: Button.() -> Unit = {}) = - Button(text).also(this::append).also(init) - -@KWebViewDsl -fun ViewCollection.button(text: ReadOnlyProperty, init: Button.() -> Unit = {}) = - Button(text.value).also(this::append).also { it.bind(text) }.also(init) - -@KWebViewDsl -fun ViewCollection.button(init: Button.() -> Unit = {}) = - Button().also(this::append).also(init) diff --git a/src/jsMain/kotlin/de/westermann/kwebview/components/Checkbox.kt b/src/jsMain/kotlin/de/westermann/kwebview/components/Checkbox.kt deleted file mode 100644 index a4aaf4f..0000000 --- a/src/jsMain/kotlin/de/westermann/kwebview/components/Checkbox.kt +++ /dev/null @@ -1,68 +0,0 @@ -package de.westermann.kwebview.components - -import de.westermann.kobserve.Property -import de.westermann.kobserve.ReadOnlyProperty -import de.westermann.kobserve.ValidationProperty -import de.westermann.kobserve.basic.property -import de.westermann.kwebview.* -import org.w3c.dom.events.Event -import org.w3c.dom.events.EventListener - -class Checkbox( - initValue: Boolean = false -) : ViewForLabel() { - - fun bind(property: ReadOnlyProperty) { - checkedProperty.bind(property) - readonly = true - } - - fun bind(property: Property) { - checkedProperty.bindBidirectional(property) - } - - fun unbind() { - checkedProperty.unbind() - } - - var checked: Boolean - get() = html.checked - set(value) { - html.checked = value - checkedProperty.invalidate() - } - - val checkedProperty: Property = property(this::checked) - - init { - checked = initValue - html.type = "checkbox" - - var lastValue = checked - val changeListener = object : EventListener { - override fun handleEvent(event: Event) { - val value = checked - if (value != checkedProperty.value || value != lastValue) { - lastValue = value - checkedProperty.value = value - } - } - } - - html.addEventListener("change", changeListener) - html.addEventListener("keyup", changeListener) - html.addEventListener("keypress", changeListener) - } -} - -@KWebViewDsl -fun ViewCollection.checkbox(value: Boolean = false, init: Checkbox.() -> Unit = {}) = - Checkbox(value).also(this::append).also(init) - -@KWebViewDsl -fun ViewCollection.checkbox(value: ReadOnlyProperty, init: Checkbox.() -> Unit = {}) = - Checkbox(value.value).also(this::append).also { it.bind(value) }.also(init) - -@KWebViewDsl -fun ViewCollection.checkbox(value: Property, init: Checkbox.() -> Unit = {}) = - Checkbox(value.value).also(this::append).also { it.bind(value) }.also(init) diff --git a/src/jsMain/kotlin/de/westermann/kwebview/components/FilterList.kt b/src/jsMain/kotlin/de/westermann/kwebview/components/FilterList.kt deleted file mode 100644 index 3da687a..0000000 --- a/src/jsMain/kotlin/de/westermann/kwebview/components/FilterList.kt +++ /dev/null @@ -1,105 +0,0 @@ -package de.westermann.kwebview.components - -import de.westermann.kobserve.Property -import de.westermann.kobserve.ReadOnlyProperty -import de.westermann.kwebview.View -import de.westermann.kwebview.ViewCollection -import de.westermann.kwebview.createHtmlView - -class FilterList( - val property: ReadOnlyProperty, - val filter: Filter -) : ViewCollection(createHtmlView()) { - - private val content: MutableMap = mutableMapOf() - - fun update() { - val list = filter.filter(property.value) - var missing = list - - for ((element, view) in content.entries) { - if (element in list) { - missing -= element - } else { - if (contains(view)) { - remove(view) - } - if (!filter.useCache) { - content -= element - } - } - } - - for (element in missing) { - val view = filter.render(element) - append(view) - if (property is Property) { - view.onClick { - property.value = element - } - } - content[element] = view - } - - clear() - - for (element in list) { - append(content[element]!!) - } - } - - init { - update() - - property.onChange { - update() - } - } -} - -interface Filter { - fun filter(partial: T): List - fun render(element: T): V - - val useCache: Boolean -} - -class StringFilter( - private val dataSet: List -) : Filter { - override fun filter(partial: String): List { - val lower = partial.trim().toLowerCase() - return dataSet.filter { - it.toLowerCase().contains(lower) - }.sortedBy { it.length + it.toLowerCase().indexOf(partial) * 2 } - } - - override fun render(element: String) = TextView(element) - - override val useCache = true -} - -class StaticStringFilter( - private val dataSet: List -) : Filter { - override fun filter(partial: String) = dataSet - - override fun render(element: String) = TextView(element) - - override val useCache = true -} - - -class DynamicStringFilter( - private val filter: (partial: String) -> List -) : Filter { - override fun filter(partial: String) = filter.invoke(partial) - - override fun render(element: String) = TextView(element) - - override val useCache = false -} - - -fun ViewCollection>.filterList(property: ReadOnlyProperty, filter: Filter, init: FilterList.() -> Unit = {}) = - FilterList(property, filter).also(this::append).also(init) \ No newline at end of file diff --git a/src/jsMain/kotlin/de/westermann/kwebview/components/Heading.kt b/src/jsMain/kotlin/de/westermann/kwebview/components/Heading.kt deleted file mode 100644 index 7808b0f..0000000 --- a/src/jsMain/kotlin/de/westermann/kwebview/components/Heading.kt +++ /dev/null @@ -1,96 +0,0 @@ -package de.westermann.kwebview.components - -import de.westermann.kobserve.Property -import de.westermann.kobserve.ReadOnlyProperty -import de.westermann.kobserve.basic.property -import de.westermann.kwebview.KWebViewDsl -import de.westermann.kwebview.View -import de.westermann.kwebview.ViewCollection -import de.westermann.kwebview.createHtmlView -import org.w3c.dom.HTMLHeadingElement - -class Heading( - val type: Type, - value: String = "" -) : View(createHtmlView(type.tagName)) { - - override val html = super.html as HTMLHeadingElement - - fun bind(property: ReadOnlyProperty) { - textProperty.bind(property) - } - - fun unbind() { - textProperty.unbind() - } - - var text: String - get() = html.textContent ?: "" - set(value) { - html.textContent = value - textProperty.invalidate() - } - - val textProperty: Property = property(this::text) - - init { - text = value - } - - enum class Type(val tagName: String) { - H1("h1"), - H2("h2"), - H3("h3"), - H4("h4"), - H5("h5"), - H6("h6") - } -} - -@KWebViewDsl -fun ViewCollection.h1(text: String = "", init: Heading.() -> Unit = {}) = - Heading(Heading.Type.H1, text).also(this::append).also(init) - -@KWebViewDsl -fun ViewCollection.h1(text: ReadOnlyProperty, init: Heading.() -> Unit = {}) = - Heading(Heading.Type.H1, text.value).also(this::append).also { it.bind(text) }.also(init) - -@KWebViewDsl -fun ViewCollection.h2(text: String = "", init: Heading.() -> Unit = {}) = - Heading(Heading.Type.H2, text).also(this::append).also(init) - -@KWebViewDsl -fun ViewCollection.h2(text: ReadOnlyProperty, init: Heading.() -> Unit = {}) = - Heading(Heading.Type.H2, text.value).also(this::append).also { it.bind(text) }.also(init) - -@KWebViewDsl -fun ViewCollection.h3(text: String = "", init: Heading.() -> Unit = {}) = - Heading(Heading.Type.H3, text).also(this::append).also(init) - -@KWebViewDsl -fun ViewCollection.h3(text: ReadOnlyProperty, init: Heading.() -> Unit = {}) = - Heading(Heading.Type.H3, text.value).also(this::append).also { it.bind(text) }.also(init) - -@KWebViewDsl -fun ViewCollection.h4(text: String = "", init: Heading.() -> Unit = {}) = - Heading(Heading.Type.H4, text).also(this::append).also(init) - -@KWebViewDsl -fun ViewCollection.h4(text: ReadOnlyProperty, init: Heading.() -> Unit = {}) = - Heading(Heading.Type.H4, text.value).also(this::append).also { it.bind(text) }.also(init) - -@KWebViewDsl -fun ViewCollection.h5(text: String = "", init: Heading.() -> Unit = {}) = - Heading(Heading.Type.H5, text).also(this::append).also(init) - -@KWebViewDsl -fun ViewCollection.h5(text: ReadOnlyProperty, init: Heading.() -> Unit = {}) = - Heading(Heading.Type.H5, text.value).also(this::append).also { it.bind(text) }.also(init) - -@KWebViewDsl -fun ViewCollection.h6(text: String = "", init: Heading.() -> Unit = {}) = - Heading(Heading.Type.H6, text).also(this::append).also(init) - -@KWebViewDsl -fun ViewCollection.h6(text: ReadOnlyProperty, init: Heading.() -> Unit = {}) = - Heading(Heading.Type.H6, text.value).also(this::append).also { it.bind(text) }.also(init) diff --git a/src/jsMain/kotlin/de/westermann/kwebview/components/ImageView.kt b/src/jsMain/kotlin/de/westermann/kwebview/components/ImageView.kt deleted file mode 100644 index c1c1f6b..0000000 --- a/src/jsMain/kotlin/de/westermann/kwebview/components/ImageView.kt +++ /dev/null @@ -1,46 +0,0 @@ -package de.westermann.kwebview.components - -import de.westermann.kobserve.Property -import de.westermann.kobserve.ReadOnlyProperty -import de.westermann.kobserve.basic.property -import de.westermann.kwebview.* -import org.w3c.dom.HTMLImageElement - -class ImageView( - src: String -) : View(createHtmlView("img")) { - - override val html = super.html as HTMLImageElement - - fun bind(property: ReadOnlyProperty) { - sourceProperty.bind(property) - } - - fun unbind() { - sourceProperty.unbind() - } - - var source: String - get() = html.src - set(value) { - html.src = value - sourceProperty.invalidate() - } - - val sourceProperty: Property = property(this::source) - - - var alt by AttributeDelegate("alt") - - init { - source = src - } -} - -@KWebViewDsl -fun ViewCollection.imageView(src: String = "", init: ImageView.() -> Unit = {}) = - ImageView(src).also(this::append).also(init) - -@KWebViewDsl -fun ViewCollection.imageView(src: ReadOnlyProperty, init: ImageView.() -> Unit = {}) = - ImageView(src.value).also(this::append).also { it.bind(src) }.also(init) diff --git a/src/jsMain/kotlin/de/westermann/kwebview/components/InputView.kt b/src/jsMain/kotlin/de/westermann/kwebview/components/InputView.kt deleted file mode 100644 index b7c5685..0000000 --- a/src/jsMain/kotlin/de/westermann/kwebview/components/InputView.kt +++ /dev/null @@ -1,154 +0,0 @@ -package de.westermann.kwebview.components - -import de.westermann.kobserve.Property -import de.westermann.kobserve.ReadOnlyProperty -import de.westermann.kobserve.ValidationProperty -import de.westermann.kobserve.basic.property -import de.westermann.kobserve.not -import de.westermann.kwebview.* -import org.w3c.dom.HTMLInputElement -import org.w3c.dom.events.Event -import org.w3c.dom.events.EventListener -import org.w3c.dom.events.KeyboardEvent - -class InputView( - type: InputType, - initValue: String = "" -) : ViewForLabel() { - - fun bind(property: ReadOnlyProperty) { - valueProperty.bind(property) - readonly = true - } - - fun bind(property: Property) { - valueProperty.bindBidirectional(property) - } - - fun bind(property: ValidationProperty) { - valueProperty.bindBidirectional(property) - invalidProperty.bind(!property.validProperty) - } - - fun unbind() { - valueProperty.unbind() - if (invalidProperty.isBound) { - invalidProperty.unbind() - } - } - - var value: String - get() = html.value - set(value) { - html.value = value - valueProperty.invalidate() - } - - val valueProperty: Property = property(this::value) - - var placeholder: String - get() = html.placeholder - set(value) { - html.placeholder = value - placeholderProperty.invalidate() - } - - val placeholderProperty: Property = property(this::placeholder) - - val invalidProperty by ClassDelegate("invalid") - var invalid by invalidProperty - - private var typeInternal by AttributeDelegate("type") - var type: InputType? - get() = typeInternal?.let(InputType.Companion::find) - set(value) { - typeInternal = value?.html - } - private var minInternal by AttributeDelegate("min") - var min: Double? - get() = minInternal?.toDoubleOrNull() - set(value) { - minInternal = value?.toString() - } - private var maxInternal by AttributeDelegate("max") - var max: Double? - get() = maxInternal?.toDoubleOrNull() - set(value) { - maxInternal = value?.toString() - } - private var stepInternal by AttributeDelegate("step") - var step: Double? - get() = stepInternal?.toDoubleOrNull() - set(value) { - stepInternal = value?.toString() - } - - init { - value = initValue - this.type = type - - var lastValue = value - val changeListener = object : EventListener { - override fun handleEvent(event: Event) { - val value = value - if (value != valueProperty.value || value != lastValue) { - lastValue = value - valueProperty.value = value - } - - (event as? KeyboardEvent)?.let { e -> - when (e.keyCode) { - 13, 27 -> blur() - } - } - } - } - - html.addEventListener("change", changeListener) - html.addEventListener("keyup", changeListener) - html.addEventListener("keypress", changeListener) - } -} - -enum class InputType(val html: String) { - TEXT("text"), - NUMBER("number"), - PASSWORD("password"); - - companion object { - fun find(html: String): InputType? = values().find { it.html == html } - } -} - -@KWebViewDsl -fun ViewCollection.inputView(text: String = "", init: InputView.() -> Unit = {}) = - InputView(InputType.TEXT, text).also(this::append).also(init) - -@KWebViewDsl -fun ViewCollection.inputView(text: ReadOnlyProperty, init: InputView.() -> Unit = {}) = - InputView(InputType.TEXT, text.value).also(this::append).also { it.bind(text) }.also(init) - -@KWebViewDsl -fun ViewCollection.inputView(text: Property, init: InputView.() -> Unit = {}) = - InputView(InputType.TEXT, text.value).also(this::append).also { it.bind(text) }.also(init) - -@KWebViewDsl -fun ViewCollection.inputView(text: ValidationProperty, init: InputView.() -> Unit = {}) = - InputView(InputType.TEXT, text.value).also(this::append).also { it.bind(text) }.also(init) - - -@KWebViewDsl -fun ViewCollection.inputView(type: InputType = InputType.TEXT, text: String = "", init: InputView.() -> Unit = {}) = - InputView(type, text).also(this::append).also(init) - -@KWebViewDsl -fun ViewCollection.inputView(type: InputType = InputType.TEXT, text: ReadOnlyProperty, init: InputView.() -> Unit = {}) = - InputView(type, text.value).also(this::append).also { it.bind(text) }.also(init) - -@KWebViewDsl -fun ViewCollection.inputView(type: InputType = InputType.TEXT, text: Property, init: InputView.() -> Unit = {}) = - InputView(type, text.value).also(this::append).also { it.bind(text) }.also(init) - -@KWebViewDsl -fun ViewCollection.inputView(type: InputType = InputType.TEXT, text: ValidationProperty, init: InputView.() -> Unit = {}) = - InputView(type, text.value).also(this::append).also { it.bind(text) }.also(init) diff --git a/src/jsMain/kotlin/de/westermann/kwebview/components/Label.kt b/src/jsMain/kotlin/de/westermann/kwebview/components/Label.kt deleted file mode 100644 index c2985ea..0000000 --- a/src/jsMain/kotlin/de/westermann/kwebview/components/Label.kt +++ /dev/null @@ -1,51 +0,0 @@ -package de.westermann.kwebview.components - -import de.westermann.kobserve.Property -import de.westermann.kobserve.ReadOnlyProperty -import de.westermann.kobserve.basic.property -import de.westermann.kwebview.* -import org.w3c.dom.HTMLLabelElement - -/** - * Represents a html label element. - * - * @author lars - */ -class Label( - inputElement: ViewForLabel, - value: String = "" -) : View(createHtmlView()) { - - override val html = super.html as HTMLLabelElement - - fun bind(property: ReadOnlyProperty) { - textProperty.bind(property) - } - - fun unbind() { - textProperty.unbind() - } - - var text: String - get() = html.textContent ?: "" - set(value) { - html.textContent = value - textProperty.invalidate() - } - - val textProperty: Property = property(this::text) - - init { - text = value - - inputElement.setLabel(this) - } -} - -@KWebViewDsl -fun ViewCollection.label(inputElement: ViewForLabel, text: String = "", init: Label.() -> Unit = {}) = - Label(inputElement, text).also(this::append).also(init) - -@KWebViewDsl -fun ViewCollection.label(inputElement: ViewForLabel, text: ReadOnlyProperty, init: Label.() -> Unit = {}) = - Label(inputElement, text.value).also(this::append).also { it.bind(text) }.also(init) diff --git a/src/jsMain/kotlin/de/westermann/kwebview/components/Link.kt b/src/jsMain/kotlin/de/westermann/kwebview/components/Link.kt deleted file mode 100644 index 014a6c9..0000000 --- a/src/jsMain/kotlin/de/westermann/kwebview/components/Link.kt +++ /dev/null @@ -1,44 +0,0 @@ -package de.westermann.kwebview.components - -import de.westermann.kwebview.KWebViewDsl -import de.westermann.kwebview.View -import de.westermann.kwebview.ViewCollection -import de.westermann.kwebview.createHtmlView -import org.w3c.dom.HTMLAnchorElement - -/** - * Represents a html span element. - * - * @author lars - */ -class Link(target: String) : ViewCollection(createHtmlView("a")) { - - override val html = super.html as HTMLAnchorElement - - var text: String? - get() = html.textContent - set(value) { - html.textContent = value - } - - var target: String - get() = html.href - set(value) { - html.href = value - } - - init { - this.target = target - } -} - -@KWebViewDsl -fun ViewCollection.link(target: String, text: String? = null, init: Link.() -> Unit = {}): Link { - val view = Link(target) - if (text != null) { - view.text = text - } - append(view) - init(view) - return view -} diff --git a/src/jsMain/kotlin/de/westermann/kwebview/components/OptionView.kt b/src/jsMain/kotlin/de/westermann/kwebview/components/OptionView.kt deleted file mode 100644 index 64a5bc1..0000000 --- a/src/jsMain/kotlin/de/westermann/kwebview/components/OptionView.kt +++ /dev/null @@ -1,32 +0,0 @@ -package de.westermann.kwebview.components - -import de.westermann.kwebview.View -import de.westermann.kwebview.createHtmlView -import org.w3c.dom.HTMLOptionElement - -class OptionView(val value: T) : View(createHtmlView()) { - - override val html = super.html as HTMLOptionElement - - var htmlValue: String - get() = html.value - set(value) { - html.value = value - } - - var text: String - get() = html.text - set(value) { - html.text = value - } - - val index: Int - get() = html.index - - var selected: Boolean - get() = html.selected - set(value) { - html.selected = value - } - -} \ No newline at end of file diff --git a/src/jsMain/kotlin/de/westermann/kwebview/components/SelectView.kt b/src/jsMain/kotlin/de/westermann/kwebview/components/SelectView.kt deleted file mode 100644 index d1fa0f1..0000000 --- a/src/jsMain/kotlin/de/westermann/kwebview/components/SelectView.kt +++ /dev/null @@ -1,112 +0,0 @@ -package de.westermann.kwebview.components - -import de.westermann.kobserve.Property -import de.westermann.kobserve.ReadOnlyProperty -import de.westermann.kobserve.basic.property -import de.westermann.kwebview.AttributeDelegate -import de.westermann.kwebview.KWebViewDsl -import de.westermann.kwebview.ViewCollection -import de.westermann.kwebview.createHtmlView -import org.w3c.dom.HTMLSelectElement -import org.w3c.dom.events.Event -import org.w3c.dom.events.EventListener - -class SelectView( - dataSet: List, - private val initValue: T, - val transform: (T) -> String = { it.toString() } -) : ViewCollection>(createHtmlView()) { - - override val html = super.html as HTMLSelectElement - - fun bind(property: ReadOnlyProperty) { - valueProperty.bind(property) - readonly = true - } - - fun bind(property: Property) { - valueProperty.bindBidirectional(property) - } - - fun unbind() { - valueProperty.unbind() - } - - var dataSet: List = emptyList() - set(value) { - field = value - clear() - - value.forEachIndexed { index, v -> - +OptionView(v).also { option -> - option.text = transform(v) - option.htmlValue = index.toString() - } - } - } - - var index: Int - get() = html.selectedIndex - set(value) { - val invalidate = html.selectedIndex != value - html.selectedIndex = value - if (invalidate) { - valueProperty.invalidate() - } - } - - var value: T - get() = dataSet.getOrNull(index) ?: initValue - set(value) { - index = dataSet.indexOf(value) - } - val valueProperty = property(this::value) - - private var readonlyInternal by AttributeDelegate("readonly") - var readonly: Boolean - get() = readonlyInternal != null - set(value) { - readonlyInternal = if (value) "readonly" else null - } - - var tabindex by AttributeDelegate() - fun preventTabStop() { - tabindex = "-1" - } - - init { - this.dataSet = dataSet - this.value = initValue - - html.addEventListener("change", object : EventListener { - override fun handleEvent(event: Event) { - valueProperty.invalidate() - } - }) - } -} - -@KWebViewDsl -fun ViewCollection>.selectView(dataSet: List, initValue: T, transform: (T) -> String = { it.toString() }, init: SelectView.() -> Unit = {}) = - SelectView(dataSet, initValue, transform).also(this::append).also(init) - -@KWebViewDsl -fun ViewCollection>.selectView(dataSet: List, property: ReadOnlyProperty, transform: (T) -> String = { it.toString() }, init: SelectView.() -> Unit = {}) = - SelectView(dataSet, property.value, transform).apply { bind(property) }.also(this::append).also(init) - -@KWebViewDsl -fun ViewCollection>.selectView(dataSet: List, property: Property, transform: (T) -> String = { it.toString() }, init: SelectView.() -> Unit = {}) = - SelectView(dataSet, property.value, transform).apply { bind(property) }.also(this::append).also(init) - - -@KWebViewDsl -inline fun > ViewCollection>.selectView(initValue: T, noinline transform: (T) -> String = { it.toString() }, init: SelectView.() -> Unit = {}) = - SelectView(enumValues().toList(), initValue, transform).also(this::append).also(init) - -@KWebViewDsl -inline fun > ViewCollection>.selectView(property: ReadOnlyProperty, noinline transform: (T) -> String = { it.toString() }, init: SelectView.() -> Unit = {}) = - SelectView(enumValues().toList(), property.value, transform).apply { bind(property) }.also(this::append).also(init) - -@KWebViewDsl -inline fun > ViewCollection>.selectView(property: Property, noinline transform: (T) -> String = { it.toString() }, init: SelectView.() -> Unit = {}) = - SelectView(enumValues().toList(), property.value, transform).apply { bind(property) }.also(this::append).also(init) diff --git a/src/jsMain/kotlin/de/westermann/kwebview/components/Table.kt b/src/jsMain/kotlin/de/westermann/kwebview/components/Table.kt deleted file mode 100644 index 5346344..0000000 --- a/src/jsMain/kotlin/de/westermann/kwebview/components/Table.kt +++ /dev/null @@ -1,22 +0,0 @@ -package de.westermann.kwebview.components - -import de.westermann.kwebview.KWebViewDsl -import de.westermann.kwebview.View -import de.westermann.kwebview.ViewCollection -import de.westermann.kwebview.createHtmlView -import org.w3c.dom.HTMLTableElement - -class Table() : ViewCollection(createHtmlView()) { - override val html = super.html as HTMLTableElement -} - -@KWebViewDsl -fun ViewCollection.table(vararg classes: String, init: Table.() -> Unit = {}): Table { - val view = Table() - for (c in classes) { - view.classList += c - } - append(view) - init(view) - return view -} diff --git a/src/jsMain/kotlin/de/westermann/kwebview/components/TableCaption.kt b/src/jsMain/kotlin/de/westermann/kwebview/components/TableCaption.kt deleted file mode 100644 index ad3830f..0000000 --- a/src/jsMain/kotlin/de/westermann/kwebview/components/TableCaption.kt +++ /dev/null @@ -1,19 +0,0 @@ -package de.westermann.kwebview.components - -import de.westermann.kwebview.KWebViewDsl -import de.westermann.kwebview.View -import de.westermann.kwebview.ViewCollection -import de.westermann.kwebview.createHtmlView -import org.w3c.dom.HTMLTableCaptionElement - -class TableCaption() : ViewCollection(createHtmlView("caption")) { - override val html = super.html as HTMLTableCaptionElement -} - -@KWebViewDsl -fun ViewCollection.caption(init: TableCaption.() -> Unit = {}): TableCaption { - val view = TableCaption() - append(view) - init(view) - return view -} diff --git a/src/jsMain/kotlin/de/westermann/kwebview/components/TableCell.kt b/src/jsMain/kotlin/de/westermann/kwebview/components/TableCell.kt deleted file mode 100644 index de7c3df..0000000 --- a/src/jsMain/kotlin/de/westermann/kwebview/components/TableCell.kt +++ /dev/null @@ -1,41 +0,0 @@ -package de.westermann.kwebview.components - -import de.westermann.kwebview.* -import org.w3c.dom.HTMLTableCellElement - -class TableCell(val isHead: Boolean) : - ViewCollection(createHtmlView(if (isHead) "th" else "td")) { - override val html = super.html as HTMLTableCellElement - - private var colSpanInternal by AttributeDelegate("colspan") - var colSpan: Int? - get() = colSpanInternal?.toIntOrNull() - set(value) { - colSpanInternal = value?.toString() - } - - private var rowSpanInternal by AttributeDelegate("rowspan") - var rowSpan: Int? - get() = rowSpanInternal?.toIntOrNull() - set(value) { - rowSpanInternal = value?.toString() - } -} - -@KWebViewDsl -fun ViewCollection.cell(colSpan: Int? = null, init: TableCell.() -> Unit = {}): TableCell { - val view = TableCell(false) - view.colSpan = colSpan - append(view) - init(view) - return view -} - -@KWebViewDsl -fun ViewCollection.head(colSpan: Int? = null, init: TableCell.() -> Unit = {}): TableCell { - val view = TableCell(true) - view.colSpan = colSpan - append(view) - init(view) - return view -} diff --git a/src/jsMain/kotlin/de/westermann/kwebview/components/TableRow.kt b/src/jsMain/kotlin/de/westermann/kwebview/components/TableRow.kt deleted file mode 100644 index 8aab596..0000000 --- a/src/jsMain/kotlin/de/westermann/kwebview/components/TableRow.kt +++ /dev/null @@ -1,21 +0,0 @@ -package de.westermann.kwebview.components - -import de.westermann.kwebview.KWebViewDsl -import de.westermann.kwebview.ViewCollection -import de.westermann.kwebview.createHtmlView -import org.w3c.dom.HTMLTableRowElement - -class TableRow() : ViewCollection(createHtmlView("tr")) { - override val html = super.html as HTMLTableRowElement -} - -@KWebViewDsl -fun ViewCollection.row(vararg classes: String, init: TableRow.() -> Unit = {}): TableRow { - val view = TableRow() - for (c in classes) { - view.classList += c - } - append(view) - init(view) - return view -} diff --git a/src/jsMain/kotlin/de/westermann/kwebview/components/TableSection.kt b/src/jsMain/kotlin/de/westermann/kwebview/components/TableSection.kt deleted file mode 100644 index 2bb9fbd..0000000 --- a/src/jsMain/kotlin/de/westermann/kwebview/components/TableSection.kt +++ /dev/null @@ -1,40 +0,0 @@ -package de.westermann.kwebview.components - -import de.westermann.kwebview.KWebViewDsl -import de.westermann.kwebview.ViewCollection -import de.westermann.kwebview.createHtmlView -import org.w3c.dom.HTMLTableSectionElement - -class TableSection(val type: Type) : ViewCollection(createHtmlView(type.tagName)) { - override val html = super.html as HTMLTableSectionElement - - enum class Type(val tagName: String) { - THEAD("thead"), - TBODY("tbody"), - TFOOT("tfoot") - } -} - -@KWebViewDsl -fun ViewCollection.thead(init: TableSection.() -> Unit = {}): TableSection { - val view = TableSection(TableSection.Type.THEAD) - append(view) - init(view) - return view -} - -@KWebViewDsl -fun ViewCollection.tbody(init: TableSection.() -> Unit = {}): TableSection { - val view = TableSection(TableSection.Type.TBODY) - append(view) - init(view) - return view -} - -@KWebViewDsl -fun ViewCollection.tfoot(init: TableSection.() -> Unit = {}): TableSection { - val view = TableSection(TableSection.Type.TFOOT) - append(view) - init(view) - return view -} diff --git a/src/jsMain/kotlin/de/westermann/kwebview/components/TextView.kt b/src/jsMain/kotlin/de/westermann/kwebview/components/TextView.kt deleted file mode 100644 index 9228091..0000000 --- a/src/jsMain/kotlin/de/westermann/kwebview/components/TextView.kt +++ /dev/null @@ -1,51 +0,0 @@ -package de.westermann.kwebview.components - -import de.westermann.kobserve.Property -import de.westermann.kobserve.ReadOnlyProperty -import de.westermann.kobserve.basic.property -import de.westermann.kwebview.KWebViewDsl -import de.westermann.kwebview.View -import de.westermann.kwebview.ViewCollection -import de.westermann.kwebview.createHtmlView -import org.w3c.dom.HTMLSpanElement - -/** - * Represents a html span element. - * - * @author lars - */ -class TextView( - value: String = "" -) : View(createHtmlView()) { - - override val html = super.html as HTMLSpanElement - - fun bind(property: ReadOnlyProperty) { - textProperty.bind(property) - } - - fun unbind() { - textProperty.unbind() - } - - var text: String - get() = html.textContent ?: "" - set(value) { - html.textContent = value - textProperty.invalidate() - } - - val textProperty: Property = property(this::text) - - init { - text = value - } -} - -@KWebViewDsl -fun ViewCollection.textView(text: String = "", init: TextView.() -> Unit = {}) = - TextView(text).also(this::append).also(init) - -@KWebViewDsl -fun ViewCollection.textView(text: ReadOnlyProperty, init: TextView.() -> Unit = {}) = - TextView(text.value).also(this::append).also { it.bind(text) }.also(init) diff --git a/src/jsMain/kotlin/de/westermann/kwebview/extensions.kt b/src/jsMain/kotlin/de/westermann/kwebview/extensions.kt deleted file mode 100644 index 598b6bd..0000000 --- a/src/jsMain/kotlin/de/westermann/kwebview/extensions.kt +++ /dev/null @@ -1,79 +0,0 @@ -package de.westermann.kwebview - -import de.westermann.kobserve.EventHandler -import org.w3c.dom.DOMRect -import org.w3c.dom.HTMLElement -import org.w3c.dom.events.Event -import org.w3c.dom.events.EventListener -import org.w3c.dom.events.MouseEvent -import kotlin.browser.document -import kotlin.browser.window - -inline fun createHtmlView(tag: String? = null): V { - var tagName: String - if (tag != null) { - tagName = tag - } else { - tagName = V::class.js.name.toLowerCase().replace("html([a-z]*)element".toRegex(), "$1") - if (tagName.isBlank()) { - tagName = "div" - } - } - return document.createElement(tagName) as V -} - -fun String.toDashCase() = replace("([a-z])([A-Z])".toRegex(), "$1-$2").toLowerCase() - -inline fun EventHandler.bind(element: HTMLElement, event: String) { - val listener = object : EventListener { - override fun handleEvent(event: Event) { - this@bind.emit(event as T) - } - } - var isAttached = false - - val updateState = { - if (isEmpty() && isAttached) { - element.removeEventListener(event, listener) - isAttached = false - } else if (!isEmpty() && !isAttached) { - element.addEventListener(event, listener) - isAttached = true - } - } - - onAttach = updateState - onDetach = updateState - updateState() -} - -fun MouseEvent.toPoint(): Point = Point(clientX, clientY) -fun DOMRect.toDimension(): Dimension = Dimension(x, y, width, height) - -fun Number.format(digits: Int): String = this.asDynamic().toFixed(digits) - -external fun delete(p: dynamic): Boolean = definedExternally - -fun delete(thing: dynamic, key: String) { - delete(thing[key]) -} - -/** - * Apply current dom changes and recalculate all sizes. Executes the given block afterwards. - * - * @param timeout Optionally set a timeout for this call. Defaults to 1. - * @param block Callback - */ -fun async(timeout: Int = 1, block: () -> Unit) { - if (timeout < 1) throw IllegalArgumentException("Timeout must be greater than 0!") - window.setTimeout(block, timeout) -} - -fun interval(timeout: Int, block: () -> Unit): Int { - if (timeout < 1) throw IllegalArgumentException("Timeout must be greater than 0!") - return window.setInterval(block, timeout) -} - -fun clearInterval(id: Int) { - window.clearInterval(id) -} diff --git a/src/jsMain/kotlin/de/westermann/kwebview/i18n.kt b/src/jsMain/kotlin/de/westermann/kwebview/i18n.kt deleted file mode 100644 index 84b5b69..0000000 --- a/src/jsMain/kotlin/de/westermann/kwebview/i18n.kt +++ /dev/null @@ -1,147 +0,0 @@ -package de.westermann.kwebview - -import kotlin.browser.window - -@Suppress("ClassName") -object i18n { - private val data: MutableMap = mutableMapOf() - - private var fallbackLocale: Locale? = null - private var locale: Locale? = null - - fun register(id: String, name: String, path: String, fallback: Boolean = false) { - val locale = Locale(id, name, path, fallback) - - if (fallback) { - if (fallbackLocale != null) { - throw IllegalStateException("Fallback locale is already set!") - } - - fallbackLocale = locale - } - - data[id] = locale - - window.fetch(path).then { - it.json() - }.then { - locale.json = it - locale.isLoaded = true - }.catch { - throw it - } - } - - val isReady: Boolean - get() = data.values.all { it.isLoaded } - - fun load(id: String, block: () -> Unit) { - fun ready() { - if (isReady) { - locale = data[id] - block() - } else { - async(50) { ready() } - } - } - ready() - } - - private fun findKey(locale: Locale, key: String): dynamic { - val keys = key.split(".") - - var result = locale.json - for (k in keys) { - if (result.hasOwnProperty(k) as Boolean) { - result = result[k] - } else { - return undefined - } - } - - return result - } - - private fun findKey(key: String): dynamic { - var result: dynamic = undefined - - if (locale != null) { - result = findKey(locale!!, key) - } - - if (result == undefined) { - if (fallbackLocale != null) { - result = findKey(fallbackLocale!!, key) - } - } - - if (result == undefined) { - throw InternationalizationError("Cannot find key '$key'!") - } else { - return result - } - } - - private fun replace(str: String, arguments: List>): String { - val unnamed = arguments.filter { it.first == null }.map { it.second } - val named = arguments.mapNotNull { it.first?.to(it.second) } - - var s = str - - for ((key, replacement) in named) { - s = s.replace("{$key}", replacement?.toString() ?: "null") - } - - for (replacement in unnamed) { - if (s.contains("{}")) { - s = s.replaceFirst("{}", replacement?.toString() ?: "null") - } - } - - return s - } - - fun t(key: String, arguments: List>): String { - return replace(findKey(key).toString(), arguments) - } - - fun t(count: Number, key: String, arguments: List>): String { - val json = findKey(key) - if (count == 0 && json.hasOwnProperty("zero") as Boolean) { - return replace(json.zero.toString(), arguments) - } else if (count == 1 && json.hasOwnProperty("one") as Boolean) { - return replace(json.one.toString(), arguments) - } - - return if (json.hasOwnProperty("many") as Boolean) - replace(json.many.toString(), arguments) - else { - replace(json.toString(), arguments) - } - - } - - private class Locale( - val id: String, - val name: String, - val path: String, - val fallback: Boolean - ) { - var isLoaded = false - var json = js("{}") - } -} - -class InternationalizationError(message: String? = null) : Error(message) - -fun t(key: String) = i18n.t(key, emptyList()) - -fun t(key: String, vararg arguments: Any?) = i18n.t(key, arguments.map { null to it }) - -fun t(key: String, vararg arguments: Pair) = i18n.t(key, arguments.asList()) - -fun t(count: Number, key: String) = i18n.t(count, key, emptyList()) - -fun t(count: Number, key: String, vararg arguments: Any?) = i18n.t(count, key, arguments.map { null to it }) - -fun t(count: Number, key: String, vararg arguments: Pair) = i18n.t(count, key, arguments.asList()) diff --git a/src/jsMain/resources/external/font/Montserrat-Black.eot b/src/jsMain/resources/external/font/Montserrat-Black.eot deleted file mode 100644 index 3a5362d..0000000 Binary files a/src/jsMain/resources/external/font/Montserrat-Black.eot and /dev/null differ diff --git a/src/jsMain/resources/external/font/Montserrat-Black.woff b/src/jsMain/resources/external/font/Montserrat-Black.woff deleted file mode 100644 index 5c60ad0..0000000 Binary files a/src/jsMain/resources/external/font/Montserrat-Black.woff and /dev/null differ diff --git a/src/jsMain/resources/external/font/Montserrat-Black.woff2 b/src/jsMain/resources/external/font/Montserrat-Black.woff2 deleted file mode 100644 index 3ac8d46..0000000 Binary files a/src/jsMain/resources/external/font/Montserrat-Black.woff2 and /dev/null differ diff --git a/src/jsMain/resources/external/font/Montserrat-BlackItalic.eot b/src/jsMain/resources/external/font/Montserrat-BlackItalic.eot deleted file mode 100644 index 4b92a25..0000000 Binary files a/src/jsMain/resources/external/font/Montserrat-BlackItalic.eot and /dev/null differ diff --git a/src/jsMain/resources/external/font/Montserrat-BlackItalic.woff b/src/jsMain/resources/external/font/Montserrat-BlackItalic.woff deleted file mode 100644 index 0caeeb5..0000000 Binary files a/src/jsMain/resources/external/font/Montserrat-BlackItalic.woff and /dev/null differ diff --git a/src/jsMain/resources/external/font/Montserrat-BlackItalic.woff2 b/src/jsMain/resources/external/font/Montserrat-BlackItalic.woff2 deleted file mode 100644 index 1e5d135..0000000 Binary files a/src/jsMain/resources/external/font/Montserrat-BlackItalic.woff2 and /dev/null differ diff --git a/src/jsMain/resources/external/font/Montserrat-Bold.eot b/src/jsMain/resources/external/font/Montserrat-Bold.eot deleted file mode 100644 index 5ab4fd5..0000000 Binary files a/src/jsMain/resources/external/font/Montserrat-Bold.eot and /dev/null differ diff --git a/src/jsMain/resources/external/font/Montserrat-Bold.woff b/src/jsMain/resources/external/font/Montserrat-Bold.woff deleted file mode 100644 index aad827f..0000000 Binary files a/src/jsMain/resources/external/font/Montserrat-Bold.woff and /dev/null differ diff --git a/src/jsMain/resources/external/font/Montserrat-Bold.woff2 b/src/jsMain/resources/external/font/Montserrat-Bold.woff2 deleted file mode 100644 index ad25d26..0000000 Binary files a/src/jsMain/resources/external/font/Montserrat-Bold.woff2 and /dev/null differ diff --git a/src/jsMain/resources/external/font/Montserrat-BoldItalic.eot b/src/jsMain/resources/external/font/Montserrat-BoldItalic.eot deleted file mode 100644 index 5eeff1e..0000000 Binary files a/src/jsMain/resources/external/font/Montserrat-BoldItalic.eot and /dev/null differ diff --git a/src/jsMain/resources/external/font/Montserrat-BoldItalic.woff b/src/jsMain/resources/external/font/Montserrat-BoldItalic.woff deleted file mode 100644 index 875f5b5..0000000 Binary files a/src/jsMain/resources/external/font/Montserrat-BoldItalic.woff and /dev/null differ diff --git a/src/jsMain/resources/external/font/Montserrat-BoldItalic.woff2 b/src/jsMain/resources/external/font/Montserrat-BoldItalic.woff2 deleted file mode 100644 index f9a3d40..0000000 Binary files a/src/jsMain/resources/external/font/Montserrat-BoldItalic.woff2 and /dev/null differ diff --git a/src/jsMain/resources/external/font/Montserrat-ExtraBold.eot b/src/jsMain/resources/external/font/Montserrat-ExtraBold.eot deleted file mode 100644 index 203ed8e..0000000 Binary files a/src/jsMain/resources/external/font/Montserrat-ExtraBold.eot and /dev/null differ diff --git a/src/jsMain/resources/external/font/Montserrat-ExtraBold.woff b/src/jsMain/resources/external/font/Montserrat-ExtraBold.woff deleted file mode 100644 index 08c7e2e..0000000 Binary files a/src/jsMain/resources/external/font/Montserrat-ExtraBold.woff and /dev/null differ diff --git a/src/jsMain/resources/external/font/Montserrat-ExtraBold.woff2 b/src/jsMain/resources/external/font/Montserrat-ExtraBold.woff2 deleted file mode 100644 index e961597..0000000 Binary files a/src/jsMain/resources/external/font/Montserrat-ExtraBold.woff2 and /dev/null differ diff --git a/src/jsMain/resources/external/font/Montserrat-ExtraBoldItalic.eot b/src/jsMain/resources/external/font/Montserrat-ExtraBoldItalic.eot deleted file mode 100644 index 329171b..0000000 Binary files a/src/jsMain/resources/external/font/Montserrat-ExtraBoldItalic.eot and /dev/null differ diff --git a/src/jsMain/resources/external/font/Montserrat-ExtraBoldItalic.woff b/src/jsMain/resources/external/font/Montserrat-ExtraBoldItalic.woff deleted file mode 100644 index 935251b..0000000 Binary files a/src/jsMain/resources/external/font/Montserrat-ExtraBoldItalic.woff and /dev/null differ diff --git a/src/jsMain/resources/external/font/Montserrat-ExtraBoldItalic.woff2 b/src/jsMain/resources/external/font/Montserrat-ExtraBoldItalic.woff2 deleted file mode 100644 index 97b0e28..0000000 Binary files a/src/jsMain/resources/external/font/Montserrat-ExtraBoldItalic.woff2 and /dev/null differ diff --git a/src/jsMain/resources/external/font/Montserrat-ExtraLight.eot b/src/jsMain/resources/external/font/Montserrat-ExtraLight.eot deleted file mode 100644 index 1a9012b..0000000 Binary files a/src/jsMain/resources/external/font/Montserrat-ExtraLight.eot and /dev/null differ diff --git a/src/jsMain/resources/external/font/Montserrat-ExtraLight.woff b/src/jsMain/resources/external/font/Montserrat-ExtraLight.woff deleted file mode 100644 index a9a848e..0000000 Binary files a/src/jsMain/resources/external/font/Montserrat-ExtraLight.woff and /dev/null differ diff --git a/src/jsMain/resources/external/font/Montserrat-ExtraLight.woff2 b/src/jsMain/resources/external/font/Montserrat-ExtraLight.woff2 deleted file mode 100644 index 5fee343..0000000 Binary files a/src/jsMain/resources/external/font/Montserrat-ExtraLight.woff2 and /dev/null differ diff --git a/src/jsMain/resources/external/font/Montserrat-ExtraLightItalic.eot b/src/jsMain/resources/external/font/Montserrat-ExtraLightItalic.eot deleted file mode 100644 index 0c5369b..0000000 Binary files a/src/jsMain/resources/external/font/Montserrat-ExtraLightItalic.eot and /dev/null differ diff --git a/src/jsMain/resources/external/font/Montserrat-ExtraLightItalic.woff b/src/jsMain/resources/external/font/Montserrat-ExtraLightItalic.woff deleted file mode 100644 index 112038e..0000000 Binary files a/src/jsMain/resources/external/font/Montserrat-ExtraLightItalic.woff and /dev/null differ diff --git a/src/jsMain/resources/external/font/Montserrat-ExtraLightItalic.woff2 b/src/jsMain/resources/external/font/Montserrat-ExtraLightItalic.woff2 deleted file mode 100644 index 959479b..0000000 Binary files a/src/jsMain/resources/external/font/Montserrat-ExtraLightItalic.woff2 and /dev/null differ diff --git a/src/jsMain/resources/external/font/Montserrat-Italic.eot b/src/jsMain/resources/external/font/Montserrat-Italic.eot deleted file mode 100644 index 867a104..0000000 Binary files a/src/jsMain/resources/external/font/Montserrat-Italic.eot and /dev/null differ diff --git a/src/jsMain/resources/external/font/Montserrat-Italic.woff b/src/jsMain/resources/external/font/Montserrat-Italic.woff deleted file mode 100644 index 1c15293..0000000 Binary files a/src/jsMain/resources/external/font/Montserrat-Italic.woff and /dev/null differ diff --git a/src/jsMain/resources/external/font/Montserrat-Italic.woff2 b/src/jsMain/resources/external/font/Montserrat-Italic.woff2 deleted file mode 100644 index 8ccfb98..0000000 Binary files a/src/jsMain/resources/external/font/Montserrat-Italic.woff2 and /dev/null differ diff --git a/src/jsMain/resources/external/font/Montserrat-Light.eot b/src/jsMain/resources/external/font/Montserrat-Light.eot deleted file mode 100644 index 62d678e..0000000 Binary files a/src/jsMain/resources/external/font/Montserrat-Light.eot and /dev/null differ diff --git a/src/jsMain/resources/external/font/Montserrat-Light.woff b/src/jsMain/resources/external/font/Montserrat-Light.woff deleted file mode 100644 index 7aa52b2..0000000 Binary files a/src/jsMain/resources/external/font/Montserrat-Light.woff and /dev/null differ diff --git a/src/jsMain/resources/external/font/Montserrat-Light.woff2 b/src/jsMain/resources/external/font/Montserrat-Light.woff2 deleted file mode 100644 index 0b253c4..0000000 Binary files a/src/jsMain/resources/external/font/Montserrat-Light.woff2 and /dev/null differ diff --git a/src/jsMain/resources/external/font/Montserrat-LightItalic.eot b/src/jsMain/resources/external/font/Montserrat-LightItalic.eot deleted file mode 100644 index 9e70f97..0000000 Binary files a/src/jsMain/resources/external/font/Montserrat-LightItalic.eot and /dev/null differ diff --git a/src/jsMain/resources/external/font/Montserrat-LightItalic.woff b/src/jsMain/resources/external/font/Montserrat-LightItalic.woff deleted file mode 100644 index ef12fe2..0000000 Binary files a/src/jsMain/resources/external/font/Montserrat-LightItalic.woff and /dev/null differ diff --git a/src/jsMain/resources/external/font/Montserrat-LightItalic.woff2 b/src/jsMain/resources/external/font/Montserrat-LightItalic.woff2 deleted file mode 100644 index c4cc5a3..0000000 Binary files a/src/jsMain/resources/external/font/Montserrat-LightItalic.woff2 and /dev/null differ diff --git a/src/jsMain/resources/external/font/Montserrat-Medium.eot b/src/jsMain/resources/external/font/Montserrat-Medium.eot deleted file mode 100644 index abb0a84..0000000 Binary files a/src/jsMain/resources/external/font/Montserrat-Medium.eot and /dev/null differ diff --git a/src/jsMain/resources/external/font/Montserrat-Medium.woff b/src/jsMain/resources/external/font/Montserrat-Medium.woff deleted file mode 100644 index 2778c8b..0000000 Binary files a/src/jsMain/resources/external/font/Montserrat-Medium.woff and /dev/null differ diff --git a/src/jsMain/resources/external/font/Montserrat-Medium.woff2 b/src/jsMain/resources/external/font/Montserrat-Medium.woff2 deleted file mode 100644 index 80d6f58..0000000 Binary files a/src/jsMain/resources/external/font/Montserrat-Medium.woff2 and /dev/null differ diff --git a/src/jsMain/resources/external/font/Montserrat-MediumItalic.eot b/src/jsMain/resources/external/font/Montserrat-MediumItalic.eot deleted file mode 100644 index d7986e9..0000000 Binary files a/src/jsMain/resources/external/font/Montserrat-MediumItalic.eot and /dev/null differ diff --git a/src/jsMain/resources/external/font/Montserrat-MediumItalic.woff b/src/jsMain/resources/external/font/Montserrat-MediumItalic.woff deleted file mode 100644 index 7a2329f..0000000 Binary files a/src/jsMain/resources/external/font/Montserrat-MediumItalic.woff and /dev/null differ diff --git a/src/jsMain/resources/external/font/Montserrat-MediumItalic.woff2 b/src/jsMain/resources/external/font/Montserrat-MediumItalic.woff2 deleted file mode 100644 index a7f9cfd..0000000 Binary files a/src/jsMain/resources/external/font/Montserrat-MediumItalic.woff2 and /dev/null differ diff --git a/src/jsMain/resources/external/font/Montserrat-Regular.eot b/src/jsMain/resources/external/font/Montserrat-Regular.eot deleted file mode 100644 index d030e7f..0000000 Binary files a/src/jsMain/resources/external/font/Montserrat-Regular.eot and /dev/null differ diff --git a/src/jsMain/resources/external/font/Montserrat-Regular.woff b/src/jsMain/resources/external/font/Montserrat-Regular.woff deleted file mode 100644 index ebb48a9..0000000 Binary files a/src/jsMain/resources/external/font/Montserrat-Regular.woff and /dev/null differ diff --git a/src/jsMain/resources/external/font/Montserrat-Regular.woff2 b/src/jsMain/resources/external/font/Montserrat-Regular.woff2 deleted file mode 100644 index 3261a6a..0000000 Binary files a/src/jsMain/resources/external/font/Montserrat-Regular.woff2 and /dev/null differ diff --git a/src/jsMain/resources/external/font/Montserrat-SemiBold.eot b/src/jsMain/resources/external/font/Montserrat-SemiBold.eot deleted file mode 100644 index 92bdd9b..0000000 Binary files a/src/jsMain/resources/external/font/Montserrat-SemiBold.eot and /dev/null differ diff --git a/src/jsMain/resources/external/font/Montserrat-SemiBold.woff b/src/jsMain/resources/external/font/Montserrat-SemiBold.woff deleted file mode 100644 index 32904f5..0000000 Binary files a/src/jsMain/resources/external/font/Montserrat-SemiBold.woff and /dev/null differ diff --git a/src/jsMain/resources/external/font/Montserrat-SemiBold.woff2 b/src/jsMain/resources/external/font/Montserrat-SemiBold.woff2 deleted file mode 100644 index 0c9bc28..0000000 Binary files a/src/jsMain/resources/external/font/Montserrat-SemiBold.woff2 and /dev/null differ diff --git a/src/jsMain/resources/external/font/Montserrat-SemiBoldItalic.eot b/src/jsMain/resources/external/font/Montserrat-SemiBoldItalic.eot deleted file mode 100644 index 9caec26..0000000 Binary files a/src/jsMain/resources/external/font/Montserrat-SemiBoldItalic.eot and /dev/null differ diff --git a/src/jsMain/resources/external/font/Montserrat-SemiBoldItalic.woff b/src/jsMain/resources/external/font/Montserrat-SemiBoldItalic.woff deleted file mode 100644 index d990b52..0000000 Binary files a/src/jsMain/resources/external/font/Montserrat-SemiBoldItalic.woff and /dev/null differ diff --git a/src/jsMain/resources/external/font/Montserrat-SemiBoldItalic.woff2 b/src/jsMain/resources/external/font/Montserrat-SemiBoldItalic.woff2 deleted file mode 100644 index 4d597b3..0000000 Binary files a/src/jsMain/resources/external/font/Montserrat-SemiBoldItalic.woff2 and /dev/null differ diff --git a/src/jsMain/resources/external/font/Montserrat-Thin.eot b/src/jsMain/resources/external/font/Montserrat-Thin.eot deleted file mode 100644 index 125b165..0000000 Binary files a/src/jsMain/resources/external/font/Montserrat-Thin.eot and /dev/null differ diff --git a/src/jsMain/resources/external/font/Montserrat-Thin.woff b/src/jsMain/resources/external/font/Montserrat-Thin.woff deleted file mode 100644 index 43cffac..0000000 Binary files a/src/jsMain/resources/external/font/Montserrat-Thin.woff and /dev/null differ diff --git a/src/jsMain/resources/external/font/Montserrat-Thin.woff2 b/src/jsMain/resources/external/font/Montserrat-Thin.woff2 deleted file mode 100644 index ef8d0d5..0000000 Binary files a/src/jsMain/resources/external/font/Montserrat-Thin.woff2 and /dev/null differ diff --git a/src/jsMain/resources/external/font/Montserrat-ThinItalic.eot b/src/jsMain/resources/external/font/Montserrat-ThinItalic.eot deleted file mode 100644 index a53bd66..0000000 Binary files a/src/jsMain/resources/external/font/Montserrat-ThinItalic.eot and /dev/null differ diff --git a/src/jsMain/resources/external/font/Montserrat-ThinItalic.woff b/src/jsMain/resources/external/font/Montserrat-ThinItalic.woff deleted file mode 100644 index dd4a314..0000000 Binary files a/src/jsMain/resources/external/font/Montserrat-ThinItalic.woff and /dev/null differ diff --git a/src/jsMain/resources/external/font/Montserrat-ThinItalic.woff2 b/src/jsMain/resources/external/font/Montserrat-ThinItalic.woff2 deleted file mode 100644 index e5e9367..0000000 Binary files a/src/jsMain/resources/external/font/Montserrat-ThinItalic.woff2 and /dev/null differ diff --git a/src/jsMain/resources/external/font/Montserrat.css b/src/jsMain/resources/external/font/Montserrat.css deleted file mode 100644 index a52ef06..0000000 --- a/src/jsMain/resources/external/font/Montserrat.css +++ /dev/null @@ -1,399 +0,0 @@ -/** =================== MONTSERRAT =================== **/ - -/** Montserrat Thin **/ -@font-face { - font-family: "Montserrat"; - font-weight: 100; - font-style: normal; - src: url("Montserrat-Thin.eot"); - src: url("Montserrat-Thin.eot?#iefix") format('embedded-opentype'), - url("Montserrat-Thin.woff2") format("woff2"), - url("Montserrat-Thin.woff") format("woff"); -} - -/** Montserrat Thin-Italic **/ -@font-face { - font-family: "Montserrat"; - font-weight: 100; - font-style: italic; - src: url("Montserrat-ThinItalic.eot"); - src: url("Montserrat-ThinItalic.eot?#iefix") format('embedded-opentype'), - url("Montserrat-ThinItalic.woff2") format("woff2"), - url("Montserrat-ThinItalic.woff") format("woff"); -} - -/** Montserrat ExtraLight **/ -@font-face { - font-family: "Montserrat"; - font-weight: 200; - font-style: normal; - src: url("Montserrat-ExtraLight.eot"); - src: url("Montserrat-ExtraLight.eot?#iefix") format('embedded-opentype'), - url("Montserrat-ExtraLight.woff2") format("woff2"), - url("Montserrat-ExtraLight.woff") format("woff"); -} - -/** Montserrat ExtraLight-Italic **/ -@font-face { - font-family: "Montserrat"; - font-weight: 200; - font-style: italic; - src: url("Montserrat-ExtraLightItalic.eot"); - src: url("Montserrat-ExtraLightItalic.eot?#iefix") format('embedded-opentype'), - url("Montserrat-ExtraLightItalic.woff2") format("woff2"), - url("Montserrat-ExtraLightItalic.woff") format("woff"); -} - -/** Montserrat Light **/ -@font-face { - font-family: "Montserrat"; - font-weight: 300; - font-style: normal; - src: url("Montserrat-Light.eot"); - src: url("Montserrat-Light.eot?#iefix") format('embedded-opentype'), - url("Montserrat-Light.woff2") format("woff2"), - url("Montserrat-Light.woff") format("woff"); -} - -/** Montserrat Light-Italic **/ -@font-face { - font-family: "Montserrat"; - font-weight: 300; - font-style: italic; - src: url("Montserrat-LightItalic.eot"); - src: url("Montserrat-LightItalic.eot?#iefix") format('embedded-opentype'), - url("Montserrat-LightItalic.woff2") format("woff2"), - url("Montserrat-LightItalic.woff") format("woff"); -} - -/** Montserrat Regular **/ -@font-face { - font-family: "Montserrat"; - font-weight: 400; - font-style: normal; - src: url("Montserrat-Regular.eot"); - src: url("Montserrat-Regular.eot?#iefix") format('embedded-opentype'), - url("Montserrat-Regular.woff2") format("woff2"), - url("Montserrat-Regular.woff") format("woff"); -} - -/** Montserrat Regular-Italic **/ -@font-face { - font-family: "Montserrat"; - font-weight: 400; - font-style: italic; - src: url("Montserrat-Italic.eot"); - src: url("Montserrat-Italic.eot?#iefix") format('embedded-opentype'), - url("Montserrat-Italic.woff2") format("woff2"), - url("Montserrat-Italic.woff") format("woff"); -} - -/** Montserrat Medium **/ -@font-face { - font-family: "Montserrat"; - font-weight: 500; - font-style: normal; - src: url("Montserrat-Medium.eot"); - src: url("Montserrat-Medium.eot?#iefix") format('embedded-opentype'), - url("Montserrat-Medium.woff2") format("woff2"), - url("Montserrat-Medium.woff") format("woff"); -} - -/** Montserrat Medium-Italic **/ -@font-face { - font-family: "Montserrat"; - font-weight: 500; - font-style: italic; - src: url("Montserrat-MediumItalic.eot"); - src: url("Montserrat-MediumItalic.eot?#iefix") format('embedded-opentype'), - url("Montserrat-MediumItalic.woff2") format("woff2"), - url("Montserrat-MediumItalic.woff") format("woff"); -} - -/** Montserrat SemiBold **/ -@font-face { - font-family: "Montserrat"; - font-weight: 600; - font-style: normal; - src: url("Montserrat-SemiBold.eot"); - src: url("Montserrat-SemiBold.eot?#iefix") format('embedded-opentype'), - url("Montserrat-SemiBold.woff2") format("woff2"), - url("Montserrat-SemiBold.woff") format("woff"); -} - -/** Montserrat SemiBold-Italic **/ -@font-face { - font-family: "Montserrat"; - font-weight: 600; - font-style: italic; - src: url("Montserrat-SemiBoldItalic.eot"); - src: url("Montserrat-SemiBoldItalic.eot?#iefix") format('embedded-opentype'), - url("Montserrat-SemiBoldItalic.woff2") format("woff2"), - url("Montserrat-SemiBoldItalic.woff") format("woff"); -} - -/** Montserrat Bold **/ -@font-face { - font-family: "Montserrat"; - font-weight: 700; - font-style: normal; - src: url("Montserrat-Bold.eot"); - src: url("Montserrat-Bold.eot?#iefix") format('embedded-opentype'), - url("Montserrat-Bold.woff2") format("woff2"), - url("Montserrat-Bold.woff") format("woff"); -} - -/** Montserrat Bold-Italic **/ -@font-face { - font-family: "Montserrat"; - font-weight: 700; - font-style: italic; - src: url("Montserrat-BoldItalic.eot"); - src: url("Montserrat-BoldItalic.eot?#iefix") format('embedded-opentype'), - url("Montserrat-BoldItalic.woff2") format("woff2"), - url("Montserrat-BoldItalic.woff") format("woff"); -} - -/** Montserrat ExtraBold **/ -@font-face { - font-family: "Montserrat"; - font-weight: 800; - font-style: normal; - src: url("Montserrat-ExtraBold.eot"); - src: url("Montserrat-ExtraBold.eot?#iefix") format('embedded-opentype'), - url("Montserrat-ExtraBold.woff2") format("woff2"), - url("Montserrat-ExtraBold.woff") format("woff"); -} - -/** Montserrat ExtraBold-Italic **/ -@font-face { - font-family: "Montserrat"; - font-weight: 800; - font-style: italic; - src: url("Montserrat-ExtraBoldItalic.eot"); - src: url("Montserrat-ExtraBoldItalic.eot?#iefix") format('embedded-opentype'), - url("Montserrat-ExtraBoldItalic.woff2") format("woff2"), - url("Montserrat-ExtraBoldItalic.woff") format("woff"); -} - -/** Montserrat Black **/ -@font-face { - font-family: "Montserrat"; - font-weight: 900; - font-style: normal; - src: url("Montserrat-Black.eot"); - src: url("Montserrat-Black.eot?#iefix") format('embedded-opentype'), - url("Montserrat-Black.woff2") format("woff2"), - url("Montserrat-Black.woff") format("woff"); -} - -/** Montserrat Black-Italic **/ -@font-face { - font-family: "Montserrat"; - font-weight: 900; - font-style: italic; - src: url("Montserrat-BlackItalic.eot"); - src: url("Montserrat-BlackItalic.eot?#iefix") format('embedded-opentype'), - url("Montserrat-BlackItalic.woff2") format("woff2"), - url("Montserrat-BlackItalic.woff") format("woff"); -} - -/** =================== MONTSERRAT ALTERNATES =================== **/ - -/** Montserrat Alternates Thin **/ -@font-face { - font-family: "Montserrat Alternates"; - font-weight: 100; - font-style: normal; - src: url("MontserratAlternates-Thin.eot"); - src: url("MontserratAlternates-Thin.eot?#iefix") format('embedded-opentype'), - url("MontserratAlternates-Thin.woff2") format("woff2"), - url("MontserratAlternates-Thin.woff") format("woff"); -} - -/** Montserrat Alternates Thin-Italic **/ -@font-face { - font-family: "Montserrat Alternates"; - font-weight: 100; - font-style: italic; - src: url("MontserratAlternates-ThinItalic.eot"); - src: url("MontserratAlternates-ThinItalic.eot?#iefix") format('embedded-opentype'), - url("MontserratAlternates-ThinItalic.woff2") format("woff2"), - url("MontserratAlternates-ThinItalic.woff") format("woff"); -} - -/** Montserrat Alternates ExtraLight **/ -@font-face { - font-family: "Montserrat Alternates"; - font-weight: 200; - font-style: normal; - src: url("MontserratAlternates-ExtraLight.eot"); - src: url("MontserratAlternates-ExtraLight.eot?#iefix") format('embedded-opentype'), - url("MontserratAlternates-ExtraLight.woff2") format("woff2"), - url("MontserratAlternates-ExtraLight.woff") format("woff"); -} - -/** Montserrat Alternates ExtraLight-Italic **/ -@font-face { - font-family: "Montserrat Alternates"; - font-weight: 200; - font-style: italic; - src: url("MontserratAlternates-ExtraLightItalic.eot"); - src: url("MontserratAlternates-ExtraLightItalic.eot?#iefix") format('embedded-opentype'), - url("MontserratAlternates-ExtraLightItalic.woff2") format("woff2"), - url("MontserratAlternates-ExtraLightItalic.woff") format("woff"); -} - -/** Montserrat Alternates Light **/ -@font-face { - font-family: "Montserrat Alternates"; - font-weight: 300; - font-style: normal; - src: url("MontserratAlternates-Light.eot"); - src: url("MontserratAlternates-Light.eot?#iefix") format('embedded-opentype'), - url("MontserratAlternates-Light.woff2") format("woff2"), - url("MontserratAlternates-Light.woff") format("woff"); -} - -/** Montserrat Alternates Light-Italic **/ -@font-face { - font-family: "Montserrat Alternates"; - font-weight: 300; - font-style: italic; - src: url("MontserratAlternates-LightItalic.eot"); - src: url("MontserratAlternates-LightItalic.eot?#iefix") format('embedded-opentype'), - url("MontserratAlternates-LightItalic.woff2") format("woff2"), - url("MontserratAlternates-LightItalic.woff") format("woff"); -} - -/** Montserrat Alternates Regular **/ -@font-face { - font-family: "Montserrat Alternates"; - font-weight: 400; - font-style: normal; - src: url("MontserratAlternates-Regular.eot"); - src: url("MontserratAlternates-Regular.eot?#iefix") format('embedded-opentype'), - url("MontserratAlternates-Regular.woff2") format("woff2"), - url("MontserratAlternates-Regular.woff") format("woff"); -} - -/** Montserrat Alternates Regular-Italic **/ -@font-face { - font-family: "Montserrat Alternates"; - font-weight: 400; - font-style: italic; - src: url("MontserratAlternates-Italic.eot"); - src: url("MontserratAlternates-Italic.eot?#iefix") format('embedded-opentype'), - url("MontserratAlternates-Italic.woff2") format("woff2"), - url("MontserratAlternates-Italic.woff") format("woff"); -} - -/** Montserrat Alternates Medium **/ -@font-face { - font-family: "Montserrat Alternates"; - font-weight: 500; - font-style: normal; - src: url("MontserratAlternates-Medium.eot"); - src: url("MontserratAlternates-Medium.eot?#iefix") format('embedded-opentype'), - url("MontserratAlternates-Medium.woff2") format("woff2"), - url("MontserratAlternates-Medium.woff") format("woff"); -} - -/** Montserrat Alternates Medium-Italic **/ -@font-face { - font-family: "Montserrat Alternates"; - font-weight: 500; - font-style: italic; - src: url("MontserratAlternates-MediumItalic.eot"); - src: url("MontserratAlternates-MediumItalic.eot?#iefix") format('embedded-opentype'), - url("MontserratAlternates-MediumItalic.woff2") format("woff2"), - url("MontserratAlternates-MediumItalic.woff") format("woff"); -} - -/** Montserrat Alternates SemiBold **/ -@font-face { - font-family: "Montserrat Alternates"; - font-weight: 600; - font-style: normal; - src: url("MontserratAlternates-SemiBold.eot"); - src: url("MontserratAlternates-SemiBold.eot?#iefix") format('embedded-opentype'), - url("MontserratAlternates-SemiBold.woff2") format("woff2"), - url("MontserratAlternates-SemiBold.woff") format("woff"); -} - -/** Montserrat Alternates SemiBold-Italic **/ -@font-face { - font-family: "Montserrat Alternates"; - font-weight: 600; - font-style: italic; - src: url("MontserratAlternates-SemiBoldItalic.eot"); - src: url("MontserratAlternates-SemiBoldItalic.eot?#iefix") format('embedded-opentype'), - url("MontserratAlternates-SemiBoldItalic.woff2") format("woff2"), - url("MontserratAlternates-SemiBoldItalic.woff") format("woff"); -} - -/** Montserrat Alternates Bold **/ -@font-face { - font-family: "Montserrat Alternates"; - font-weight: 700; - font-style: normal; - src: url("MontserratAlternates-Bold.eot"); - src: url("MontserratAlternates-Bold.eot?#iefix") format('embedded-opentype'), - url("MontserratAlternates-Bold.woff2") format("woff2"), - url("MontserratAlternates-Bold.woff") format("woff"); -} - -/** Montserrat Alternates Bold-Italic **/ -@font-face { - font-family: "Montserrat Alternates"; - font-weight: 700; - font-style: italic; - src: url("MontserratAlternates-BoldItalic.eot"); - src: url("MontserratAlternates-BoldItalic.eot?#iefix") format('embedded-opentype'), - url("MontserratAlternates-BoldItalic.woff2") format("woff2"), - url("MontserratAlternates-BoldItalic.woff") format("woff"); -} - -/** Montserrat Alternates ExtraBold **/ -@font-face { - font-family: "Montserrat Alternates"; - font-weight: 800; - font-style: normal; - src: url("MontserratAlternates-ExtraBold.eot"); - src: url("MontserratAlternates-ExtraBold.eot?#iefix") format('embedded-opentype'), - url("MontserratAlternates-ExtraBold.woff2") format("woff2"), - url("MontserratAlternates-ExtraBold.woff") format("woff"); -} - -/** Montserrat Alternates ExtraBold-Italic **/ -@font-face { - font-family: "Montserrat Alternates"; - font-weight: 800; - font-style: italic; - src: url("MontserratAlternates-ExtraBoldItalic.eot"); - src: url("MontserratAlternates-ExtraBoldItalic.eot?#iefix") format('embedded-opentype'), - url("MontserratAlternates-ExtraBoldItalic.woff2") format("woff2"), - url("MontserratAlternates-ExtraBoldItalic.woff") format("woff"); -} - -/** Montserrat Alternates Black **/ -@font-face { - font-family: "Montserrat Alternates"; - font-weight: 900; - font-style: normal; - src: url("MontserratAlternates-Black.eot"); - src: url("MontserratAlternates-Black.eot?#iefix") format('embedded-opentype'), - url("MontserratAlternates-Black.woff2") format("woff2"), - url("MontserratAlternates-Black.woff") format("woff"); -} - -/** Montserrat Alternates Black-Italic **/ -@font-face { - font-family: "Montserrat"; - font-weight: 900; - font-style: italic; - src: url("MontserratAlternates-BlackItalic.eot"); - src: url("MontserratAlternates-BlackItalic.eot?#iefix") format('embedded-opentype'), - url("MontserratAlternates-BlackItalic.woff2") format("woff2"), - url("MontserratAlternates-BlackItalic.woff") format("woff"); -} \ No newline at end of file diff --git a/src/jsMain/resources/external/font/MontserratAlternates-Black.eot b/src/jsMain/resources/external/font/MontserratAlternates-Black.eot deleted file mode 100644 index fc23ac4..0000000 Binary files a/src/jsMain/resources/external/font/MontserratAlternates-Black.eot and /dev/null differ diff --git a/src/jsMain/resources/external/font/MontserratAlternates-Black.woff b/src/jsMain/resources/external/font/MontserratAlternates-Black.woff deleted file mode 100644 index 11a3ce6..0000000 Binary files a/src/jsMain/resources/external/font/MontserratAlternates-Black.woff and /dev/null differ diff --git a/src/jsMain/resources/external/font/MontserratAlternates-Black.woff2 b/src/jsMain/resources/external/font/MontserratAlternates-Black.woff2 deleted file mode 100644 index 235a3c8..0000000 Binary files a/src/jsMain/resources/external/font/MontserratAlternates-Black.woff2 and /dev/null differ diff --git a/src/jsMain/resources/external/font/MontserratAlternates-BlackItalic.eot b/src/jsMain/resources/external/font/MontserratAlternates-BlackItalic.eot deleted file mode 100644 index a965308..0000000 Binary files a/src/jsMain/resources/external/font/MontserratAlternates-BlackItalic.eot and /dev/null differ diff --git a/src/jsMain/resources/external/font/MontserratAlternates-BlackItalic.woff b/src/jsMain/resources/external/font/MontserratAlternates-BlackItalic.woff deleted file mode 100644 index a2ddfd3..0000000 Binary files a/src/jsMain/resources/external/font/MontserratAlternates-BlackItalic.woff and /dev/null differ diff --git a/src/jsMain/resources/external/font/MontserratAlternates-BlackItalic.woff2 b/src/jsMain/resources/external/font/MontserratAlternates-BlackItalic.woff2 deleted file mode 100644 index a8004a1..0000000 Binary files a/src/jsMain/resources/external/font/MontserratAlternates-BlackItalic.woff2 and /dev/null differ diff --git a/src/jsMain/resources/external/font/MontserratAlternates-Bold.eot b/src/jsMain/resources/external/font/MontserratAlternates-Bold.eot deleted file mode 100644 index f17c416..0000000 Binary files a/src/jsMain/resources/external/font/MontserratAlternates-Bold.eot and /dev/null differ diff --git a/src/jsMain/resources/external/font/MontserratAlternates-Bold.woff b/src/jsMain/resources/external/font/MontserratAlternates-Bold.woff deleted file mode 100644 index 9fc7e5e..0000000 Binary files a/src/jsMain/resources/external/font/MontserratAlternates-Bold.woff and /dev/null differ diff --git a/src/jsMain/resources/external/font/MontserratAlternates-Bold.woff2 b/src/jsMain/resources/external/font/MontserratAlternates-Bold.woff2 deleted file mode 100644 index 22ff691..0000000 Binary files a/src/jsMain/resources/external/font/MontserratAlternates-Bold.woff2 and /dev/null differ diff --git a/src/jsMain/resources/external/font/MontserratAlternates-BoldItalic.eot b/src/jsMain/resources/external/font/MontserratAlternates-BoldItalic.eot deleted file mode 100644 index 90cf559..0000000 Binary files a/src/jsMain/resources/external/font/MontserratAlternates-BoldItalic.eot and /dev/null differ diff --git a/src/jsMain/resources/external/font/MontserratAlternates-BoldItalic.woff b/src/jsMain/resources/external/font/MontserratAlternates-BoldItalic.woff deleted file mode 100644 index e1483bd..0000000 Binary files a/src/jsMain/resources/external/font/MontserratAlternates-BoldItalic.woff and /dev/null differ diff --git a/src/jsMain/resources/external/font/MontserratAlternates-BoldItalic.woff2 b/src/jsMain/resources/external/font/MontserratAlternates-BoldItalic.woff2 deleted file mode 100644 index bed052a..0000000 Binary files a/src/jsMain/resources/external/font/MontserratAlternates-BoldItalic.woff2 and /dev/null differ diff --git a/src/jsMain/resources/external/font/MontserratAlternates-ExtraBold.eot b/src/jsMain/resources/external/font/MontserratAlternates-ExtraBold.eot deleted file mode 100644 index 3b1d443..0000000 Binary files a/src/jsMain/resources/external/font/MontserratAlternates-ExtraBold.eot and /dev/null differ diff --git a/src/jsMain/resources/external/font/MontserratAlternates-ExtraBold.woff b/src/jsMain/resources/external/font/MontserratAlternates-ExtraBold.woff deleted file mode 100644 index f6a794d..0000000 Binary files a/src/jsMain/resources/external/font/MontserratAlternates-ExtraBold.woff and /dev/null differ diff --git a/src/jsMain/resources/external/font/MontserratAlternates-ExtraBold.woff2 b/src/jsMain/resources/external/font/MontserratAlternates-ExtraBold.woff2 deleted file mode 100644 index e2cd944..0000000 Binary files a/src/jsMain/resources/external/font/MontserratAlternates-ExtraBold.woff2 and /dev/null differ diff --git a/src/jsMain/resources/external/font/MontserratAlternates-ExtraBoldItalic.eot b/src/jsMain/resources/external/font/MontserratAlternates-ExtraBoldItalic.eot deleted file mode 100644 index 9af7c24..0000000 Binary files a/src/jsMain/resources/external/font/MontserratAlternates-ExtraBoldItalic.eot and /dev/null differ diff --git a/src/jsMain/resources/external/font/MontserratAlternates-ExtraBoldItalic.woff b/src/jsMain/resources/external/font/MontserratAlternates-ExtraBoldItalic.woff deleted file mode 100644 index 1403e27..0000000 Binary files a/src/jsMain/resources/external/font/MontserratAlternates-ExtraBoldItalic.woff and /dev/null differ diff --git a/src/jsMain/resources/external/font/MontserratAlternates-ExtraBoldItalic.woff2 b/src/jsMain/resources/external/font/MontserratAlternates-ExtraBoldItalic.woff2 deleted file mode 100644 index 979839f..0000000 Binary files a/src/jsMain/resources/external/font/MontserratAlternates-ExtraBoldItalic.woff2 and /dev/null differ diff --git a/src/jsMain/resources/external/font/MontserratAlternates-ExtraLight.eot b/src/jsMain/resources/external/font/MontserratAlternates-ExtraLight.eot deleted file mode 100644 index 345c60d..0000000 Binary files a/src/jsMain/resources/external/font/MontserratAlternates-ExtraLight.eot and /dev/null differ diff --git a/src/jsMain/resources/external/font/MontserratAlternates-ExtraLight.woff b/src/jsMain/resources/external/font/MontserratAlternates-ExtraLight.woff deleted file mode 100644 index 6c47d58..0000000 Binary files a/src/jsMain/resources/external/font/MontserratAlternates-ExtraLight.woff and /dev/null differ diff --git a/src/jsMain/resources/external/font/MontserratAlternates-ExtraLight.woff2 b/src/jsMain/resources/external/font/MontserratAlternates-ExtraLight.woff2 deleted file mode 100644 index 9fe8bb2..0000000 Binary files a/src/jsMain/resources/external/font/MontserratAlternates-ExtraLight.woff2 and /dev/null differ diff --git a/src/jsMain/resources/external/font/MontserratAlternates-ExtraLightItalic.eot b/src/jsMain/resources/external/font/MontserratAlternates-ExtraLightItalic.eot deleted file mode 100644 index 29b4c1f..0000000 Binary files a/src/jsMain/resources/external/font/MontserratAlternates-ExtraLightItalic.eot and /dev/null differ diff --git a/src/jsMain/resources/external/font/MontserratAlternates-ExtraLightItalic.woff b/src/jsMain/resources/external/font/MontserratAlternates-ExtraLightItalic.woff deleted file mode 100644 index 622cc9a..0000000 Binary files a/src/jsMain/resources/external/font/MontserratAlternates-ExtraLightItalic.woff and /dev/null differ diff --git a/src/jsMain/resources/external/font/MontserratAlternates-ExtraLightItalic.woff2 b/src/jsMain/resources/external/font/MontserratAlternates-ExtraLightItalic.woff2 deleted file mode 100644 index 2632c08..0000000 Binary files a/src/jsMain/resources/external/font/MontserratAlternates-ExtraLightItalic.woff2 and /dev/null differ diff --git a/src/jsMain/resources/external/font/MontserratAlternates-Italic.eot b/src/jsMain/resources/external/font/MontserratAlternates-Italic.eot deleted file mode 100644 index 6e8c22e..0000000 Binary files a/src/jsMain/resources/external/font/MontserratAlternates-Italic.eot and /dev/null differ diff --git a/src/jsMain/resources/external/font/MontserratAlternates-Italic.woff b/src/jsMain/resources/external/font/MontserratAlternates-Italic.woff deleted file mode 100644 index 65094d4..0000000 Binary files a/src/jsMain/resources/external/font/MontserratAlternates-Italic.woff and /dev/null differ diff --git a/src/jsMain/resources/external/font/MontserratAlternates-Italic.woff2 b/src/jsMain/resources/external/font/MontserratAlternates-Italic.woff2 deleted file mode 100644 index 40944d4..0000000 Binary files a/src/jsMain/resources/external/font/MontserratAlternates-Italic.woff2 and /dev/null differ diff --git a/src/jsMain/resources/external/font/MontserratAlternates-Light.eot b/src/jsMain/resources/external/font/MontserratAlternates-Light.eot deleted file mode 100644 index e999003..0000000 Binary files a/src/jsMain/resources/external/font/MontserratAlternates-Light.eot and /dev/null differ diff --git a/src/jsMain/resources/external/font/MontserratAlternates-Light.woff b/src/jsMain/resources/external/font/MontserratAlternates-Light.woff deleted file mode 100644 index 4a9a0d4..0000000 Binary files a/src/jsMain/resources/external/font/MontserratAlternates-Light.woff and /dev/null differ diff --git a/src/jsMain/resources/external/font/MontserratAlternates-Light.woff2 b/src/jsMain/resources/external/font/MontserratAlternates-Light.woff2 deleted file mode 100644 index c7ef715..0000000 Binary files a/src/jsMain/resources/external/font/MontserratAlternates-Light.woff2 and /dev/null differ diff --git a/src/jsMain/resources/external/font/MontserratAlternates-LightItalic.eot b/src/jsMain/resources/external/font/MontserratAlternates-LightItalic.eot deleted file mode 100644 index fd1b318..0000000 Binary files a/src/jsMain/resources/external/font/MontserratAlternates-LightItalic.eot and /dev/null differ diff --git a/src/jsMain/resources/external/font/MontserratAlternates-LightItalic.woff b/src/jsMain/resources/external/font/MontserratAlternates-LightItalic.woff deleted file mode 100644 index 22f432f..0000000 Binary files a/src/jsMain/resources/external/font/MontserratAlternates-LightItalic.woff and /dev/null differ diff --git a/src/jsMain/resources/external/font/MontserratAlternates-LightItalic.woff2 b/src/jsMain/resources/external/font/MontserratAlternates-LightItalic.woff2 deleted file mode 100644 index 9f3b5d0..0000000 Binary files a/src/jsMain/resources/external/font/MontserratAlternates-LightItalic.woff2 and /dev/null differ diff --git a/src/jsMain/resources/external/font/MontserratAlternates-Medium.eot b/src/jsMain/resources/external/font/MontserratAlternates-Medium.eot deleted file mode 100644 index 4dd10f2..0000000 Binary files a/src/jsMain/resources/external/font/MontserratAlternates-Medium.eot and /dev/null differ diff --git a/src/jsMain/resources/external/font/MontserratAlternates-Medium.woff b/src/jsMain/resources/external/font/MontserratAlternates-Medium.woff deleted file mode 100644 index 92bd129..0000000 Binary files a/src/jsMain/resources/external/font/MontserratAlternates-Medium.woff and /dev/null differ diff --git a/src/jsMain/resources/external/font/MontserratAlternates-Medium.woff2 b/src/jsMain/resources/external/font/MontserratAlternates-Medium.woff2 deleted file mode 100644 index f8f0530..0000000 Binary files a/src/jsMain/resources/external/font/MontserratAlternates-Medium.woff2 and /dev/null differ diff --git a/src/jsMain/resources/external/font/MontserratAlternates-MediumItalic.eot b/src/jsMain/resources/external/font/MontserratAlternates-MediumItalic.eot deleted file mode 100644 index 9f33af7..0000000 Binary files a/src/jsMain/resources/external/font/MontserratAlternates-MediumItalic.eot and /dev/null differ diff --git a/src/jsMain/resources/external/font/MontserratAlternates-MediumItalic.woff b/src/jsMain/resources/external/font/MontserratAlternates-MediumItalic.woff deleted file mode 100644 index aefdeee..0000000 Binary files a/src/jsMain/resources/external/font/MontserratAlternates-MediumItalic.woff and /dev/null differ diff --git a/src/jsMain/resources/external/font/MontserratAlternates-MediumItalic.woff2 b/src/jsMain/resources/external/font/MontserratAlternates-MediumItalic.woff2 deleted file mode 100644 index 9775f42..0000000 Binary files a/src/jsMain/resources/external/font/MontserratAlternates-MediumItalic.woff2 and /dev/null differ diff --git a/src/jsMain/resources/external/font/MontserratAlternates-Regular.eot b/src/jsMain/resources/external/font/MontserratAlternates-Regular.eot deleted file mode 100644 index ad10b6b..0000000 Binary files a/src/jsMain/resources/external/font/MontserratAlternates-Regular.eot and /dev/null differ diff --git a/src/jsMain/resources/external/font/MontserratAlternates-Regular.woff b/src/jsMain/resources/external/font/MontserratAlternates-Regular.woff deleted file mode 100644 index 3aaf1f7..0000000 Binary files a/src/jsMain/resources/external/font/MontserratAlternates-Regular.woff and /dev/null differ diff --git a/src/jsMain/resources/external/font/MontserratAlternates-Regular.woff2 b/src/jsMain/resources/external/font/MontserratAlternates-Regular.woff2 deleted file mode 100644 index f7d23ca..0000000 Binary files a/src/jsMain/resources/external/font/MontserratAlternates-Regular.woff2 and /dev/null differ diff --git a/src/jsMain/resources/external/font/MontserratAlternates-SemiBold.eot b/src/jsMain/resources/external/font/MontserratAlternates-SemiBold.eot deleted file mode 100644 index 13a121d..0000000 Binary files a/src/jsMain/resources/external/font/MontserratAlternates-SemiBold.eot and /dev/null differ diff --git a/src/jsMain/resources/external/font/MontserratAlternates-SemiBold.woff b/src/jsMain/resources/external/font/MontserratAlternates-SemiBold.woff deleted file mode 100644 index 35ba984..0000000 Binary files a/src/jsMain/resources/external/font/MontserratAlternates-SemiBold.woff and /dev/null differ diff --git a/src/jsMain/resources/external/font/MontserratAlternates-SemiBold.woff2 b/src/jsMain/resources/external/font/MontserratAlternates-SemiBold.woff2 deleted file mode 100644 index 80bf4c2..0000000 Binary files a/src/jsMain/resources/external/font/MontserratAlternates-SemiBold.woff2 and /dev/null differ diff --git a/src/jsMain/resources/external/font/MontserratAlternates-SemiBoldItalic.eot b/src/jsMain/resources/external/font/MontserratAlternates-SemiBoldItalic.eot deleted file mode 100644 index 799cae5..0000000 Binary files a/src/jsMain/resources/external/font/MontserratAlternates-SemiBoldItalic.eot and /dev/null differ diff --git a/src/jsMain/resources/external/font/MontserratAlternates-SemiBoldItalic.woff b/src/jsMain/resources/external/font/MontserratAlternates-SemiBoldItalic.woff deleted file mode 100644 index 39283e1..0000000 Binary files a/src/jsMain/resources/external/font/MontserratAlternates-SemiBoldItalic.woff and /dev/null differ diff --git a/src/jsMain/resources/external/font/MontserratAlternates-SemiBoldItalic.woff2 b/src/jsMain/resources/external/font/MontserratAlternates-SemiBoldItalic.woff2 deleted file mode 100644 index 0bb26ae..0000000 Binary files a/src/jsMain/resources/external/font/MontserratAlternates-SemiBoldItalic.woff2 and /dev/null differ diff --git a/src/jsMain/resources/external/font/MontserratAlternates-Thin.eot b/src/jsMain/resources/external/font/MontserratAlternates-Thin.eot deleted file mode 100644 index d49ba52..0000000 Binary files a/src/jsMain/resources/external/font/MontserratAlternates-Thin.eot and /dev/null differ diff --git a/src/jsMain/resources/external/font/MontserratAlternates-Thin.woff b/src/jsMain/resources/external/font/MontserratAlternates-Thin.woff deleted file mode 100644 index 9f031c2..0000000 Binary files a/src/jsMain/resources/external/font/MontserratAlternates-Thin.woff and /dev/null differ diff --git a/src/jsMain/resources/external/font/MontserratAlternates-Thin.woff2 b/src/jsMain/resources/external/font/MontserratAlternates-Thin.woff2 deleted file mode 100644 index 23a80f9..0000000 Binary files a/src/jsMain/resources/external/font/MontserratAlternates-Thin.woff2 and /dev/null differ diff --git a/src/jsMain/resources/external/font/MontserratAlternates-ThinItalic.eot b/src/jsMain/resources/external/font/MontserratAlternates-ThinItalic.eot deleted file mode 100644 index 2fcd16d..0000000 Binary files a/src/jsMain/resources/external/font/MontserratAlternates-ThinItalic.eot and /dev/null differ diff --git a/src/jsMain/resources/external/font/MontserratAlternates-ThinItalic.woff b/src/jsMain/resources/external/font/MontserratAlternates-ThinItalic.woff deleted file mode 100644 index c601966..0000000 Binary files a/src/jsMain/resources/external/font/MontserratAlternates-ThinItalic.woff and /dev/null differ diff --git a/src/jsMain/resources/external/font/MontserratAlternates-ThinItalic.woff2 b/src/jsMain/resources/external/font/MontserratAlternates-ThinItalic.woff2 deleted file mode 100644 index d98a952..0000000 Binary files a/src/jsMain/resources/external/font/MontserratAlternates-ThinItalic.woff2 and /dev/null differ diff --git a/src/jsMain/resources/external/font/README.MD b/src/jsMain/resources/external/font/README.MD deleted file mode 100644 index 811ad40..0000000 --- a/src/jsMain/resources/external/font/README.MD +++ /dev/null @@ -1,35 +0,0 @@ -# The Montserrat Font Project -To use this font as a webfont, ```Montserrat.css``` is included. - -## How to use -### 1. @import -You can import the file into your stylesheet as follows: -```css -@import url("static/fonts/Montserrat/fonts/webfonts/Montserrat.css"); -``` - -**NOTE:** The directory where the stylesheet is placed. - -Then we can use it to style elements: -```css -body { - font-family: 'Montserrat', sans-serif; - font-weight: 400; -} -``` - -### 2. \ing a stylesheet -Similarly, you could link to the same asset as you would any other CSS filter, in the \ of the HTML document rather than in the CSS: -```html - -``` - -**NOTE:** The directory where the stylesheet is placed. - -Then we can use it to style elements: -```css -body { - font-family: 'Montserrat', sans-serif; - font-weight: 400; -} -``` \ No newline at end of file diff --git a/src/jsMain/resources/external/material-icons.css b/src/jsMain/resources/external/material-icons.css deleted file mode 100644 index c134ba5..0000000 --- a/src/jsMain/resources/external/material-icons.css +++ /dev/null @@ -1,24 +0,0 @@ -/* fallback */ -@font-face { - font-family: 'Material Icons'; - font-style: normal; - font-weight: 400; - src: local('Material Icons'), local('MaterialIcons-Regular'), url(material-icons.woff2) format('woff2'); -} - -.material-icons { - font-family: 'Material Icons' !important; - font-weight: normal; - font-style: normal; - letter-spacing: normal; - text-transform: none; - display: inline-block; - white-space: nowrap; - word-wrap: normal; - direction: ltr; - -moz-font-feature-settings: 'liga'; - -moz-osx-font-smoothing: grayscale; - font-feature-settings: 'liga'; - -webkit-font-smoothing: antialiased; - text-rendering: optimizeLegibility; -} diff --git a/src/jsMain/resources/external/material-icons.woff2 b/src/jsMain/resources/external/material-icons.woff2 deleted file mode 100644 index e916217..0000000 Binary files a/src/jsMain/resources/external/material-icons.woff2 and /dev/null differ diff --git a/src/jsMain/resources/require.min.js b/src/jsMain/resources/require.min.js deleted file mode 100644 index 0dcbf0e..0000000 --- a/src/jsMain/resources/require.min.js +++ /dev/null @@ -1,2 +0,0 @@ - -var requirejs,require,define;!function(global,setTimeout){function commentReplace(e,t){return t||""}function isFunction(e){return"[object Function]"===ostring.call(e)}function isArray(e){return"[object Array]"===ostring.call(e)}function each(e,t){if(e){var i;for(i=0;i-1&&(!e[i]||!t(e[i],i,e));i-=1);}}function hasProp(e,t){return hasOwn.call(e,t)}function getOwn(e,t){return hasProp(e,t)&&e[t]}function eachProp(e,t){var i;for(i in e)if(hasProp(e,i)&&t(e[i],i))break}function mixin(e,t,i,r){return t&&eachProp(t,function(t,n){!i&&hasProp(e,n)||(!r||"object"!=typeof t||!t||isArray(t)||isFunction(t)||t instanceof RegExp?e[n]=t:(e[n]||(e[n]={}),mixin(e[n],t,i,r)))}),e}function bind(e,t){return function(){return t.apply(e,arguments)}}function scripts(){return document.getElementsByTagName("script")}function defaultOnError(e){throw e}function getGlobal(e){if(!e)return e;var t=global;return each(e.split("."),function(e){t=t[e]}),t}function makeError(e,t,i,r){var n=new Error(t+"\nhttp://requirejs.org/docs/errors.html#"+e);return n.requireType=e,n.requireModules=r,i&&(n.originalError=i),n}function newContext(e){function t(e){var t,i;for(t=0;t0&&(e.splice(t-1,2),t-=2)}}function i(e,i,r){var n,o,a,s,u,c,d,p,f,l,h=i&&i.split("/"),m=y.map,g=m&&m["*"];if(e&&(c=(e=e.split("/")).length-1,y.nodeIdCompat&&jsSuffixRegExp.test(e[c])&&(e[c]=e[c].replace(jsSuffixRegExp,"")),"."===e[0].charAt(0)&&h&&(e=h.slice(0,h.length-1).concat(e)),t(e),e=e.join("/")),r&&m&&(h||g)){e:for(a=(o=e.split("/")).length;a>0;a-=1){if(u=o.slice(0,a).join("/"),h)for(s=h.length;s>0;s-=1)if((n=getOwn(m,h.slice(0,s).join("/")))&&(n=getOwn(n,u))){d=n,p=a;break e}!f&&g&&getOwn(g,u)&&(f=getOwn(g,u),l=a)}!d&&f&&(d=f,p=l),d&&(o.splice(0,p,d),e=o.join("/"))}return getOwn(y.pkgs,e)||e}function r(e){isBrowser&&each(scripts(),function(t){if(t.getAttribute("data-requiremodule")===e&&t.getAttribute("data-requirecontext")===q.contextName)return t.parentNode.removeChild(t),!0})}function n(e){var t=getOwn(y.paths,e);if(t&&isArray(t)&&t.length>1)return t.shift(),q.require.undef(e),q.makeRequire(null,{skipMap:!0})([e]),!0}function o(e){var t,i=e?e.indexOf("!"):-1;return i>-1&&(t=e.substring(0,i),e=e.substring(i+1,e.length)),[t,e]}function a(e,t,r,n){var a,s,u,c,d=null,p=t?t.name:null,f=e,l=!0,h="";return e||(l=!1,e="_@r"+(T+=1)),c=o(e),d=c[0],e=c[1],d&&(d=i(d,p,n),s=getOwn(j,d)),e&&(d?h=r?e:s&&s.normalize?s.normalize(e,function(e){return i(e,p,n)}):-1===e.indexOf("!")?i(e,p,n):e:(d=(c=o(h=i(e,p,n)))[0],h=c[1],r=!0,a=q.nameToUrl(h))),u=!d||s||r?"":"_unnormalized"+(A+=1),{prefix:d,name:h,parentMap:t,unnormalized:!!u,url:a,originalName:f,isDefine:l,id:(d?d+"!"+h:h)+u}}function s(e){var t=e.id,i=getOwn(S,t);return i||(i=S[t]=new q.Module(e)),i}function u(e,t,i){var r=e.id,n=getOwn(S,r);!hasProp(j,r)||n&&!n.defineEmitComplete?(n=s(e)).error&&"error"===t?i(n.error):n.on(t,i):"defined"===t&&i(j[r])}function c(e,t){var i=e.requireModules,r=!1;t?t(e):(each(i,function(t){var i=getOwn(S,t);i&&(i.error=e,i.events.error&&(r=!0,i.emit("error",e)))}),r||req.onError(e))}function d(){globalDefQueue.length&&(each(globalDefQueue,function(e){var t=e[0];"string"==typeof t&&(q.defQueueMap[t]=!0),O.push(e)}),globalDefQueue=[])}function p(e){delete S[e],delete k[e]}function f(e,t,i){var r=e.map.id;e.error?e.emit("error",e.error):(t[r]=!0,each(e.depMaps,function(r,n){var o=r.id,a=getOwn(S,o);!a||e.depMatched[n]||i[o]||(getOwn(t,o)?(e.defineDep(n,j[o]),e.check()):f(a,t,i))}),i[r]=!0)}function l(){var e,t,i=1e3*y.waitSeconds,o=i&&q.startTime+i<(new Date).getTime(),a=[],s=[],u=!1,d=!0;if(!x){if(x=!0,eachProp(k,function(e){var i=e.map,c=i.id;if(e.enabled&&(i.isDefine||s.push(e),!e.error))if(!e.inited&&o)n(c)?(t=!0,u=!0):(a.push(c),r(c));else if(!e.inited&&e.fetched&&i.isDefine&&(u=!0,!i.prefix))return d=!1}),o&&a.length)return e=makeError("timeout","Load timeout for modules: "+a,null,a),e.contextName=q.contextName,c(e);d&&each(s,function(e){f(e,{},{})}),o&&!t||!u||!isBrowser&&!isWebWorker||w||(w=setTimeout(function(){w=0,l()},50)),x=!1}}function h(e){hasProp(j,e[0])||s(a(e[0],null,!0)).init(e[1],e[2])}function m(e,t,i,r){e.detachEvent&&!isOpera?r&&e.detachEvent(r,t):e.removeEventListener(i,t,!1)}function g(e){var t=e.currentTarget||e.srcElement;return m(t,q.onScriptLoad,"load","onreadystatechange"),m(t,q.onScriptError,"error"),{node:t,id:t&&t.getAttribute("data-requiremodule")}}function v(){var e;for(d();O.length;){if(null===(e=O.shift())[0])return c(makeError("mismatch","Mismatched anonymous define() module: "+e[e.length-1]));h(e)}q.defQueueMap={}}var x,b,q,E,w,y={waitSeconds:7,baseUrl:"./",paths:{},bundles:{},pkgs:{},shim:{},config:{}},S={},k={},M={},O=[],j={},P={},R={},T=1,A=1;return E={require:function(e){return e.require?e.require:e.require=q.makeRequire(e.map)},exports:function(e){if(e.usingExports=!0,e.map.isDefine)return e.exports?j[e.map.id]=e.exports:e.exports=j[e.map.id]={}},module:function(e){return e.module?e.module:e.module={id:e.map.id,uri:e.map.url,config:function(){return getOwn(y.config,e.map.id)||{}},exports:e.exports||(e.exports={})}}},b=function(e){this.events=getOwn(M,e.id)||{},this.map=e,this.shim=getOwn(y.shim,e.id),this.depExports=[],this.depMaps=[],this.depMatched=[],this.pluginMaps={},this.depCount=0},b.prototype={init:function(e,t,i,r){r=r||{},this.inited||(this.factory=t,i?this.on("error",i):this.events.error&&(i=bind(this,function(e){this.emit("error",e)})),this.depMaps=e&&e.slice(0),this.errback=i,this.inited=!0,this.ignore=r.ignore,r.enabled||this.enabled?this.enable():this.check())},defineDep:function(e,t){this.depMatched[e]||(this.depMatched[e]=!0,this.depCount-=1,this.depExports[e]=t)},fetch:function(){if(!this.fetched){this.fetched=!0,q.startTime=(new Date).getTime();var e=this.map;if(!this.shim)return e.prefix?this.callPlugin():this.load();q.makeRequire(this.map,{enableBuildCallback:!0})(this.shim.deps||[],bind(this,function(){return e.prefix?this.callPlugin():this.load()}))}},load:function(){var e=this.map.url;P[e]||(P[e]=!0,q.load(this.map.id,e))},check:function(){if(this.enabled&&!this.enabling){var e,t,i=this.map.id,r=this.depExports,n=this.exports,o=this.factory;if(this.inited){if(this.error)this.emit("error",this.error);else if(!this.defining){if(this.defining=!0,this.depCount<1&&!this.defined){if(isFunction(o)){if(this.events.error&&this.map.isDefine||req.onError!==defaultOnError)try{n=q.execCb(i,o,r,n)}catch(t){e=t}else n=q.execCb(i,o,r,n);if(this.map.isDefine&&void 0===n&&((t=this.module)?n=t.exports:this.usingExports&&(n=this.exports)),e)return e.requireMap=this.map,e.requireModules=this.map.isDefine?[this.map.id]:null,e.requireType=this.map.isDefine?"define":"require",c(this.error=e)}else n=o;if(this.exports=n,this.map.isDefine&&!this.ignore&&(j[i]=n,req.onResourceLoad)){var a=[];each(this.depMaps,function(e){a.push(e.normalizedMap||e)}),req.onResourceLoad(q,this.map,a)}p(i),this.defined=!0}this.defining=!1,this.defined&&!this.defineEmitted&&(this.defineEmitted=!0,this.emit("defined",this.exports),this.defineEmitComplete=!0)}}else hasProp(q.defQueueMap,i)||this.fetch()}},callPlugin:function(){var e=this.map,t=e.id,r=a(e.prefix);this.depMaps.push(r),u(r,"defined",bind(this,function(r){var n,o,d,f=getOwn(R,this.map.id),l=this.map.name,h=this.map.parentMap?this.map.parentMap.name:null,m=q.makeRequire(e.parentMap,{enableBuildCallback:!0});return this.map.unnormalized?(r.normalize&&(l=r.normalize(l,function(e){return i(e,h,!0)})||""),o=a(e.prefix+"!"+l,this.map.parentMap,!0),u(o,"defined",bind(this,function(e){this.map.normalizedMap=o,this.init([],function(){return e},null,{enabled:!0,ignore:!0})})),void((d=getOwn(S,o.id))&&(this.depMaps.push(o),this.events.error&&d.on("error",bind(this,function(e){this.emit("error",e)})),d.enable()))):f?(this.map.url=q.nameToUrl(f),void this.load()):((n=bind(this,function(e){this.init([],function(){return e},null,{enabled:!0})})).error=bind(this,function(e){this.inited=!0,this.error=e,e.requireModules=[t],eachProp(S,function(e){0===e.map.id.indexOf(t+"_unnormalized")&&p(e.map.id)}),c(e)}),n.fromText=bind(this,function(i,r){var o=e.name,u=a(o),d=useInteractive;r&&(i=r),d&&(useInteractive=!1),s(u),hasProp(y.config,t)&&(y.config[o]=y.config[t]);try{req.exec(i)}catch(e){return c(makeError("fromtexteval","fromText eval for "+t+" failed: "+e,e,[t]))}d&&(useInteractive=!0),this.depMaps.push(u),q.completeLoad(o),m([o],n)}),void r.load(e.name,m,n,y))})),q.enable(r,this),this.pluginMaps[r.id]=r},enable:function(){k[this.map.id]=this,this.enabled=!0,this.enabling=!0,each(this.depMaps,bind(this,function(e,t){var i,r,n;if("string"==typeof e){if(e=a(e,this.map.isDefine?this.map:this.map.parentMap,!1,!this.skipMap),this.depMaps[t]=e,n=getOwn(E,e.id))return void(this.depExports[t]=n(this));this.depCount+=1,u(e,"defined",bind(this,function(e){this.undefed||(this.defineDep(t,e),this.check())})),this.errback?u(e,"error",bind(this,this.errback)):this.events.error&&u(e,"error",bind(this,function(e){this.emit("error",e)}))}i=e.id,r=S[i],hasProp(E,i)||!r||r.enabled||q.enable(e,this)})),eachProp(this.pluginMaps,bind(this,function(e){var t=getOwn(S,e.id);t&&!t.enabled&&q.enable(e,this)})),this.enabling=!1,this.check()},on:function(e,t){var i=this.events[e];i||(i=this.events[e]=[]),i.push(t)},emit:function(e,t){each(this.events[e],function(e){e(t)}),"error"===e&&delete this.events[e]}},q={config:y,contextName:e,registry:S,defined:j,urlFetched:P,defQueue:O,defQueueMap:{},Module:b,makeModuleMap:a,nextTick:req.nextTick,onError:c,configure:function(e){if(e.baseUrl&&"/"!==e.baseUrl.charAt(e.baseUrl.length-1)&&(e.baseUrl+="/"),"string"==typeof e.urlArgs){var t=e.urlArgs;e.urlArgs=function(e,i){return(-1===i.indexOf("?")?"?":"&")+t}}var i=y.shim,r={paths:!0,bundles:!0,config:!0,map:!0};eachProp(e,function(e,t){r[t]?(y[t]||(y[t]={}),mixin(y[t],e,!0,!0)):y[t]=e}),e.bundles&&eachProp(e.bundles,function(e,t){each(e,function(e){e!==t&&(R[e]=t)})}),e.shim&&(eachProp(e.shim,function(e,t){isArray(e)&&(e={deps:e}),!e.exports&&!e.init||e.exportsFn||(e.exportsFn=q.makeShimExports(e)),i[t]=e}),y.shim=i),e.packages&&each(e.packages,function(e){var t;t=(e="string"==typeof e?{name:e}:e).name,e.location&&(y.paths[t]=e.location),y.pkgs[t]=e.name+"/"+(e.main||"main").replace(currDirRegExp,"").replace(jsSuffixRegExp,"")}),eachProp(S,function(e,t){e.inited||e.map.unnormalized||(e.map=a(t,null,!0))}),(e.deps||e.callback)&&q.require(e.deps||[],e.callback)},makeShimExports:function(e){return function(){var t;return e.init&&(t=e.init.apply(global,arguments)),t||e.exports&&getGlobal(e.exports)}},makeRequire:function(t,n){function o(i,r,u){var d,p,f;return n.enableBuildCallback&&r&&isFunction(r)&&(r.__requireJsBuild=!0),"string"==typeof i?isFunction(r)?c(makeError("requireargs","Invalid require call"),u):t&&hasProp(E,i)?E[i](S[t.id]):req.get?req.get(q,i,t,o):(p=a(i,t,!1,!0),d=p.id,hasProp(j,d)?j[d]:c(makeError("notloaded",'Module name "'+d+'" has not been loaded yet for context: '+e+(t?"":". Use require([])")))):(v(),q.nextTick(function(){v(),(f=s(a(null,t))).skipMap=n.skipMap,f.init(i,r,u,{enabled:!0}),l()}),o)}return n=n||{},mixin(o,{isBrowser:isBrowser,toUrl:function(e){var r,n=e.lastIndexOf("."),o=e.split("/")[0],a="."===o||".."===o;return-1!==n&&(!a||n>1)&&(r=e.substring(n,e.length),e=e.substring(0,n)),q.nameToUrl(i(e,t&&t.id,!0),r,!0)},defined:function(e){return hasProp(j,a(e,t,!1,!0).id)},specified:function(e){return e=a(e,t,!1,!0).id,hasProp(j,e)||hasProp(S,e)}}),t||(o.undef=function(e){d();var i=a(e,t,!0),n=getOwn(S,e);n.undefed=!0,r(e),delete j[e],delete P[i.url],delete M[e],eachReverse(O,function(t,i){t[0]===e&&O.splice(i,1)}),delete q.defQueueMap[e],n&&(n.events.defined&&(M[e]=n.events),p(e))}),o},enable:function(e){getOwn(S,e.id)&&s(e).enable()},completeLoad:function(e){var t,i,r,o=getOwn(y.shim,e)||{},a=o.exports;for(d();O.length;){if(null===(i=O.shift())[0]){if(i[0]=e,t)break;t=!0}else i[0]===e&&(t=!0);h(i)}if(q.defQueueMap={},r=getOwn(S,e),!t&&!hasProp(j,e)&&r&&!r.inited){if(!(!y.enforceDefine||a&&getGlobal(a)))return n(e)?void 0:c(makeError("nodefine","No define call for "+e,null,[e]));h([e,o.deps||[],o.exportsFn])}l()},nameToUrl:function(e,t,i){var r,n,o,a,s,u,c,d=getOwn(y.pkgs,e);if(d&&(e=d),c=getOwn(R,e))return q.nameToUrl(c,t,i);if(req.jsExtRegExp.test(e))s=e+(t||"");else{for(r=y.paths,o=(n=e.split("/")).length;o>0;o-=1)if(a=n.slice(0,o).join("/"),u=getOwn(r,a)){isArray(u)&&(u=u[0]),n.splice(0,o,u);break}s=n.join("/"),s=("/"===(s+=t||(/^data\:|^blob\:|\?/.test(s)||i?"":".js")).charAt(0)||s.match(/^[\w\+\.\-]+:/)?"":y.baseUrl)+s}return y.urlArgs&&!/^blob\:/.test(s)?s+y.urlArgs(e,s):s},load:function(e,t){req.load(q,e,t)},execCb:function(e,t,i,r){return t.apply(r,i)},onScriptLoad:function(e){if("load"===e.type||readyRegExp.test((e.currentTarget||e.srcElement).readyState)){interactiveScript=null;var t=g(e);q.completeLoad(t.id)}},onScriptError:function(e){var t=g(e);if(!n(t.id)){var i=[];return eachProp(S,function(e,r){0!==r.indexOf("_@r")&&each(e.depMaps,function(e){if(e.id===t.id)return i.push(r),!0})}),c(makeError("scripterror",'Script error for "'+t.id+(i.length?'", needed by: '+i.join(", "):'"'),e,[t.id]))}}},q.require=q.makeRequire(),q}function getInteractiveScript(){return interactiveScript&&"interactive"===interactiveScript.readyState?interactiveScript:(eachReverse(scripts(),function(e){if("interactive"===e.readyState)return interactiveScript=e}),interactiveScript)}var req,s,head,baseElement,dataMain,src,interactiveScript,currentlyAddingScript,mainScript,subPath,version="2.3.4",commentRegExp=/\/\*[\s\S]*?\*\/|([^:"'=]|^)\/\/.*$/gm,cjsRequireRegExp=/[^.]\s*require\s*\(\s*["']([^'"\s]+)["']\s*\)/g,jsSuffixRegExp=/\.js$/,currDirRegExp=/^\.\//,op=Object.prototype,ostring=op.toString,hasOwn=op.hasOwnProperty,isBrowser=!("undefined"==typeof window||"undefined"==typeof navigator||!window.document),isWebWorker=!isBrowser&&"undefined"!=typeof importScripts,readyRegExp=isBrowser&&"PLAYSTATION 3"===navigator.platform?/^complete$/:/^(complete|loaded)$/,defContextName="_",isOpera="undefined"!=typeof opera&&"[object Opera]"===opera.toString(),contexts={},cfg={},globalDefQueue=[],useInteractive=!1;if(void 0===define){if(void 0!==requirejs){if(isFunction(requirejs))return;cfg=requirejs,requirejs=void 0}void 0===require||isFunction(require)||(cfg=require,require=void 0),req=requirejs=function(e,t,i,r){var n,o,a=defContextName;return isArray(e)||"string"==typeof e||(o=e,isArray(t)?(e=t,t=i,i=r):e=[]),o&&o.context&&(a=o.context),(n=getOwn(contexts,a))||(n=contexts[a]=req.s.newContext(a)),o&&n.configure(o),n.require(e,t,i)},req.config=function(e){return req(e)},req.nextTick=void 0!==setTimeout?function(e){setTimeout(e,4)}:function(e){e()},require||(require=req),req.version=version,req.jsExtRegExp=/^\/|:|\?|\.js$/,req.isBrowser=isBrowser,s=req.s={contexts:contexts,newContext:newContext},req({}),each(["toUrl","undef","defined","specified"],function(e){req[e]=function(){var t=contexts[defContextName];return t.require[e].apply(t,arguments)}}),isBrowser&&(head=s.head=document.getElementsByTagName("head")[0],(baseElement=document.getElementsByTagName("base")[0])&&(head=s.head=baseElement.parentNode)),req.onError=defaultOnError,req.createNode=function(e,t,i){var r=e.xhtml?document.createElementNS("http://www.w3.org/1999/xhtml","html:script"):document.createElement("script");return r.type=e.scriptType||"text/javascript",r.charset="utf-8",r.async=!0,r},req.load=function(e,t,i){var r,n=e&&e.config||{};if(isBrowser)return(r=req.createNode(n,t,i)).setAttribute("data-requirecontext",e.contextName),r.setAttribute("data-requiremodule",t),!r.attachEvent||r.attachEvent.toString&&r.attachEvent.toString().indexOf("[native code")<0||isOpera?(r.addEventListener("load",e.onScriptLoad,!1),r.addEventListener("error",e.onScriptError,!1)):(useInteractive=!0,r.attachEvent("onreadystatechange",e.onScriptLoad)),r.src=i,n.onNodeCreated&&n.onNodeCreated(r,n,t,i),currentlyAddingScript=r,baseElement?head.insertBefore(r,baseElement):head.appendChild(r),currentlyAddingScript=null,r;if(isWebWorker)try{setTimeout(function(){},0),importScripts(i),e.completeLoad(t)}catch(r){e.onError(makeError("importscripts","importScripts failed for "+t+" at "+i,r,[t]))}},isBrowser&&!cfg.skipDataMain&&eachReverse(scripts(),function(e){if(head||(head=e.parentNode),dataMain=e.getAttribute("data-main"))return mainScript=dataMain,cfg.baseUrl||-1!==mainScript.indexOf("!")||(src=mainScript.split("/"),mainScript=src.pop(),subPath=src.length?src.join("/")+"/":"./",cfg.baseUrl=subPath),mainScript=mainScript.replace(jsSuffixRegExp,""),req.jsExtRegExp.test(mainScript)&&(mainScript=dataMain),cfg.deps=cfg.deps?cfg.deps.concat(mainScript):[mainScript],!0}),define=function(e,t,i){var r,n;"string"!=typeof e&&(i=t,t=e,e=null),isArray(t)||(i=t,t=null),!t&&isFunction(i)&&(t=[],i.length&&(i.toString().replace(commentRegExp,commentReplace).replace(cjsRequireRegExp,function(e,i){t.push(i)}),t=(1===i.length?["require"]:["require","exports","module"]).concat(t))),useInteractive&&(r=currentlyAddingScript||getInteractiveScript())&&(e||(e=r.getAttribute("data-requiremodule")),n=contexts[r.getAttribute("data-requirecontext")]),n?(n.defQueue.push([e,t,i]),n.defQueueMap[e]=!0):globalDefQueue.push([e,t,i])},define.amd={jQuery:!0},req.exec=function(text){return eval(text)},req(cfg)}}(this,"undefined"==typeof setTimeout?void 0:setTimeout); diff --git a/src/jsMain/resources/style/style.scss b/src/jsMain/resources/style/style.scss deleted file mode 100644 index 1483aa4..0000000 --- a/src/jsMain/resources/style/style.scss +++ /dev/null @@ -1,427 +0,0 @@ -@mixin no-select() { - -webkit-touch-callout: none; - -webkit-user-select: none; - -khtml-user-select: none; - -moz-user-select: none; - -ms-user-select: none; - user-select: none; -} - -$background-primary-color: #fff; -$background-secondary-color: #fcfcfc; - -$text-primary-color: #333; - -$primary-color: #B11D33; -$primary-text-color: #fff; - -$error-color: #D55225; -$error-text-color: #fff; - -$border-color: #888; - -$transitionTime: 150ms; - -$bg-disabled-color: rgba($text-primary-color, .26); -$bg-enabled-color: rgba($primary-color, .5); -$lever-disabled-color: $background-primary-color; -$lever-enabled-color: $primary-color; - -body, html { - color: $text-primary-color; - background: $background-secondary-color; - - font-family: 'Montserrat', Roboto, Arial, sans-serif; - font-weight: 600; - - width: 100%; - height: 100%; - margin: 0; - padding: 0; -} - -a { - text-decoration: none; - outline: none; - color: $primary-color; - - &:hover { - text-decoration: none; - } - - &:active { - color: $primary-color; - } -} - -.container { - width: 100%; - margin: 0 auto; -} - -* { - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; - box-sizing: border-box; -} - -@media (min-width: 768px) { - .container { - width: 720px; - } -} - -@media (min-width: 992px) { - .container { - width: 960px; - } -} - -@media (min-width: 1200px) { - .container { - width: 1140px; - } -} - -.menu { - background-color: $background-secondary-color; - color: $text-primary-color; - width: 100%; - clear: both; - height: 6rem; - line-height: 6rem; - - a { - padding: 0 1rem; - color: $text-primary-color; - height: 100%; - display: inline-block; - font-family: "Bungee", sans-serif; - font-weight: normal; - font-size: 1.1rem; - position: relative; - text-transform: uppercase; - white-space: nowrap; - - &::after { - content: ''; - display: block; - position: absolute; - left: 1rem; - right: 1rem; - bottom: 1.8em; - height: 0.25rem; - - background: transparent; - transition: background-color $transitionTime; - } - - &.active::after { - background: $text-primary-color; - } - - &:hover { - background-color: rgba($primary-text-color, 0.1); - - &::after { - background: $primary-color; - } - } - } - - & ~ * { - content: ''; - clear: both; - } -} - -.menu-left { - float: left; -} - -.menu-right { - float: right; - - .menu-icon { - display: block; - cursor: default; - - padding: 0 1rem; - color: $text-primary-color; - height: 100%; - font-size: 2rem; - position: relative; - } - - .menu-content { - display: none; - position: absolute; - background-color: $background-secondary-color; - z-index: 1; - left: 1rem; - right: 1rem; - - a { - display: block; - line-height: 3rem; - &:after { - bottom: 0.2rem; - } - } - } - - &:hover { - .menu-content { - display: block; - } - } -} - -@media (min-width: 992px) { - .menu-right { - .menu-icon { - display: none; - } - - .menu-content { - display: block; - position: static; - background-color: transparent; - z-index: unset; - - a { - display: inline-block; - line-height: unset; - &:after { - bottom: 1.8em - } - } - } - } -} - -.main { - padding: 0 1rem; -} - -.table-layout-search { - float: left; - padding-bottom: 0.5rem !important; - - input { - padding-right: 4rem; - } - - .btn-search { - position: absolute; - top: 0; - height: calc(2.5rem + 2px); - line-height: 2.5rem; - right: -3px; - border-bottom-left-radius: 0; - border-top-left-radius: 0; - - margin-top: 1px; - margin-right: 2px; - } - - input:focus ~ .btn-search { - border-color: $primary-color; - border-width: 2px; - margin-top: 0; - height: calc(2.5rem + 4px); - margin-right: 1px; - } -} - -.table-layout-action { - float: right; - line-height: 2.5rem; -} - -.table-layout-table { - width: 100%; - border-spacing: 0; - border-collapse: collapse; - clear: both; - - th { - text-align: start; - } - - th, td { - padding: 0 0.6rem; - } - - .action { - text-align: center; - } - - tr { - border-top: solid 1px rgba($text-primary-color, 0.1); - - &:first-child { - background-color: rgba($text-primary-color, 0.06); - height: 2.5rem; - line-height: 2.5rem; - } - - &:not(:first-child) { - height: 2rem; - line-height: 2rem; - - &:hover { - background-color: rgba($text-primary-color, 0.06); - } - } - } -} - -.form-control { - border: solid 1px $border-color; - outline: none; - padding: 0 1rem; - line-height: 2.5rem; - width: 100%; - background-color: $background-primary-color; - border-radius: 0.2rem; - margin: 1px; - transition: border-color $transitionTime; - - &:focus { - border-color: $primary-color; - border-width: 2px; - margin: 0; - } -} - -.form-group { - padding-bottom: 1rem; - display: block; - position: relative; - clear: both; - - label { - display: block; - padding-bottom: 0.3rem; - padding-left: 0.2rem; - } -} - -.form-switch { - line-height: 24px; - - input { - position: absolute; - top: 0; - left: 0; - width: 0; - height: 0; - opacity: 0; - z-index: 0; - } - - label { - display: block; - padding: 0 0 0 44px; - cursor: pointer; - - &:before { - content: ''; - position: absolute; - top: 5px; - left: 0; - width: 36px; - height: 14px; - background-color: $bg-disabled-color; - border-radius: 14px; - z-index: 1; - transition: background-color 0.28s cubic-bezier(.4, 0, .2, 1); - } - - &:after { - content: ''; - position: absolute; - top: 2px; - left: 0; - width: 20px; - height: 20px; - background-color: $lever-disabled-color; - border-radius: 14px; - box-shadow: 0 2px 2px 0 rgba(0, 0, 0, .14), 0 3px 1px -2px rgba(0, 0, 0, .2), 0 1px 5px 0 rgba(0, 0, 0, .12); - z-index: 2; - transition: all 0.28s cubic-bezier(.4, 0, .2, 1); - transition-property: left, background-color; - } - - @include no-select - } - - input:checked + label { - &:before { - background-color: $bg-enabled-color; - } - - &:after { - left: 16px; - background-color: $lever-enabled-color; - } - } -} - -.form-switch-group { - padding: 0.5rem 0; -} - -.form-btn { - border: solid 1px $border-color; - outline: none; - padding: 0 1rem; - line-height: 2rem; - background-color: $background-primary-color; - color: $primary-color; - - display: inline-block; - margin-right: 0.6rem; - - border-radius: 0.2rem; - font-weight: 600; - text-transform: uppercase; - font-size: 0.9rem; - - transition: border-color $transitionTime, outline-color $transitionTime; - - cursor: pointer; - - &:focus, &:hover { - border-color: $primary-color; - outline-color: $primary-color; - } -} - -.btn-primary { - background-color: $primary-color; - color: $primary-text-color; - border-color: $primary-color; -} - -.btn-danger { - background-color: $error-color; - color: $error-text-color; - border-color: $error-color; -} - -button::-moz-focus-inner, input::-moz-focus-inner { - border: 0; -} - -form { - margin-bottom: 2rem; - width: 100%; -} - -@media (min-width: 768px) { - form { - width: 24rem; - } -} diff --git a/src/jvmMain/kotlin/de/kif/backend/Application.kt b/src/jvmMain/kotlin/de/kif/backend/Application.kt deleted file mode 100644 index 75caf31..0000000 --- a/src/jvmMain/kotlin/de/kif/backend/Application.kt +++ /dev/null @@ -1,154 +0,0 @@ -package de.kif.backend - -import de.kif.backend.database.Connection -import de.kif.backend.model.User -import de.kif.backend.route.* -import io.ktor.application.Application -import io.ktor.application.ApplicationCall -import io.ktor.application.install -import io.ktor.application.log -import io.ktor.auth.Authentication -import io.ktor.auth.FormAuthChallenge -import io.ktor.auth.UserPasswordCredential -import io.ktor.auth.form -import io.ktor.features.* -import io.ktor.http.content.files -import io.ktor.http.content.static -import io.ktor.locations.Location -import io.ktor.locations.Locations -import io.ktor.response.respondRedirect -import io.ktor.routing.routing -import io.ktor.sessions.* -import io.ktor.util.hex -import kotlinx.coroutines.launch - -data class PortalSession(val id: Int, val name: String) { - suspend fun getUser(call: ApplicationCall): User { - val user = User.find(name) - if (user == null || user.id != id) { - call.sessions.clear() - call.respondRedirect("/login?error") - throw IllegalAccessException() - } - return user - } -} - -@Location("/") -class LocationDashboard() - -@Location("/calendar") -class LocationCalendar() - -@Location("/login") -data class LocationLogin(val username: String = "", val password: String = "", val next: String = "/") - -@Location("/logout") -class LocationLogout() - -@Location("/account") -class LocationAccount() - -@Location("/user") -data class LocationUser(val search: String = "") { - @Location("/{id}") - data class Edit(val id: Int) - - @Location("/new") - class New() - - @Location("/{id}/delete") - data class Delete(val id: Int) -} - -@Location("/workgroup") -data class LocationWorkGroup(val search: String = "") { - @Location("/{id}") - data class Edit(val id: Int) - - @Location("/new") - class New() - - @Location("/{id}/delete") - data class Delete(val id: Int) -} - -@Location("/room") -data class LocationRoom(val search: String = "") { - @Location("/{id}") - data class Edit(val id: Int) - - @Location("/new") - class New() - - @Location("/{id}/delete") - data class Delete(val id: Int) -} - -@Location("/person") -data class LocationPerson(val search: String = "") { - @Location("/{id}") - data class Edit(val id: Int) - - @Location("/new") - class New() - - @Location("/{id}/delete") - data class Delete(val id: Int) -} - -fun Application.main() { - Connection.init() - - install(DefaultHeaders) - install(CallLogging) - install(ConditionalHeaders) - install(Compression) - install(DataConversion) - install(Locations) - - install(Authentication) { - form { - userParamName = LocationLogin::username.name - passwordParamName = LocationLogin::password.name - challenge = FormAuthChallenge.Redirect { _ -> - "/login?error" - } - validate { credential: UserPasswordCredential -> - val user = User.find(credential.name) ?: return@validate null - if (user.checkPassword(credential.password)) user else null - } - } - } - - val sessionKey = hex("1234567890abcdef") //TODO - install(Sessions) { - cookie("SESSION") { - transform(SessionTransportTransformerMessageAuthentication(sessionKey)) - } - } - - routing { - static("/static") { - files(Resources.directory) - } - - launch { - val firstStart = User.exists() - if (firstStart) { - log.info("Please create the first user and restart the server!") - setup() - } else { - dashboard() - calendar() - login() - account() - - workGroup() - room() - person() - user() - } - } - } -} \ No newline at end of file diff --git a/src/jvmMain/kotlin/de/kif/backend/Main.kt b/src/jvmMain/kotlin/de/kif/backend/Main.kt deleted file mode 100644 index 1d5a852..0000000 --- a/src/jvmMain/kotlin/de/kif/backend/Main.kt +++ /dev/null @@ -1,18 +0,0 @@ -package de.kif.backend - -import io.ktor.application.Application -import io.ktor.server.engine.embeddedServer -import io.ktor.server.netty.Netty - -object Main { - @Suppress("UnusedMainParameter") - @JvmStatic - fun main(args: Array) { - embeddedServer( - factory = Netty, - port = 8080, - host = "0.0.0.0", - module = Application::main - ).start(wait = true) - } -} diff --git a/src/jvmMain/kotlin/de/kif/backend/Resources.kt b/src/jvmMain/kotlin/de/kif/backend/Resources.kt deleted file mode 100644 index ca720f8..0000000 --- a/src/jvmMain/kotlin/de/kif/backend/Resources.kt +++ /dev/null @@ -1,73 +0,0 @@ -package de.kif.backend - -import mu.KotlinLogging -import java.io.File -import java.net.URI -import java.nio.file.* - -/** - * Manage static resource files of the ui - */ -object Resources { - - private val logger = KotlinLogging.logger {} - - /** - * Extract web directory from jar file. - * - * @return File that points the extracted web directory. - */ - private fun extractWebFolder(): File { - val destination: Path = Files.createTempDirectory("web") - - val classPath = "web" - val uri: URI = this::class.java.classLoader.getResource(classPath).toURI() - val fileSystem: FileSystem? - val src: Path = if (uri.scheme == "jar") { - fileSystem = FileSystems.newFileSystem(uri, mutableMapOf()) - fileSystem.getPath(classPath) - } else { - Paths.get(uri) - } - - Files.walk(src).forEach { path: Path -> - val name = path.toAbsolutePath().toString().let { name -> - name.drop(classPath.length + name.indexOf(classPath, ignoreCase = true)).dropWhile { - it == '/' || it == '\\' - } - } - if (Files.isDirectory(path)) { - Files.createDirectories(destination.resolve(name)) - } else { - Files.copy(path, destination.resolve(name)) - } - } - - return destination.toFile() - } - - /** - * File that points the web directory. - */ - val directory = File(".").absoluteFile.canonicalFile.let { currentDir -> - listOf( - "web", - "../web" - ).map { - File(currentDir, it) - }.firstOrNull { it.isDirectory }?.absoluteFile?.canonicalFile ?: extractWebFolder() - }.also { - logger.info { "Web directory: $it" } - } - - /** - * List of js modules to be included. - */ - val jsModules = directory.list().toList().filter { - it.endsWith(".js") && - !it.endsWith(".meta.js") && - !it.endsWith("-test.js") && - it != "require.min.js" - }.joinToString(", ") { "'${it.take(it.length - 3)}'" } - -} diff --git a/src/jvmMain/kotlin/de/kif/backend/database/Connection.kt b/src/jvmMain/kotlin/de/kif/backend/database/Connection.kt deleted file mode 100644 index c4ddb0c..0000000 --- a/src/jvmMain/kotlin/de/kif/backend/database/Connection.kt +++ /dev/null @@ -1,31 +0,0 @@ -package de.kif.backend.database - -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.withContext -import org.jetbrains.exposed.sql.Database -import org.jetbrains.exposed.sql.SchemaUtils -import org.jetbrains.exposed.sql.transactions.TransactionManager -import org.jetbrains.exposed.sql.transactions.transaction -import java.sql.Connection.TRANSACTION_SERIALIZABLE - - -object Connection { - fun init() { - Database.connect("jdbc:sqlite:portal.db", "org.sqlite.JDBC") - TransactionManager.manager.defaultIsolationLevel = TRANSACTION_SERIALIZABLE - - transaction { - SchemaUtils.create( - DbPerson, DbPersonConstraint, - DbTrack, DbWorkGroup, DbWorkGroupConstraint, - DbLeader, DbWorkGroupOrder, - DbRoom, DbTimeSlot, DbSchedule, - DbUser, DbUserPermission - ) - } - } -} - -suspend fun dbQuery(block: () -> T): T = withContext(Dispatchers.IO) { - transaction { block() } -} diff --git a/src/jvmMain/kotlin/de/kif/backend/database/Schema.kt b/src/jvmMain/kotlin/de/kif/backend/database/Schema.kt deleted file mode 100644 index 9c07e59..0000000 --- a/src/jvmMain/kotlin/de/kif/backend/database/Schema.kt +++ /dev/null @@ -1,100 +0,0 @@ -package de.kif.backend.database - -import de.kif.backend.model.Permission -import org.jetbrains.exposed.sql.Table - -object DbPerson : Table() { - val id = integer("id").autoIncrement().primaryKey() - val firstName = varchar("first_name", 64) - val lastName = varchar("last_name", 64) - - val arrival = long("arrival").nullable() - val departure = long("departure").nullable() -} - -object DbPersonConstraint : Table() { - val id = integer("id").autoIncrement().primaryKey() - val personId = integer("person_id") - - val type = enumeration("type", DbConstraintType::class) - val time = long("time") - val duration = integer("duration").default(0) - val day = integer("day") -} - -object DbTrack : Table() { - val id = integer("id").autoIncrement().primaryKey() - val name = varchar("name", 64) -} - -object DbWorkGroup : Table() { - val id = integer("id").autoIncrement().primaryKey() - val name = varchar("first_name", 64) - - val interested = integer("interested") - val trackId = integer("track_id").nullable() - val projector = bool("projector") - val resolution = bool("resolution") - - val length = integer("length") - - val start = long("start").nullable() - val end = long("end").nullable() -} - -object DbWorkGroupConstraint : Table() { - val id = integer("id").autoIncrement().primaryKey() - val workGroupId = integer("work_group_id") - - val type = enumeration("type", DbConstraintType::class) - val time = long("time") - val duration = integer("duration").default(0) - val day = integer("day") -} - -object DbLeader : Table() { - val workGroupId = integer("work_group_id").primaryKey(0) - val personId = integer("person_id").primaryKey(1) -} - -object DbWorkGroupOrder : Table() { - val beforeWorkGroupId = integer("before_work_group_id").primaryKey(0) - val afterWorkGroupId = integer("after_work_group_id").primaryKey(1) -} - -object DbRoom : Table() { - val id = integer("id").autoIncrement().primaryKey() - val name = varchar("name", 64) - - val places = integer("places") - val projector = bool("projector") -} - -object DbTimeSlot : Table() { - val id = integer("id").autoIncrement().primaryKey() - - val time = integer("time") - val duration = integer("duration") - val day = integer("day") -} - -object DbSchedule : Table() { - val workGroupId = integer("work_group_id").primaryKey(0) - val timeSlotId = integer("time_slot_id").primaryKey(1) - val roomId = integer("room_id").primaryKey(2) -} - -enum class DbConstraintType { - BEGIN, END, BLOCKED -} - -object DbUser : Table() { - val userId = integer("id").autoIncrement().primaryKey() - val username = varchar("username", 64).uniqueIndex() - val password = varchar("password", 64) -} - -object DbUserPermission : Table() { - val userId = integer("id").primaryKey(0) - val permission = enumeration("permission", Permission::class).primaryKey(1) -} diff --git a/src/jvmMain/kotlin/de/kif/backend/model/Day.kt b/src/jvmMain/kotlin/de/kif/backend/model/Day.kt deleted file mode 100644 index 9461387..0000000 --- a/src/jvmMain/kotlin/de/kif/backend/model/Day.kt +++ /dev/null @@ -1,4 +0,0 @@ -package de.kif.backend.model - -class Day { -} \ No newline at end of file diff --git a/src/jvmMain/kotlin/de/kif/backend/model/Permission.kt b/src/jvmMain/kotlin/de/kif/backend/model/Permission.kt deleted file mode 100644 index 67b0ca6..0000000 --- a/src/jvmMain/kotlin/de/kif/backend/model/Permission.kt +++ /dev/null @@ -1,5 +0,0 @@ -package de.kif.backend.model - -enum class Permission { - USER, SCHEDULE, WORK_GROUP, ROOM, PERSON, ADMIN -} diff --git a/src/jvmMain/kotlin/de/kif/backend/model/Person.kt b/src/jvmMain/kotlin/de/kif/backend/model/Person.kt deleted file mode 100644 index efe6fd7..0000000 --- a/src/jvmMain/kotlin/de/kif/backend/model/Person.kt +++ /dev/null @@ -1,89 +0,0 @@ -package de.kif.backend.model - -import de.kif.backend.database.DbPerson -import de.kif.backend.database.DbPersonConstraint -import de.kif.backend.database.dbQuery -import org.jetbrains.exposed.sql.* - -class Person( - var id: Int = -1, - var firstName: String = "", - var lastName: String = "", - var arrival: Long? = null, - var departure: Long? = null -) { - var constraints: Set = emptySet() - - suspend fun save() { - if (id < 0) { - dbQuery { - val newId = DbPerson.insert { - it[firstName] = this@Person.firstName - it[lastName] = this@Person.lastName - it[arrival] = this@Person.arrival - it[departure] = this@Person.departure - }[DbPerson.id]!! - this@Person.id = newId - } - for (constraint in constraints) { - constraint.save(this@Person.id) - } - } else { - dbQuery { - DbPerson.update({ DbPerson.id eq id }) { - it[firstName] = this@Person.firstName - it[lastName] = this@Person.lastName - it[arrival] = this@Person.arrival - it[departure] = this@Person.departure - } - - DbPersonConstraint.deleteWhere { DbPersonConstraint.personId eq id } - } - for (constraint in constraints) { - constraint.save(this@Person.id) - } - } - } - - suspend fun delete() { - val id = id - if (id >= 0) { - dbQuery { - DbPersonConstraint.deleteWhere { DbPersonConstraint.personId eq id } - DbPerson.deleteWhere { DbPerson.id eq id } - } - } - } - - suspend fun loadConstraints() { - if (id >= 0) { - constraints = PersonConstraint.get(id) - } - } - - companion object { - suspend fun get(personId: Int): Person? = dbQuery { - val result = DbPerson.select { DbPerson.id eq personId }.firstOrNull() ?: return@dbQuery null - Person( - result[DbPerson.id], - result[DbPerson.firstName], - result[DbPerson.lastName], - result[DbPerson.arrival], - result[DbPerson.departure] - ) - }?.apply { loadConstraints() } - - suspend fun list(): List = dbQuery { - val query = DbPerson.selectAll() - query.map { result -> - Person( - result[DbPerson.id], - result[DbPerson.firstName], - result[DbPerson.lastName], - result[DbPerson.arrival], - result[DbPerson.departure] - ) - } - }.onEach { it.loadConstraints() } - } -} diff --git a/src/jvmMain/kotlin/de/kif/backend/model/PersonConstraint.kt b/src/jvmMain/kotlin/de/kif/backend/model/PersonConstraint.kt deleted file mode 100644 index 6754e89..0000000 --- a/src/jvmMain/kotlin/de/kif/backend/model/PersonConstraint.kt +++ /dev/null @@ -1,132 +0,0 @@ -package de.kif.backend.model - -import de.kif.backend.database.DbConstraintType -import de.kif.backend.database.DbPersonConstraint -import de.kif.backend.database.dbQuery -import org.jetbrains.exposed.sql.deleteWhere -import org.jetbrains.exposed.sql.insert -import org.jetbrains.exposed.sql.select -import org.jetbrains.exposed.sql.update - -sealed class PersonConstraint( - var id: Int = -1 -) { - - abstract suspend fun save(personId: Int) - - suspend fun delete() { - val id = id - if (id >= 0) { - dbQuery { - DbPersonConstraint.deleteWhere { DbPersonConstraint.id eq id } - } - } - } - - class BeginOnDay( - var time: Long = 0, - var day: Int = 0 - ) : PersonConstraint() { - override suspend fun save(personId: Int) { - if (id < 0) { - dbQuery { - val newId = DbPersonConstraint.insert { - it[this@insert.personId] = personId - it[type] = DbConstraintType.BEGIN - it[time] = this@BeginOnDay.time - it[day] = this@BeginOnDay.day - }[DbPersonConstraint.id]!! - this@BeginOnDay.id = newId - } - } else { - dbQuery { - DbPersonConstraint.update({ DbPersonConstraint.id eq id }) { - it[this@update.personId] = personId - it[type] = DbConstraintType.BEGIN - it[time] = this@BeginOnDay.time - it[day] = this@BeginOnDay.day - } - } - } - } - } - - class EndOnDay( - var time: Long = 0, - var day: Int = 0 - ) : PersonConstraint() { - override suspend fun save(personId: Int) { - if (id < 0) { - dbQuery { - val newId = DbPersonConstraint.insert { - it[this@insert.personId] = personId - it[type] = DbConstraintType.END - it[time] = this@EndOnDay.time - it[day] = this@EndOnDay.day - }[DbPersonConstraint.id]!! - this@EndOnDay.id = newId - } - } else { - dbQuery { - DbPersonConstraint.update({ DbPersonConstraint.id eq id }) { - it[this@update.personId] = personId - it[type] = DbConstraintType.END - it[time] = this@EndOnDay.time - it[day] = this@EndOnDay.day - } - } - } - } - } - - class BlockedOnDay( - var time: Long = 0, - var duration: Int = 0, - var day: Int = 0 - ) : PersonConstraint() { - - override suspend fun save(personId: Int) { - if (id < 0) { - dbQuery { - val newId = DbPersonConstraint.insert { - it[this@insert.personId] = personId - it[type] = DbConstraintType.BLOCKED - it[time] = this@BlockedOnDay.time - it[duration] = this@BlockedOnDay.duration - it[day] = this@BlockedOnDay.day - }[DbPersonConstraint.id]!! - this@BlockedOnDay.id = newId - } - } else { - dbQuery { - DbPersonConstraint.update({ DbPersonConstraint.id eq id }) { - it[this@update.personId] = personId - it[type] = DbConstraintType.BLOCKED - it[time] = this@BlockedOnDay.time - it[duration] = this@BlockedOnDay.duration - it[day] = this@BlockedOnDay.day - } - } - } - } - } - - companion object { - suspend fun get(personId: Int): Set = dbQuery { - val result = DbPersonConstraint.select { DbPersonConstraint.personId eq personId } - result.map { - val id = it[DbPersonConstraint.id] - val type = it[DbPersonConstraint.type] - val time = it[DbPersonConstraint.time] - val duration = it[DbPersonConstraint.duration] - val day = it[DbPersonConstraint.day] - - when (type) { - DbConstraintType.BEGIN -> PersonConstraint.BeginOnDay(time, day) - DbConstraintType.END -> PersonConstraint.EndOnDay(time, day) - DbConstraintType.BLOCKED -> PersonConstraint.BlockedOnDay(time, duration, day) - }.also { it.id = id } - }.toSet() - } - } -} diff --git a/src/jvmMain/kotlin/de/kif/backend/model/Room.kt b/src/jvmMain/kotlin/de/kif/backend/model/Room.kt deleted file mode 100644 index 3d9ced9..0000000 --- a/src/jvmMain/kotlin/de/kif/backend/model/Room.kt +++ /dev/null @@ -1,66 +0,0 @@ -package de.kif.backend.model - -import de.kif.backend.database.DbRoom -import de.kif.backend.database.dbQuery -import org.jetbrains.exposed.sql.* - -class Room( - var id: Int = -1, - var name: String = "", - var places: Int = 0, - var projector: Boolean = false -) { - suspend fun save() { - if (id < 0) { - dbQuery { - val newId = DbRoom.insert { - it[name] = this@Room.name - it[places] = this@Room.places - it[projector] = this@Room.projector - }[DbRoom.id]!! - this@Room.id = newId - } - } else { - dbQuery { - DbRoom.update({ DbRoom.id eq id }) { - it[name] = this@Room.name - it[places] = this@Room.places - it[projector] = this@Room.projector - } - } - } - } - - suspend fun delete() { - val id = id - if (id >= 0) { - dbQuery { - DbRoom.deleteWhere { DbRoom.id eq id } - } - } - } - - companion object { - suspend fun get(roomId: Int): Room? = dbQuery { - val result = DbRoom.select { DbRoom.id eq roomId }.firstOrNull() ?: return@dbQuery null - Room( - result[DbRoom.id], - result[DbRoom.name], - result[DbRoom.places], - result[DbRoom.projector] - ) - } - - suspend fun list(): List = dbQuery { - val query = DbRoom.selectAll() - query.map { result -> - Room( - result[DbRoom.id], - result[DbRoom.name], - result[DbRoom.places], - result[DbRoom.projector] - ) - } - } - } -} diff --git a/src/jvmMain/kotlin/de/kif/backend/model/TimeSlot.kt b/src/jvmMain/kotlin/de/kif/backend/model/TimeSlot.kt deleted file mode 100644 index 37122f2..0000000 --- a/src/jvmMain/kotlin/de/kif/backend/model/TimeSlot.kt +++ /dev/null @@ -1,4 +0,0 @@ -package de.kif.backend.model - -class TimeSlot { -} \ No newline at end of file diff --git a/src/jvmMain/kotlin/de/kif/backend/model/User.kt b/src/jvmMain/kotlin/de/kif/backend/model/User.kt deleted file mode 100644 index 85aee20..0000000 --- a/src/jvmMain/kotlin/de/kif/backend/model/User.kt +++ /dev/null @@ -1,110 +0,0 @@ -package de.kif.backend.model - -import de.kif.backend.database.DbUser -import de.kif.backend.database.DbUserPermission -import de.kif.backend.database.dbQuery -import io.ktor.auth.Principal -import org.jetbrains.exposed.sql.* -import org.mindrot.jbcrypt.BCrypt - -class User( - var id: Int = -1, - var username: String = "", - private var password: String = "" -) : Principal { - var permissions: Set = emptySet() - - fun checkPassword(password: String): Boolean { - return BCrypt.checkpw(password, this.password) - } - - fun hashPassword(newPassword: String) { - password = BCrypt.hashpw(newPassword, BCrypt.gensalt()) - } - - fun checkPermission(permission: Permission): Boolean { - return permission in permissions || Permission.ADMIN in permissions - } - - suspend fun loadPermissions() = dbQuery { - permissions = DbUserPermission.slice(DbUserPermission.permission).select { - DbUserPermission.userId eq id - }.map { it[DbUserPermission.permission] }.toSet() - } - - suspend fun save() { - if (id < 0) { - dbQuery { - val newId = DbUser.insert { - it[username] = this@User.username - it[password] = this@User.password - }[DbUser.userId]!! - this@User.id = newId - - for (permission in permissions) { - DbUserPermission.insert { - it[userId] = newId - it[this.permission] = permission - } - } - } - } else { - dbQuery { - DbUser.update({ DbUser.userId eq id }) { - it[username] = this@User.username - it[password] = this@User.password - } - - DbUserPermission.deleteWhere { DbUserPermission.userId eq id } - - for (permission in permissions) { - DbUserPermission.insert { - it[userId] = id - it[this.permission] = permission - } - } - } - } - } - - suspend fun delete() { - val id = id - if (id >= 0) { - dbQuery { - DbUserPermission.deleteWhere { DbUserPermission.userId eq id } - DbUser.deleteWhere { DbUser.userId eq id } - } - } - } - - companion object { - suspend fun create(username: String, password: String, permissions: Set) { - val user = User(username = username) - user.hashPassword(password) - user.permissions = permissions - user.save() - } - - suspend fun find(username: String): User? = dbQuery { - val result = DbUser.select { DbUser.username eq username }.firstOrNull() ?: return@dbQuery null - User(result[DbUser.userId], result[DbUser.username], result[DbUser.password]) - - }?.apply { loadPermissions() } - - suspend fun get(userId: Int): User? = dbQuery { - val result = DbUser.select { DbUser.userId eq userId }.firstOrNull() ?: return@dbQuery null - User(result[DbUser.userId], result[DbUser.username], result[DbUser.password]) - }?.apply { loadPermissions() } - - suspend fun list(): List = dbQuery { - val query = DbUser.selectAll() - query.map { result -> - User(result[DbUser.userId], result[DbUser.username], result[DbUser.password]) - } - }.onEach { it.loadPermissions() } - - suspend fun exists(): Boolean = dbQuery { - DbUser.selectAll().count() == 0 - } - } -} diff --git a/src/jvmMain/kotlin/de/kif/backend/model/WorkGroup.kt b/src/jvmMain/kotlin/de/kif/backend/model/WorkGroup.kt deleted file mode 100644 index 0e30f88..0000000 --- a/src/jvmMain/kotlin/de/kif/backend/model/WorkGroup.kt +++ /dev/null @@ -1,109 +0,0 @@ -package de.kif.backend.model - -import de.kif.backend.database.DbWorkGroup -import de.kif.backend.database.DbWorkGroupConstraint -import de.kif.backend.database.dbQuery -import org.jetbrains.exposed.sql.* - -class WorkGroup( - var id: Int = -1, - var name: String = "", - var interested: Int = 0, - var trackId: Int? = null, - var projector: Boolean = false, - var resolution: Boolean = false, - var length: Int = 0, - var start: Long? = null, - var end: Long? = null -) { - var constraints: Set = emptySet() - - suspend fun save() { - if (id < 0) { - dbQuery { - val newId = DbWorkGroup.insert { - it[name] = this@WorkGroup.name - it[interested] = this@WorkGroup.interested - it[trackId] = this@WorkGroup.trackId - it[projector] = this@WorkGroup.projector - it[resolution] = this@WorkGroup.resolution - it[length] = this@WorkGroup.length - it[start] = this@WorkGroup.start - it[end] = this@WorkGroup.end - }[DbWorkGroup.id]!! - this@WorkGroup.id = newId - } - for (constraint in constraints) { - constraint.save(this@WorkGroup.id) - } - } else { - dbQuery { - DbWorkGroup.update({ DbWorkGroup.id eq id }) { - it[name] = this@WorkGroup.name - it[interested] = this@WorkGroup.interested - it[trackId] = this@WorkGroup.trackId - it[projector] = this@WorkGroup.projector - it[resolution] = this@WorkGroup.resolution - it[length] = this@WorkGroup.length - it[start] = this@WorkGroup.start - it[end] = this@WorkGroup.end - } - - DbWorkGroupConstraint.deleteWhere { DbWorkGroupConstraint.workGroupId eq id } - } - for (constraint in constraints) { - constraint.save(this@WorkGroup.id) - } - } - } - - suspend fun delete() { - val id = id - if (id >= 0) { - dbQuery { - DbWorkGroupConstraint.deleteWhere { DbWorkGroupConstraint.workGroupId eq id } - DbWorkGroup.deleteWhere { DbWorkGroup.id eq id } - } - } - } - - suspend fun loadConstraints() { - if (id >= 0) { - constraints = WorkGroupConstraint.get(id) - } - } - - companion object { - suspend fun get(workGroupId: Int): WorkGroup? = dbQuery { - val result = DbWorkGroup.select { DbWorkGroup.id eq workGroupId }.firstOrNull() ?: return@dbQuery null - WorkGroup( - result[DbWorkGroup.id], - result[DbWorkGroup.name], - result[DbWorkGroup.interested], - result[DbWorkGroup.trackId], - result[DbWorkGroup.projector], - result[DbWorkGroup.resolution], - result[DbWorkGroup.length], - result[DbWorkGroup.start], - result[DbWorkGroup.end] - ) - }?.apply { loadConstraints() } - - suspend fun list(): List = dbQuery { - val query = DbWorkGroup.selectAll() - query.map { result -> - WorkGroup( - result[DbWorkGroup.id], - result[DbWorkGroup.name], - result[DbWorkGroup.interested], - result[DbWorkGroup.trackId], - result[DbWorkGroup.projector], - result[DbWorkGroup.resolution], - result[DbWorkGroup.length], - result[DbWorkGroup.start], - result[DbWorkGroup.end] - ) - } - }.onEach { it.loadConstraints() } - } -} diff --git a/src/jvmMain/kotlin/de/kif/backend/model/WorkGroupConstraint.kt b/src/jvmMain/kotlin/de/kif/backend/model/WorkGroupConstraint.kt deleted file mode 100644 index ab7dde5..0000000 --- a/src/jvmMain/kotlin/de/kif/backend/model/WorkGroupConstraint.kt +++ /dev/null @@ -1,132 +0,0 @@ -package de.kif.backend.model - -import de.kif.backend.database.DbConstraintType -import de.kif.backend.database.DbWorkGroupConstraint -import de.kif.backend.database.dbQuery -import org.jetbrains.exposed.sql.deleteWhere -import org.jetbrains.exposed.sql.insert -import org.jetbrains.exposed.sql.select -import org.jetbrains.exposed.sql.update - -sealed class WorkGroupConstraint( - var id: Int = -1 -) { - - abstract suspend fun save(workGroupId: Int) - - suspend fun delete() { - val id = id - if (id >= 0) { - dbQuery { - DbWorkGroupConstraint.deleteWhere { DbWorkGroupConstraint.id eq id } - } - } - } - - class BeginOnDay( - var time: Long = 0, - var day: Int = 0 - ) : WorkGroupConstraint() { - override suspend fun save(workGroupId: Int) { - if (id < 0) { - dbQuery { - val newId = DbWorkGroupConstraint.insert { - it[this@insert.workGroupId] = workGroupId - it[type] = DbConstraintType.BEGIN - it[time] = this@BeginOnDay.time - it[day] = this@BeginOnDay.day - }[DbWorkGroupConstraint.id]!! - this@BeginOnDay.id = newId - } - } else { - dbQuery { - DbWorkGroupConstraint.update({ DbWorkGroupConstraint.id eq id }) { - it[this@update.workGroupId] = workGroupId - it[type] = DbConstraintType.BEGIN - it[time] = this@BeginOnDay.time - it[day] = this@BeginOnDay.day - } - } - } - } - } - - class EndOnDay( - var time: Long = 0, - var day: Int = 0 - ) : WorkGroupConstraint() { - override suspend fun save(workGroupId: Int) { - if (id < 0) { - dbQuery { - val newId = DbWorkGroupConstraint.insert { - it[this@insert.workGroupId] = workGroupId - it[type] = DbConstraintType.END - it[time] = this@EndOnDay.time - it[day] = this@EndOnDay.day - }[DbWorkGroupConstraint.id]!! - this@EndOnDay.id = newId - } - } else { - dbQuery { - DbWorkGroupConstraint.update({ DbWorkGroupConstraint.id eq id }) { - it[this@update.workGroupId] = workGroupId - it[type] = DbConstraintType.END - it[time] = this@EndOnDay.time - it[day] = this@EndOnDay.day - } - } - } - } - } - - class BlockedOnDay( - var time: Long = 0, - var duration: Int = 0, - var day: Int = 0 - ) : WorkGroupConstraint() { - - override suspend fun save(workGroupId: Int) { - if (id < 0) { - dbQuery { - val newId = DbWorkGroupConstraint.insert { - it[this@insert.workGroupId] = workGroupId - it[type] = DbConstraintType.BLOCKED - it[time] = this@BlockedOnDay.time - it[duration] = this@BlockedOnDay.duration - it[day] = this@BlockedOnDay.day - }[DbWorkGroupConstraint.id]!! - this@BlockedOnDay.id = newId - } - } else { - dbQuery { - DbWorkGroupConstraint.update({ DbWorkGroupConstraint.id eq id }) { - it[this@update.workGroupId] = workGroupId - it[type] = DbConstraintType.BLOCKED - it[time] = this@BlockedOnDay.time - it[duration] = this@BlockedOnDay.duration - it[day] = this@BlockedOnDay.day - } - } - } - } - } - - companion object { - suspend fun get(workGroupId: Int): Set = dbQuery { - val result = DbWorkGroupConstraint.select { DbWorkGroupConstraint.workGroupId eq workGroupId } - result.map { - val id = it[DbWorkGroupConstraint.id] - val type = it[DbWorkGroupConstraint.type] - val time = it[DbWorkGroupConstraint.time] - val duration = it[DbWorkGroupConstraint.duration] - val day = it[DbWorkGroupConstraint.day] - - when (type) { - DbConstraintType.BEGIN -> WorkGroupConstraint.BeginOnDay(time, day) - DbConstraintType.END -> WorkGroupConstraint.EndOnDay(time, day) - DbConstraintType.BLOCKED -> WorkGroupConstraint.BlockedOnDay(time, duration, day) - }.also { it.id = id } - }.toSet() - } - } -} diff --git a/src/jvmMain/kotlin/de/kif/backend/route/Account.kt b/src/jvmMain/kotlin/de/kif/backend/route/Account.kt deleted file mode 100644 index ee8ad87..0000000 --- a/src/jvmMain/kotlin/de/kif/backend/route/Account.kt +++ /dev/null @@ -1,46 +0,0 @@ -package de.kif.backend.route - -import de.kif.backend.LocationAccount -import de.kif.backend.LocationLogin -import de.kif.backend.PortalSession -import de.kif.backend.view.MainTemplate -import de.kif.backend.view.MenuTemplate -import io.ktor.application.call -import io.ktor.html.respondHtmlTemplate -import io.ktor.locations.get -import io.ktor.request.path -import io.ktor.response.respondRedirect -import io.ktor.routing.Route -import io.ktor.sessions.get -import io.ktor.sessions.sessions -import kotlinx.html.* - -fun Route.account() { - get { - val user = call.sessions.get()?.getUser(call) - if (user == null) { - call.respondRedirect("/login?${LocationLogin::next.name}=${call.request.path()}}") - } else { - call.respondHtmlTemplate(MainTemplate()) { - menuTemplate { - this.user = user - active = MenuTemplate.Tab.ACCOUNT - } - content { - h1 { +"Account" } - div { - +"Welcome ${user.username}!" - br {} - +"You have the following rights: ${user.permissions}" - br {} - a("/logout") { - button(classes="form-btn") { - +"Logout" - } - } - } - } - } - } - } -} diff --git a/src/jvmMain/kotlin/de/kif/backend/route/Calendar.kt b/src/jvmMain/kotlin/de/kif/backend/route/Calendar.kt deleted file mode 100644 index 00ec006..0000000 --- a/src/jvmMain/kotlin/de/kif/backend/route/Calendar.kt +++ /dev/null @@ -1,28 +0,0 @@ -package de.kif.backend.route - -import de.kif.backend.LocationCalendar -import de.kif.backend.PortalSession -import de.kif.backend.view.MainTemplate -import de.kif.backend.view.MenuTemplate -import io.ktor.application.call -import io.ktor.html.respondHtmlTemplate -import io.ktor.locations.get -import io.ktor.routing.Route -import io.ktor.sessions.get -import io.ktor.sessions.sessions -import kotlinx.html.h1 - -fun Route.calendar() { - get { - val user = call.sessions.get()?.getUser(call) - call.respondHtmlTemplate(MainTemplate()) { - menuTemplate { - this.user = user - active = MenuTemplate.Tab.CALENDAR - } - content { - h1 { +"Calendar" } - } - } - } -} diff --git a/src/jvmMain/kotlin/de/kif/backend/route/Dashboard.kt b/src/jvmMain/kotlin/de/kif/backend/route/Dashboard.kt deleted file mode 100644 index a71934a..0000000 --- a/src/jvmMain/kotlin/de/kif/backend/route/Dashboard.kt +++ /dev/null @@ -1,28 +0,0 @@ -package de.kif.backend.route - -import de.kif.backend.LocationDashboard -import de.kif.backend.PortalSession -import de.kif.backend.view.MainTemplate -import de.kif.backend.view.MenuTemplate -import io.ktor.application.call -import io.ktor.html.respondHtmlTemplate -import io.ktor.locations.get -import io.ktor.routing.Route -import io.ktor.sessions.get -import io.ktor.sessions.sessions -import kotlinx.html.h1 - -fun Route.dashboard() { - get { - val user = call.sessions.get()?.getUser(call) - call.respondHtmlTemplate(MainTemplate()) { - menuTemplate { - this.user = user - active = MenuTemplate.Tab.DASHBOARD - } - content { - h1 { +"Dashboard" } - } - } - } -} diff --git a/src/jvmMain/kotlin/de/kif/backend/route/Login.kt b/src/jvmMain/kotlin/de/kif/backend/route/Login.kt deleted file mode 100644 index 7f4533a..0000000 --- a/src/jvmMain/kotlin/de/kif/backend/route/Login.kt +++ /dev/null @@ -1,102 +0,0 @@ -package de.kif.backend.route - -import de.kif.backend.LocationLogin -import de.kif.backend.LocationLogout -import de.kif.backend.PortalSession -import de.kif.backend.model.User -import de.kif.backend.view.MainTemplate -import io.ktor.application.call -import io.ktor.auth.authenticate -import io.ktor.auth.principal -import io.ktor.html.respondHtmlTemplate -import io.ktor.locations.location -import io.ktor.response.respondRedirect -import io.ktor.routing.Route -import io.ktor.routing.get -import io.ktor.routing.post -import io.ktor.sessions.clear -import io.ktor.sessions.get -import io.ktor.sessions.sessions -import io.ktor.sessions.set -import kotlinx.html.* - -fun Route.login() { - location { - authenticate { - post { - val principal = call.principal() ?: return@post - call.sessions.set(PortalSession(principal.id, principal.username)) - call.respondRedirect(call.parameters[LocationLogin::next.name] ?: "/") - } - } - - get { - val needLogin = call.sessions.get() == null - if (needLogin) { - call.respondHtmlTemplate(MainTemplate()) { - content { - div { - div { - br { } - form("/login", method = FormMethod.post) { - div("form-group") { - label { - htmlFor = LocationLogin::username.name - +"Username" - } - input( - name = LocationLogin::username.name, - classes = "form-control" - ) { - id = LocationLogin::username.name - placeholder = "Username" - } - } - div("form-group") { - label { - htmlFor = LocationLogin::password.name - +"Password" - } - input( - name = LocationLogin::password.name, - classes = "form-control", - type = InputType.password - ) { - id = LocationLogin::password.name - placeholder = "Password" - } - } - input( - name = LocationLogin::next.name, - type = InputType.hidden - ) { - value = call.parameters[LocationLogin::next.name] ?: "/" - } - button(type = ButtonType.submit, classes = "form-btn btn-primary") { - +"Login" - } - } - - if ("error" in call.parameters) { - br { } - div("alert alert-danger") { - +"Username or password incorrect!" - } - } - } - } - } - } - } else { - call.respondRedirect(call.parameters[LocationLogin::next.name] ?: "/") - } - } - } - - location { - get { - call.sessions.clear() - call.respondRedirect("/") - } - } -} diff --git a/src/jvmMain/kotlin/de/kif/backend/route/Person.kt b/src/jvmMain/kotlin/de/kif/backend/route/Person.kt deleted file mode 100644 index 77803d3..0000000 --- a/src/jvmMain/kotlin/de/kif/backend/route/Person.kt +++ /dev/null @@ -1,258 +0,0 @@ -package de.kif.backend.route - -import de.kif.backend.LocationLogin -import de.kif.backend.LocationPerson -import de.kif.backend.PortalSession -import de.kif.backend.model.Permission -import de.kif.backend.model.Person -import de.kif.backend.util.Search -import de.kif.backend.view.MainTemplate -import de.kif.backend.view.MenuTemplate -import de.kif.backend.view.TableTemplate -import io.ktor.application.call -import io.ktor.html.insert -import io.ktor.html.respondHtmlTemplate -import io.ktor.locations.get -import io.ktor.locations.post -import io.ktor.request.path -import io.ktor.request.receiveParameters -import io.ktor.response.respondRedirect -import io.ktor.routing.Route -import io.ktor.sessions.get -import io.ktor.sessions.sessions -import io.ktor.util.toMap -import kotlinx.html.* - -fun Route.person() { - get { param -> - val user = call.sessions.get()?.getUser(call) - if (user == null || !user.checkPermission(Permission.PERSON)) { - call.respondRedirect("/login?${LocationLogin::next.name}=${call.request.path()}}") - } else { - val list = Person.list() - call.respondHtmlTemplate(MainTemplate()) { - menuTemplate { - this.user = user - active = MenuTemplate.Tab.PERSON - } - content { - h1 { +"Persons" } - insert(TableTemplate()) { - searchValue = param.search - - action { - a("/person/new") { - button(classes="form-btn btn-primary") { - +"Add person" - } - } - } - - header { - th { - +"First name" - } - th { - +"Last name" - } - th(classes = "action") { - +"Action" - } - } - - for (u in list) { - if (Search.match(param.search, u.firstName, u.lastName)) { - entry { - attributes["data-search"] = Search.pack(u.firstName, u.lastName) - td { - +u.firstName - } - td { - +u.lastName - } - td(classes = "action") { - a("/person/${u.id}") { - i("material-icons") { +"edit" } - } - } - } - } - } - } - } - } - } - } - - get { personId -> - val user = call.sessions.get()?.getUser(call) - if (user == null || !user.checkPermission(Permission.PERSON)) { - call.respondRedirect("/login?${LocationLogin::next.name}=${call.request.path()}}") - } else { - val editPerson = Person.get(personId.id) ?: return@get - call.respondHtmlTemplate(MainTemplate()) { - menuTemplate { - this.user = user - active = MenuTemplate.Tab.PERSON - } - content { - h1 { +"Edit person" } - form(method = FormMethod.post) { - div("form-group") { - label { - htmlFor = "first-name" - +"First name" - } - input( - name = "first-name", - classes = "form-control" - ) { - id = "first-name" - placeholder = "First name" - value = editPerson.firstName - } - } - div("form-group") { - label { - htmlFor = "last-name" - +"Last name" - } - input( - name = "last-name", - classes = "form-control" - ) { - id = "last-name" - placeholder = "Last name" - value = editPerson.lastName - } - } - - div("form-group") { - a("/person") { - button(classes = "form-btn") { - +"Cancel" - } - } - button(type = ButtonType.submit, classes = "form-btn btn-primary") { - +"Save" - } - } - } - a("/person/${editPerson.id}/delete") { - button(classes = "form-btn btn-danger") { - +"Delete" - } - } - } - } - } - } - - post { personId -> - val user = call.sessions.get()?.getUser(call) - if (user == null || !user.checkPermission(Permission.PERSON)) { - call.respondRedirect("/login?${LocationLogin::next.name}=${call.request.path()}}") - } else { - val params = call.receiveParameters().toMap().mapValues { (_, list) -> - list.firstOrNull() - } - val editPerson = Person.get(personId.id) ?: return@post - - params["first-name"]?.let { editPerson.firstName = it } - params["last-name"]?.let { editPerson.lastName = it } - - editPerson.save() - - call.respondRedirect("/person") - } - } - - get { - val user = call.sessions.get()?.getUser(call) - if (user == null || !user.checkPermission(Permission.PERSON)) { - call.respondRedirect("/login?${LocationLogin::next.name}=${call.request.path()}}") - } else { - call.respondHtmlTemplate(MainTemplate()) { - menuTemplate { - this.user = user - active = MenuTemplate.Tab.PERSON - } - content { - h1 { +"Create person" } - form(method = FormMethod.post) { - div("form-group") { - label { - htmlFor = "first-name" - +"First name" - } - input( - name = "first-name", - classes = "form-control" - ) { - id = "first-name" - placeholder = "First name" - value = "" - } - } - div("form-group") { - label { - htmlFor = "last-name" - +"Last name" - } - input( - name = "last-name", - classes = "form-control" - ) { - id = "last-name" - placeholder = "Last name" - value = "" - } - } - - div("form-group") { - a("/person") { - button(classes = "form-btn") { - +"Cancel" - } - } - button(type = ButtonType.submit, classes = "form-btn btn-primary") { - +"Create" - } - } - } - } - } - } - } - - post { - val user = call.sessions.get()?.getUser(call) - if (user == null || !user.checkPermission(Permission.PERSON)) { - call.respondRedirect("/login?${LocationLogin::next.name}=${call.request.path()}}") - } else { - val params = call.receiveParameters().toMap().mapValues { (_, list) -> - list.firstOrNull() - } - - val firstName = params["first-name"] ?: return@post - val lastName = params["last-name"] ?: return@post - - Person(firstName = firstName, lastName = lastName).save() - - call.respondRedirect("/person") - } - } - - get { personId -> - val user = call.sessions.get()?.getUser(call) - if (user == null || !user.checkPermission(Permission.PERSON)) { - call.respondRedirect("/login?${LocationLogin::next.name}=${call.request.path()}}") - } else { - val deletePerson = Person.get(personId.id) ?: return@get - - deletePerson.delete() - - call.respondRedirect("/person") - } - } -} diff --git a/src/jvmMain/kotlin/de/kif/backend/route/Room.kt b/src/jvmMain/kotlin/de/kif/backend/route/Room.kt deleted file mode 100644 index e8a0532..0000000 --- a/src/jvmMain/kotlin/de/kif/backend/route/Room.kt +++ /dev/null @@ -1,308 +0,0 @@ -package de.kif.backend.route - -import de.kif.backend.LocationLogin -import de.kif.backend.LocationRoom -import de.kif.backend.PortalSession -import de.kif.backend.model.Permission -import de.kif.backend.model.Room -import de.kif.backend.util.Search -import de.kif.backend.view.MainTemplate -import de.kif.backend.view.MenuTemplate -import de.kif.backend.view.TableTemplate -import io.ktor.application.call -import io.ktor.html.insert -import io.ktor.html.respondHtmlTemplate -import io.ktor.locations.get -import io.ktor.locations.post -import io.ktor.request.path -import io.ktor.request.receiveParameters -import io.ktor.response.respondRedirect -import io.ktor.routing.Route -import io.ktor.sessions.get -import io.ktor.sessions.sessions -import io.ktor.util.toMap -import kotlinx.html.* - -fun Route.room() { - get { param -> - val user = call.sessions.get()?.getUser(call) - if (user == null || !user.checkPermission(Permission.ROOM)) { - call.respondRedirect("/login?${LocationLogin::next.name}=${call.request.path()}}") - } else { - val list = Room.list() - call.respondHtmlTemplate(MainTemplate()) { - menuTemplate { - this.user = user - active = MenuTemplate.Tab.ROOM - } - content { - h1 { +"Rooms" } - insert(TableTemplate()) { - searchValue = param.search - - action { - a("/room/new") { - button(classes="form-btn btn-primary") { - +"Add room" - } - } - } - - header { - th { - +"Name" - } - th { - +"Places" - } - th { - +"Projector" - } - th(classes = "action") { - +"Action" - } - } - - for (u in list) { - if (Search.match(param.search, u.name)) { - entry { - attributes["data-search"] = Search.pack(u.name) - td { - +u.name - } - td { - +u.places.toString() - } - td { - +u.projector.toString() - } - td(classes = "action") { - a("/room/${u.id}") { - i("material-icons") { +"edit" } - } - } - } - } - } - } - } - } - } - } - - get { roomId -> - val user = call.sessions.get()?.getUser(call) - if (user == null || !user.checkPermission(Permission.ROOM)) { - call.respondRedirect("/login?${LocationLogin::next.name}=${call.request.path()}}") - } else { - val editRoom = Room.get(roomId.id) ?: return@get - call.respondHtmlTemplate(MainTemplate()) { - menuTemplate { - this.user = user - active = MenuTemplate.Tab.ROOM - } - content { - h1 { +"Edit room" } - form(method = FormMethod.post) { - div("form-group") { - label { - htmlFor = "name" - +"Name" - } - input( - name = "name", - classes = "form-control" - ) { - id = "name" - placeholder = "Name" - value = editRoom.name - } - } - div("form-group") { - label { - htmlFor = "places" - +"Places" - } - input( - name = "places", - classes = "form-control", - type = InputType.number - ) { - id = "places" - placeholder = "Places" - value = editRoom.places.toString() - - min = "0" - max = "1337" - } - } - - div("form-switch-group") { - div("form-group form-switch") { - input( - name = "projector", - classes = "form-control", - type = InputType.checkBox - ) { - id = "projector" - checked = editRoom.projector - } - label { - htmlFor = "projector" - +"Projector" - } - } - } - - div("form-group") { - a("/room") { - button(classes = "form-btn") { - +"Cancel" - } - } - button(type = ButtonType.submit, classes = "form-btn btn-primary") { - +"Save" - } - } - } - a("/room/${editRoom.id}/delete") { - button(classes = "form-btn btn-danger") { - +"Delete" - } - } - } - } - } - } - - post { roomId -> - val user = call.sessions.get()?.getUser(call) - if (user == null || !user.checkPermission(Permission.ROOM)) { - call.respondRedirect("/login?${LocationLogin::next.name}=${call.request.path()}}") - } else { - val params = call.receiveParameters().toMap().mapValues { (_, list) -> - list.firstOrNull() - } - val editRoom = Room.get(roomId.id) ?: return@post - - params["name"]?.let { editRoom.name = it } - params["places"]?.let { editRoom.places = it.toIntOrNull() ?: 0 } - params["projector"]?.let { editRoom.projector = it == "on" } - - editRoom.save() - - call.respondRedirect("/room") - } - } - - get { - val user = call.sessions.get()?.getUser(call) - if (user == null || !user.checkPermission(Permission.ROOM)) { - call.respondRedirect("/login?${LocationLogin::next.name}=${call.request.path()}}") - } else { - call.respondHtmlTemplate(MainTemplate()) { - menuTemplate { - this.user = user - active = MenuTemplate.Tab.ROOM - } - content { - h1 { +"Create room" } - form(method = FormMethod.post) { - div("form-group") { - label { - htmlFor = "name" - +"Name" - } - input( - name = "name", - classes = "form-control" - ) { - id = "name" - placeholder = "Name" - value = "" - } - } - div("form-group") { - label { - htmlFor = "places" - +"Places" - } - input( - name = "places", - classes = "form-control", - type = InputType.number - ) { - id = "places" - placeholder = "Places" - value = "0" - - min = "0" - max = "1337" - } - } - - div("form-switch-group") { - div("form-group form-switch") { - input( - name = "projector", - classes = "form-control", - type = InputType.checkBox - ) { - id = "projector" - checked = false - } - label { - htmlFor = "projector" - +"Projector" - } - } - } - - div("form-group") { - a("/room") { - button(classes = "form-btn") { - +"Cancel" - } - } - button(type = ButtonType.submit, classes = "form-btn btn-primary") { - +"Create" - } - } - } - } - } - } - } - - post { - val user = call.sessions.get()?.getUser(call) - if (user == null || !user.checkPermission(Permission.ROOM)) { - call.respondRedirect("/login?${LocationLogin::next.name}=${call.request.path()}}") - } else { - val params = call.receiveParameters().toMap().mapValues { (_, list) -> - list.firstOrNull() - } - - val name = params["name"] ?: return@post - val places = (params["places"] ?: return@post).toIntOrNull() ?: 0 - val projector = params["projector"] == "on" - - Room(name = name, places = places, projector = projector).save() - - call.respondRedirect("/room") - } - } - - get { roomId -> - val user = call.sessions.get()?.getUser(call) - if (user == null || !user.checkPermission(Permission.ROOM)) { - call.respondRedirect("/login?${LocationLogin::next.name}=${call.request.path()}}") - } else { - val deleteRoom = Room.get(roomId.id) ?: return@get - - deleteRoom.delete() - - call.respondRedirect("/room") - } - } -} diff --git a/src/jvmMain/kotlin/de/kif/backend/route/Setup.kt b/src/jvmMain/kotlin/de/kif/backend/route/Setup.kt deleted file mode 100644 index 73029c7..0000000 --- a/src/jvmMain/kotlin/de/kif/backend/route/Setup.kt +++ /dev/null @@ -1,101 +0,0 @@ -package de.kif.backend.route - -import de.kif.backend.LocationLogin -import de.kif.backend.database.DbUser -import de.kif.backend.model.Permission -import de.kif.backend.model.User -import de.kif.backend.view.MainTemplate -import io.ktor.application.call -import io.ktor.html.respondHtmlTemplate -import io.ktor.request.receiveParameters -import io.ktor.response.respondRedirect -import io.ktor.routing.Route -import io.ktor.routing.get -import io.ktor.routing.post -import io.ktor.routing.route -import kotlinx.html.* -import org.jetbrains.exposed.sql.selectAll -import org.jetbrains.exposed.sql.transactions.transaction - -fun Route.setup() { - route("/") { - get { - call.respondHtmlTemplate(MainTemplate()) { - transaction { - val firstStart = DbUser.selectAll().count() == 0 - - menuTemplate { - setup = true - } - - if (firstStart) { - content { - div { - h1 { +"Create account" } - form("/", method = FormMethod.post) { - div("form-group") { - label { - htmlFor = LocationLogin::username.name - +"Username" - } - input( - name = LocationLogin::username.name, - classes = "form-control" - ) { - id = LocationLogin::username.name - placeholder = "Username" - } - } - div("form-group") { - label { - htmlFor = LocationLogin::password.name - +"Password" - } - input( - name = LocationLogin::password.name, - classes = "form-control", - type = InputType.password - ) { - id = LocationLogin::password.name - placeholder = "Password" - } - } - button(type = ButtonType.submit, classes = "btn btn-primary") { - +"Create" - } - } - } - } - } else { - content { - div { - h1 { +"Setup complete" } - p { - +"Please restart the server!" - } - } - } - } - } - } - } - - post { - val parameters = call.receiveParameters() - val username = parameters[LocationLogin::username.name] - val password = parameters[LocationLogin::password.name] - - if (username == null || password == null) { - call.respondRedirect("/") - return@post - } - - User.create(username, password, Permission.values().toSet()) - call.respondRedirect("/") - } - } - - get("*") { - call.respondRedirect("/") - } -} diff --git a/src/jvmMain/kotlin/de/kif/backend/route/User.kt b/src/jvmMain/kotlin/de/kif/backend/route/User.kt deleted file mode 100644 index 4dc6b4c..0000000 --- a/src/jvmMain/kotlin/de/kif/backend/route/User.kt +++ /dev/null @@ -1,313 +0,0 @@ -package de.kif.backend.route - -import de.kif.backend.LocationLogin -import de.kif.backend.LocationUser -import de.kif.backend.PortalSession -import de.kif.backend.model.Permission -import de.kif.backend.model.User -import de.kif.backend.util.Search -import de.kif.backend.view.MainTemplate -import de.kif.backend.view.MenuTemplate -import de.kif.backend.view.TableTemplate -import io.ktor.application.call -import io.ktor.html.insert -import io.ktor.html.respondHtmlTemplate -import io.ktor.locations.get -import io.ktor.locations.post -import io.ktor.request.path -import io.ktor.request.receiveParameters -import io.ktor.response.respondRedirect -import io.ktor.routing.Route -import io.ktor.sessions.get -import io.ktor.sessions.sessions -import io.ktor.util.toMap -import kotlinx.html.* - -fun Route.user() { - get { param -> - val user = call.sessions.get()?.getUser(call) - if (user == null || !user.checkPermission(Permission.USER)) { - call.respondRedirect("/login?${LocationLogin::next.name}=${call.request.path()}}") - } else { - val list = User.list() - call.respondHtmlTemplate(MainTemplate()) { - menuTemplate { - this.user = user - active = MenuTemplate.Tab.USER - } - content { - h1 { +"Users" } - insert(TableTemplate()) { - searchValue = param.search - - action { - a("/user/new") { - button(classes="form-btn btn-primary") { - +"Add user" - } - } - } - - header { - th { - +"Username" - } - th { - +"Permissions" - } - th(classes = "action") { - +"Action" - } - } - - for (u in list) { - if (Search.match(param.search, u.username)) { - entry { - attributes["data-search"] = Search.pack(u.username) - td { - +u.username - } - td { - +u.permissions.joinToString(", ") { it.toString().toLowerCase() } - } - td(classes = "action") { - a("/user/${u.id}") { - i("material-icons") { +"edit" } - } - } - } - } - } - } - } - } - } - } - - get { userId -> - val user = call.sessions.get()?.getUser(call) - if (user == null || !user.checkPermission(Permission.USER)) { - call.respondRedirect("/login?${LocationLogin::next.name}=${call.request.path()}}") - } else { - val editUser = User.get(userId.id) ?: return@get - call.respondHtmlTemplate(MainTemplate()) { - menuTemplate { - this.user = user - active = MenuTemplate.Tab.USER - } - content { - h1 { +"Edit user" } - form(method = FormMethod.post) { - div("form-group") { - label { - htmlFor = "username" - +"Username" - } - input( - name = "username", - classes = "form-control" - ) { - id = "username" - placeholder = "Username" - value = editUser.username - } - } - - div("form-switch-group") { - for (permission in Permission.values()) { - val name = permission.toString().toLowerCase() - div("form-group form-switch") { - input( - name = "permission-$name", - classes = "form-control", - type = InputType.checkBox - ) { - id = "permission-$name" - checked = permission in editUser.permissions - - if (!user.checkPermission(permission)) { - readonly = true - } - } - label { - htmlFor = "permission-$name" - +name.capitalize() - } - } - } - } - - div("form-group") { - a("/user") { - button(classes = "form-btn") { - +"Cancel" - } - } - button(type = ButtonType.submit, classes = "form-btn btn-primary") { - +"Save" - } - } - } - a("/user/${editUser.id}/delete") { - button(classes = "form-btn btn-danger") { - +"Delete" - } - } - } - } - } - } - - post { userId -> - val user = call.sessions.get()?.getUser(call) - if (user == null || !user.checkPermission(Permission.USER)) { - call.respondRedirect("/login?${LocationLogin::next.name}=${call.request.path()}}") - } else { - val params = call.receiveParameters().toMap().mapValues { (_, list) -> - list.firstOrNull() - } - val editUser = User.get(userId.id) ?: return@post - - params["username"]?.let { editUser.username = it } - - for (permission in Permission.values()) { - val name = permission.toString().toLowerCase() - if (user.checkPermission(permission)) { - if (params["permission-$name"] == "on") { - editUser.permissions += permission - } else { - editUser.permissions -= permission - } - } - } - editUser.save() - - call.respondRedirect("/user") - } - } - - get { - val user = call.sessions.get()?.getUser(call) - if (user == null || !user.checkPermission(Permission.USER)) { - call.respondRedirect("/login?${LocationLogin::next.name}=${call.request.path()}}") - } else { - call.respondHtmlTemplate(MainTemplate()) { - menuTemplate { - this.user = user - active = MenuTemplate.Tab.USER - } - content { - h1 { +"Create user" } - form(method = FormMethod.post) { - div("form-group") { - label { - htmlFor = "username" - +"Username" - } - input( - name = "username", - classes = "form-control" - ) { - id = "username" - placeholder = "Username" - value = "" - } - } - div("form-group") { - label { - htmlFor = "password" - +"Password" - } - input( - name = "password", - classes = "form-control", - type = InputType.password - ) { - id = "password" - placeholder = "Password" - value = "" - } - } - - div("form-switch-group") { - for (permission in Permission.values()) { - val name = permission.toString().toLowerCase() - div("form-group form-switch") { - input( - name = "permission-$name", - classes = "form-control", - type = InputType.checkBox - ) { - id = "permission-$name" - checked = false - - if (!user.checkPermission(permission)) { - readonly = true - } - } - label { - htmlFor = "permission-$name" - +name.capitalize() - } - } - } - } - - div("form-group") { - a("/user") { - button(classes = "form-btn") { - +"Cancel" - } - } - button(type = ButtonType.submit, classes = "form-btn btn-primary") { - +"Create" - } - } - } - } - } - } - } - - post { - val user = call.sessions.get()?.getUser(call) - if (user == null || !user.checkPermission(Permission.USER)) { - call.respondRedirect("/login?${LocationLogin::next.name}=${call.request.path()}}") - } else { - val params = call.receiveParameters().toMap().mapValues { (_, list) -> - list.firstOrNull() - } - - val username = params["username"] ?: return@post - val password = params["password"] ?: return@post - - val permissions = Permission.values().mapNotNull { permission -> - if (user.checkPermission(permission) && params["permission-${permission.toString().toLowerCase()}"] == "on") - permission - else - null - }.toSet() - - User.create(username, password, permissions) - - call.respondRedirect("/user") - } - } - - get { userId -> - val user = call.sessions.get()?.getUser(call) - if (user == null || !user.checkPermission(Permission.USER)) { - call.respondRedirect("/login?${LocationLogin::next.name}=${call.request.path()}}") - } else { - val deleteUser = User.get(userId.id) ?: return@get - - if (user.checkPermission(Permission.USER) && - (Permission.ADMIN !in deleteUser.permissions || Permission.ADMIN in user.permissions) - ) { - deleteUser.delete() - } - - call.respondRedirect("/user") - } - } -} diff --git a/src/jvmMain/kotlin/de/kif/backend/route/WorkGroup.kt b/src/jvmMain/kotlin/de/kif/backend/route/WorkGroup.kt deleted file mode 100644 index b24f4df..0000000 --- a/src/jvmMain/kotlin/de/kif/backend/route/WorkGroup.kt +++ /dev/null @@ -1,433 +0,0 @@ -package de.kif.backend.route - -import de.kif.backend.LocationLogin -import de.kif.backend.LocationWorkGroup -import de.kif.backend.PortalSession -import de.kif.backend.model.Permission -import de.kif.backend.model.WorkGroup -import de.kif.backend.util.Search -import de.kif.backend.view.MainTemplate -import de.kif.backend.view.MenuTemplate -import de.kif.backend.view.TableTemplate -import io.ktor.application.call -import io.ktor.html.insert -import io.ktor.html.respondHtmlTemplate -import io.ktor.locations.get -import io.ktor.locations.post -import io.ktor.request.path -import io.ktor.request.receiveParameters -import io.ktor.response.respondRedirect -import io.ktor.routing.Route -import io.ktor.sessions.get -import io.ktor.sessions.sessions -import io.ktor.util.toMap -import kotlinx.html.* - -fun Route.workGroup() { - get { param -> - val user = call.sessions.get()?.getUser(call) - if (user == null || !user.checkPermission(Permission.WORK_GROUP)) { - call.respondRedirect("/login?${LocationLogin::next.name}=${call.request.path()}}") - } else { - val list = WorkGroup.list() - call.respondHtmlTemplate(MainTemplate()) { - menuTemplate { - this.user = user - active = MenuTemplate.Tab.WORK_GROUP - } - content { - h1 { +"Work groups" } - insert(TableTemplate()) { - searchValue = param.search - - action { - a("/workgroup/new") { - button(classes = "form-btn btn-primary") { - +"Add work group" - } - } - } - - header { - th { - +"Name" - } - th { - +"Interested" - } - th { - +"Track" - } - th { - +"Projector" - } - th { - +"Resolution" - } - th { - +"Length" - } - th(classes = "action") { - +"Action" - } - } - - for (u in list) { - if (Search.match(param.search, u.name)) { - entry { - attributes["data-search"] = Search.pack(u.name) - td { - +u.name - } - td { - +u.interested.toString() - } - td { - +u.trackId.toString() - } - td { - +u.projector.toString() - } - td { - +u.resolution.toString() - } - td { - +u.length.toString() - } - td(classes = "action") { - a("/workgroup/${u.id}") { - i("material-icons") { +"edit" } - } - } - } - } - } - } - } - } - } - } - - get { workGroupId -> - val user = call.sessions.get()?.getUser(call) - if (user == null || !user.checkPermission(Permission.WORK_GROUP)) { - call.respondRedirect("/login?${LocationLogin::next.name}=${call.request.path()}}") - } else { - val editWorkGroup = WorkGroup.get(workGroupId.id) ?: return@get - call.respondHtmlTemplate(MainTemplate()) { - menuTemplate { - this.user = user - active = MenuTemplate.Tab.WORK_GROUP - } - content { - h1 { +"Edit work group" } - form(method = FormMethod.post) { - div("form-group") { - label { - htmlFor = "name" - +"Name" - } - input( - name = "name", - classes = "form-control" - ) { - id = "name" - placeholder = "Name" - value = editWorkGroup.name - } - } - div("form-group") { - label { - htmlFor = "interested" - +"Interested" - } - input( - name = "interested", - classes = "form-control", - type = InputType.number - ) { - id = "interested" - value = editWorkGroup.interested.toString() - - min = "0" - max = "1337" - } - } - div("form-group") { - label { - htmlFor = "track" - +"Track" - } - input( - name = "track", - classes = "form-control", - type = InputType.number - ) { - id = "track" - value = editWorkGroup.trackId.toString() - - min = "0" - max = "1337" - } - } - div("form-group") { - label { - htmlFor = "length" - +"Length" - } - input( - name = "length", - classes = "form-control", - type = InputType.number - ) { - id = "length" - value = editWorkGroup.length.toString() - - min = "0" - max = "1440" - } - } - - div("form-switch-group") { - div("form-group form-switch") { - input( - name = "projector", - classes = "form-control", - type = InputType.checkBox - ) { - id = "projector" - checked = editWorkGroup.projector - } - label { - htmlFor = "projector" - +"Projector" - } - } - div("form-group form-switch") { - input( - name = "resolution", - classes = "form-control", - type = InputType.checkBox - ) { - id = "resolution" - checked = editWorkGroup.resolution - } - label { - htmlFor = "resolution" - +"Resolution" - } - } - } - - div("form-group") { - a("/workgroup") { - button(classes = "form-btn") { - +"Cancel" - } - } - button(type = ButtonType.submit, classes = "form-btn btn-primary") { - +"Save" - } - } - } - a("/workgroup/${editWorkGroup.id}/delete") { - button(classes = "form-btn btn-danger") { - +"Delete" - } - } - } - } - } - } - - post { workGroupId -> - val user = call.sessions.get()?.getUser(call) - if (user == null || !user.checkPermission(Permission.WORK_GROUP)) { - call.respondRedirect("/login?${LocationLogin::next.name}=${call.request.path()}}") - } else { - val params = call.receiveParameters().toMap().mapValues { (_, list) -> - list.firstOrNull() - } - val editWorkGroup = WorkGroup.get(workGroupId.id) ?: return@post - - params["name"]?.let { editWorkGroup.name = it } - params["interested"]?.toIntOrNull()?.let { editWorkGroup.interested = it } - params["track"]?.toIntOrNull()?.let { editWorkGroup.trackId = it } - params["projector"]?.let { editWorkGroup.projector = it == "on" } - params["resolution"]?.let { editWorkGroup.resolution = it == "on" } - params["length"]?.toIntOrNull()?.let { editWorkGroup.length = it } - - editWorkGroup.save() - - call.respondRedirect("/workgroup") - } - } - - get { - val user = call.sessions.get()?.getUser(call) - if (user == null || !user.checkPermission(Permission.WORK_GROUP)) { - call.respondRedirect("/login?${LocationLogin::next.name}=${call.request.path()}}") - } else { - call.respondHtmlTemplate(MainTemplate()) { - menuTemplate { - this.user = user - active = MenuTemplate.Tab.WORK_GROUP - } - content { - h1 { +"Create work group" } - form(method = FormMethod.post) { - div("form-group") { - label { - htmlFor = "name" - +"Name" - } - input( - name = "name", - classes = "form-control" - ) { - id = "name" - placeholder = "Name" - value = "" - } - } - div("form-group") { - label { - htmlFor = "interested" - +"Interested" - } - input( - name = "interested", - classes = "form-control", - type = InputType.number - ) { - id = "interested" - value = "0" - - min = "0" - max = "1337" - } - } - div("form-group") { - label { - htmlFor = "track" - +"Track" - } - input( - name = "track", - classes = "form-control", - type = InputType.number - ) { - id = "track" - value = "" - - min = "0" - max = "1337" - } - } - div("form-group") { - label { - htmlFor = "length" - +"Length" - } - input( - name = "length", - classes = "form-control", - type = InputType.number - ) { - id = "length" - value = "0" - - min = "0" - max = "1440" - } - } - - div("form-switch-group") { - div("form-group form-switch") { - input( - name = "projector", - classes = "form-control", - type = InputType.checkBox - ) { - id = "projector" - checked = false - } - label { - htmlFor = "projector" - +"Projector" - } - } - div("form-group form-switch") { - input( - name = "resolution", - classes = "form-control", - type = InputType.checkBox - ) { - id = "resolution" - checked = false - } - label { - htmlFor = "resolution" - +"Resolution" - } - } - } - - div("form-group") { - a("/workgroup") { - button(classes = "form-btn") { - +"Cancel" - } - } - button(type = ButtonType.submit, classes = "form-btn btn-primary") { - +"Create" - } - } - } - } - } - } - } - - post { - val user = call.sessions.get()?.getUser(call) - if (user == null || !user.checkPermission(Permission.WORK_GROUP)) { - call.respondRedirect("/login?${LocationLogin::next.name}=${call.request.path()}}") - } else { - val params = call.receiveParameters().toMap().mapValues { (_, list) -> - list.firstOrNull() - } - - val name = params["name"] ?: return@post - val interested = (params["interested"] ?: return@post).toIntOrNull() ?: 0 - val trackId = (params["track"] ?: return@post).toIntOrNull() - val projector = params["projector"] == "on" - val resolution = params["resolution"] == "on" - val length = (params["length"] ?: return@post).toIntOrNull() ?: 0 - - WorkGroup( - name = name, - interested = interested, - trackId = trackId, - projector = projector, - resolution = resolution, - length = length - ).save() - - call.respondRedirect("/workgroup") - } - } - - get { workGroupId -> - val user = call.sessions.get()?.getUser(call) - if (user == null || !user.checkPermission(Permission.WORK_GROUP)) { - call.respondRedirect("/login?${LocationLogin::next.name}=${call.request.path()}}") - } else { - val deleteWorkGroup = WorkGroup.get(workGroupId.id) ?: return@get - - deleteWorkGroup.delete() - - call.respondRedirect("/workgroup") - } - } -} diff --git a/src/jvmMain/kotlin/de/kif/backend/util/Search.kt b/src/jvmMain/kotlin/de/kif/backend/util/Search.kt deleted file mode 100644 index 5467a32..0000000 --- a/src/jvmMain/kotlin/de/kif/backend/util/Search.kt +++ /dev/null @@ -1,29 +0,0 @@ -package de.kif.backend.util - -object Search { - private fun permute(list: List): List> { - if (list.size <= 1) return listOf(list) - - val perm = mutableListOf>() - - for (elem in list) { - val p = permute(list - elem) - - for (x in p) { - perm += x + elem - } - } - - return perm - } - - fun match(search: String, vararg params: String): Boolean { - val s = search.toLowerCase().replace(" ", "") - - return permute(params.map { it.toLowerCase().replace(" ", "") }).any { - it.joinToString("").contains(s) - } - } - - fun pack(vararg params: String): String = params.joinToString("|") { it.toLowerCase() } -} diff --git a/src/jvmMain/kotlin/de/kif/backend/view/MainTemplate.kt b/src/jvmMain/kotlin/de/kif/backend/view/MainTemplate.kt deleted file mode 100644 index abff722..0000000 --- a/src/jvmMain/kotlin/de/kif/backend/view/MainTemplate.kt +++ /dev/null @@ -1,43 +0,0 @@ -package de.kif.backend.view - -import io.ktor.html.Placeholder -import io.ktor.html.Template -import io.ktor.html.TemplatePlaceholder -import io.ktor.html.insert -import kotlinx.html.* - -class MainTemplate : Template { - val content = Placeholder() - val menuTemplate =TemplatePlaceholder() - - override fun HTML.apply() { - head { - meta(charset = "utf-8") - meta(name="viewport",content = "width=device-width, initial-scale=1.0") - - title("KIF Portal") - - link(href = "/static/external/material-icons.css", type = LinkType.textCss, rel = LinkRel.stylesheet) - link(href = "/static/external/font/Montserrat.css", type = LinkType.textCss, rel = LinkRel.stylesheet) - link(href = "https://fonts.googleapis.com/css?family=Bungee|Oswald", type = LinkType.textCss, rel = LinkRel.stylesheet) - link(href = "/static/style/style.css", type = LinkType.textCss, rel = LinkRel.stylesheet) - - script(src = "/static/require.min.js") {} - - /*script { - unsafe { - +"require.config({baseUrl: '/static'});\n" - +("require([${Resources.jsModules}]);\n") - } - }*/ - } - body { - insert(MenuTemplate(), menuTemplate) - div("container") { - div("main") { - insert(content) - } - } - } - } -} diff --git a/src/jvmMain/kotlin/de/kif/backend/view/MenuTemplate.kt b/src/jvmMain/kotlin/de/kif/backend/view/MenuTemplate.kt deleted file mode 100644 index 89e91a0..0000000 --- a/src/jvmMain/kotlin/de/kif/backend/view/MenuTemplate.kt +++ /dev/null @@ -1,77 +0,0 @@ -package de.kif.backend.view - -import de.kif.backend.model.Permission -import de.kif.backend.model.User -import io.ktor.html.Template -import kotlinx.html.* - -class MenuTemplate() : Template { - - var setup = false - var active: Tab = Tab.DASHBOARD - var user: User? = null - - override fun FlowContent.apply() { - nav("menu") { - div("container") { - div("menu-left") { - if (setup) { - a(classes = "active") { - +"Setup" - } - } else { - a("/", classes = if (active == Tab.DASHBOARD) "active" else null) { - +"Dashboard" - } - a("/calendar", classes = if (active == Tab.CALENDAR) "active" else null) { - +"Calendar" - } - } - } - if (!setup) { - div("menu-right") { - span("menu-icon") { - i("material-icons") { +"menu" } - } - val user = user - div("menu-content") { - if (user == null) { - a("/account", classes = if (active == Tab.ACCOUNT) "active" else null) { - +"Login" - } - } else { - if (user.checkPermission(Permission.WORK_GROUP)) { - a("/workgroup", classes = if (active == Tab.WORK_GROUP) "active" else null) { - +"Work groups" - } - } - if (user.checkPermission(Permission.ROOM)) { - a("/room", classes = if (active == Tab.ROOM) "active" else null) { - +"Rooms" - } - } - if (user.checkPermission(Permission.PERSON)) { - a("/person", classes = if (active == Tab.PERSON) "active" else null) { - +"Persons" - } - } - if (user.checkPermission(Permission.PERSON)) { - a("/user", classes = if (active == Tab.USER) "active" else null) { - +"Users" - } - } - a("/account", classes = if (active == Tab.ACCOUNT) "active" else null) { - +user.username - } - } - } - } - } - } - } - } - - enum class Tab { - DASHBOARD, CALENDAR, ACCOUNT, WORK_GROUP, ROOM, PERSON, USER - } -} diff --git a/src/jvmMain/kotlin/de/kif/backend/view/TableTemplate.kt b/src/jvmMain/kotlin/de/kif/backend/view/TableTemplate.kt deleted file mode 100644 index 2d76c41..0000000 --- a/src/jvmMain/kotlin/de/kif/backend/view/TableTemplate.kt +++ /dev/null @@ -1,42 +0,0 @@ -package de.kif.backend.view - -import io.ktor.html.* -import kotlinx.html.* - - -class TableTemplate() : Template { - - var searchValue = "" - - val action = Placeholder() - val header = Placeholder() - val entry = PlaceholderList() - - override fun FlowContent.apply() { - div("table-layout") { - form(classes = "form-group table-layout-search") { - input(InputType.search, name = "search", classes = "form-control") { - placeholder = "Search" - value = searchValue - } - button(type = ButtonType.submit, classes = "form-btn btn-search") { - i("material-icons") { +"search" } - } - } - div("table-layout-action") { - insert(action) - } - - } - table("table-layout-table") { - tr { - insert(header) - } - each(entry) { - tr { - insert(it) - } - } - } - } -} diff --git a/src/jvmMain/resources/logback.xml b/src/jvmMain/resources/logback.xml deleted file mode 100644 index 57a363c..0000000 --- a/src/jvmMain/resources/logback.xml +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - true - - %d{HH:mm:ss.SSS} [%thread] %highlight(%-5level) %cyan(%logger{20}) - %msg %n - - - - - - -