From f68e210ed8e988113aa99549fc5d8f7ef03a24bd Mon Sep 17 00:00:00 2001 From: Christos Malliaridis Date: Fri, 28 Jun 2024 13:13:45 +0200 Subject: [PATCH 01/66] Introduce libs.versions.toml --- gradle/libs.versions.toml | 40 +++++++++++++++++++++++++++++++++++++++ solr/api/build.gradle | 11 ++++++++--- solr/solrj/build.gradle | 2 +- 3 files changed, 49 insertions(+), 4 deletions(-) create mode 100644 gradle/libs.versions.toml diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml new file mode 100644 index 00000000000..840edcfb6aa --- /dev/null +++ b/gradle/libs.versions.toml @@ -0,0 +1,40 @@ +[versions] + +agp = "8.0.2" +android-compileSdk = "33" +android-minSdk = "24" +common-custom-user-data = "1.12" +fasterxml = "2.17.1" +gradle-enterprise = "3.15.1" +jakarta = "3.1.0" +kotlin = "1.9.23" +kotlinx-serialization = "1.6.3" +nexus-publish = "2.0.0-rc-1" +openapi = "7.6.0" +slf4j = "2.0.12" +semver4j = "5.3.0" +swagger3 = "2.2.22" + +[plugins] + +androidLibrary = { id = "com.android.library", version.ref = "agp" } +commonCustomUserData = { id = "com.gradle.common-custom-user-data-gradle-plugin", version.ref = "common-custom-user-data" } +gradleEnterprise = { id = "com.gradle.enterprise", version.ref = "gradle-enterprise" } +kotlinMultiplatform = { id = "org.jetbrains.kotlin.multiplatform", version.ref = "kotlin" } +kotlinSerialization = { id = "org.jetbrains.kotlin.plugin.serialization", version.ref = "kotlin" } +openapiGenerator = { id = "org.openapi.generator", version.ref = "openapi" } +swagger3Core = { id = "io.swagger.core.v3.swagger-gradle-plugin", version.ref = "swagger3" } + +[libraries] + +jakarta-rsApi = { group = "jakarta.ws.rs", name = "jakarta.ws.rs-api", version.ref = "jakarta" } +nexus-publish = { group = "io.github.gradle-nexus.publish-plugin", name = "io.github.gradle-nexus.publish-plugin.gradle.plugin", version.ref = "nexus-publish" } +slf4j-api = { group = "org.slf4j", name = "slf4j-api", version.ref = "slf4j" } +fasterxml-jackson-annotations = { group = "com.fasterxml.jackson.core", name = "jackson-annotations", version.ref = "fasterxml" } +kotlin-stdlib = { group = "org.jetbrains.kotlin", name = "kotlin-stdlib", version.ref = "kotlin" } +kotlin-test = { group = "org.jetbrains.kotlin", name = "kotlin-test", version.ref = "kotlin" } +kotlinx-serialization-core = { group = "org.jetbrains.kotlinx", name = "kotlinx-serialization-core", version.ref = "kotlinx-serialization" } +kotlinx-serialization-json = { group = "org.jetbrains.kotlinx", name = "kotlinx-serialization-json", version.ref = "kotlinx-serialization" } +semver4j-semver4j = { group = "org.semver4j", name = "semver4j", version.ref = "semver4j" } +swagger3-annotations-jakarta = { group = "io.swagger.core.v3", name = "swagger-annotations-jakarta", version.ref = "swagger3" } +swagger3-jaxrs2-jakarta = { group = "io.swagger.core.v3", name = "swagger-jaxrs2-jakarta", version.ref = "swagger3" } diff --git a/solr/api/build.gradle b/solr/api/build.gradle index 1f8118116c6..7372e96b252 100644 --- a/solr/api/build.gradle +++ b/solr/api/build.gradle @@ -1,3 +1,5 @@ +import io.swagger.v3.plugins.gradle.tasks.ResolveTask + /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with @@ -16,8 +18,8 @@ */ plugins { - id 'io.swagger.core.v3.swagger-gradle-plugin' version '2.2.2' - id "org.openapi.generator" version "6.0.1" + alias(libs.plugins.swagger3Core) + alias(libs.plugins.openapiGenerator) } apply plugin: 'java-library' @@ -45,7 +47,9 @@ configurations { canBeResolved = false } - swaggerBuild.extendsFrom implementation + swaggerBuild { + extendsFrom implementation + } } resolve { @@ -55,6 +59,7 @@ resolve { outputDir = file(project.openApiSpecDir) outputFileName = "solr-openapi-${version}" prettyPrint = true + outputFormat = ResolveTask.Format.JSONANDYAML } dependencies { diff --git a/solr/solrj/build.gradle b/solr/solrj/build.gradle index dc1656a4624..15a0411f6fd 100644 --- a/solr/solrj/build.gradle +++ b/solr/solrj/build.gradle @@ -16,7 +16,7 @@ */ plugins { - id "org.openapi.generator" version "6.6.0" + alias(libs.plugins.openapiGenerator) } apply plugin: 'java-library' From 5308579806f5a0c46402dcd8354ddb1f5cae8e26 Mon Sep 17 00:00:00 2001 From: Christos Malliaridis Date: Sat, 29 Jun 2024 15:08:20 +0200 Subject: [PATCH 02/66] Add basic Compose integration example for webapp This commit creates a new module in Solr that sets up a frontend written with Compose and targeting browser (WASM) and desktop (JVM). The webapp is modified so that it opens the WASM Compose app when accessing /solr/compose. IMPORTANT: The jetty configuration is updated to include script-src: 'wasm-unsafe-eval' to allow WASM code execution which may be considered a security issue. --- .gitignore | 3 + build.gradle | 18 +- gradle/libs.versions.toml | 31 +- kotlin-js-store/yarn.lock | 3092 +++++++++++++++++ settings.gradle | 2 + solr/compose-ui/build.gradle.kts | 126 + .../components/root/RootComponent.kt | 20 + .../root/integration/DefaultRootComponent.kt | 29 + .../solr/composeui/ui/root/RootContent.kt | 35 + .../apache/solr/composeui/ui/theme/Colors.kt | 20 + .../apache/solr/composeui/ui/theme/Fonts.kt | 29 + .../apache/solr/composeui/ui/theme/Shapes.kt | 31 + .../apache/solr/composeui/ui/theme/Theme.kt | 48 + .../composeui/utils/AppComponentContext.kt | 26 + .../composeui/utils/CoroutineContextOwner.kt | 37 + .../utils/DefaultAppComponentContext.kt | 56 + .../kotlin/org/apache/solr/composeui/Main.kt | 83 + .../kotlin/org/apache/solr/composeui/Utils.kt | 45 + .../kotlin/org/apache/solr/composeui/Main.kt | 65 + .../src/wasmJsMain/resources/index.html | 12 + .../src/wasmJsMain/resources/styles.css | 7 + .../solr/servlet/LoadAdminUiServlet.java | 2 +- solr/server/etc/jetty.xml | 2 +- solr/webapp/build.gradle | 12 + solr/webapp/web/js/angular/app.js | 3 + 25 files changed, 3824 insertions(+), 10 deletions(-) create mode 100644 kotlin-js-store/yarn.lock create mode 100644 solr/compose-ui/build.gradle.kts create mode 100644 solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/components/root/RootComponent.kt create mode 100644 solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/components/root/integration/DefaultRootComponent.kt create mode 100644 solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/ui/root/RootContent.kt create mode 100644 solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/ui/theme/Colors.kt create mode 100644 solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/ui/theme/Fonts.kt create mode 100644 solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/ui/theme/Shapes.kt create mode 100644 solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/ui/theme/Theme.kt create mode 100644 solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/utils/AppComponentContext.kt create mode 100644 solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/utils/CoroutineContextOwner.kt create mode 100644 solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/utils/DefaultAppComponentContext.kt create mode 100644 solr/compose-ui/src/desktopMain/kotlin/org/apache/solr/composeui/Main.kt create mode 100644 solr/compose-ui/src/desktopMain/kotlin/org/apache/solr/composeui/Utils.kt create mode 100644 solr/compose-ui/src/wasmJsMain/kotlin/org/apache/solr/composeui/Main.kt create mode 100644 solr/compose-ui/src/wasmJsMain/resources/index.html create mode 100644 solr/compose-ui/src/wasmJsMain/resources/styles.css diff --git a/.gitignore b/.gitignore index 8f874d5c087..42f1ceec7f3 100644 --- a/.gitignore +++ b/.gitignore @@ -36,6 +36,9 @@ __pycache__ gradle/wrapper/gradle-wrapper.jar .gradletasknamecache +# Kotlin +.kotlin/ + # WANT TO ADD MORE? You can tell Git without adding to this file: # See https://git-scm.com/docs/gitignore # In particular, if you have tools you use, add to $GIT_DIR/info/exclude or use core.excludesFile \ No newline at end of file diff --git a/build.gradle b/build.gradle index 3cecb1aa0cd..b7ca805d4e4 100644 --- a/build.gradle +++ b/build.gradle @@ -21,6 +21,8 @@ import java.time.format.DateTimeFormatter plugins { id 'base' id 'solr.build-infra' + alias(libs.plugins.kotlinMultiplatform) apply false + alias(libs.plugins.jetbrainsCompose) apply false id 'com.palantir.consistent-versions' version '2.16.0' id 'org.owasp.dependencycheck' version '9.0.8' id 'ca.cutterslade.analyze' version '1.10.0' @@ -31,6 +33,18 @@ plugins { id 'com.github.node-gradle.node' version '7.0.1' apply false } +allprojects { + repositories { + mavenCentral() + maven { + url = "https://maven.pkg.jetbrains.space/public/p/compose/dev" + } + maven { + url = "https://maven.pkg.jetbrains.space/kotlin/p/wasm/experimental" + } + } +} + apply from: file('build-tools/scriptDepVersions.gradle') // Declare default Java versions for the entire project and for SolrJ separately @@ -206,8 +220,8 @@ apply from: file('gradle/hacks/gradle-archives.gradle') apply from: file('gradle/hacks/wipe-temp.gradle') apply from: file('gradle/hacks/hashmapAssertions.gradle') -apply from: file('gradle/hacks/turbocharge-jvm-opts.gradle') -apply from: file('gradle/hacks/dummy-outputs.gradle') +//apply from: file('gradle/hacks/turbocharge-jvm-opts.gradle') +//apply from: file('gradle/hacks/dummy-outputs.gradle') apply from: file('gradle/solr/packaging.gradle') apply from: file('gradle/solr/solr-forbidden-apis.gradle') diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 840edcfb6aa..72f85e74f0f 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -1,25 +1,31 @@ [versions] -agp = "8.0.2" -android-compileSdk = "33" -android-minSdk = "24" common-custom-user-data = "1.12" +compose = "1.6.11" +decompose = "3.1.0" +essenty = "2.1.0" fasterxml = "2.17.1" gradle-enterprise = "3.15.1" jakarta = "3.1.0" -kotlin = "1.9.23" +kotlin = "2.0.0" +kotlinx-coroutines = "1.9.0-RC" +kotlinx-datetime = "0.6.0" kotlinx-serialization = "1.6.3" +ktor = "3.0.0-wasm2" +mvikotlin = "4.1.0" nexus-publish = "2.0.0-rc-1" openapi = "7.6.0" -slf4j = "2.0.12" +oshai-logging = "7.0.0" semver4j = "5.3.0" +slf4j = "2.0.12" swagger3 = "2.2.22" [plugins] -androidLibrary = { id = "com.android.library", version.ref = "agp" } commonCustomUserData = { id = "com.gradle.common-custom-user-data-gradle-plugin", version.ref = "common-custom-user-data" } +compose-compiler = { id = "org.jetbrains.kotlin.plugin.compose", version.ref = "kotlin" } gradleEnterprise = { id = "com.gradle.enterprise", version.ref = "gradle-enterprise" } +jetbrainsCompose = { id = "org.jetbrains.compose", version.ref = "compose" } kotlinMultiplatform = { id = "org.jetbrains.kotlin.multiplatform", version.ref = "kotlin" } kotlinSerialization = { id = "org.jetbrains.kotlin.plugin.serialization", version.ref = "kotlin" } openapiGenerator = { id = "org.openapi.generator", version.ref = "openapi" } @@ -27,14 +33,27 @@ swagger3Core = { id = "io.swagger.core.v3.swagger-gradle-plugin", version.ref = [libraries] +decompose-decompose = { group = "com.arkivanov.decompose", name = "decompose", version.ref = "decompose" } +decompose-extensions-compose = { group = "com.arkivanov.decompose", name = "extensions-compose", version.ref = "decompose" } +essenty-lifecycle = { group = "com.arkivanov.essenty", name = "lifecycle", version.ref = "essenty" } jakarta-rsApi = { group = "jakarta.ws.rs", name = "jakarta.ws.rs-api", version.ref = "jakarta" } nexus-publish = { group = "io.github.gradle-nexus.publish-plugin", name = "io.github.gradle-nexus.publish-plugin.gradle.plugin", version.ref = "nexus-publish" } slf4j-api = { group = "org.slf4j", name = "slf4j-api", version.ref = "slf4j" } fasterxml-jackson-annotations = { group = "com.fasterxml.jackson.core", name = "jackson-annotations", version.ref = "fasterxml" } kotlin-stdlib = { group = "org.jetbrains.kotlin", name = "kotlin-stdlib", version.ref = "kotlin" } kotlin-test = { group = "org.jetbrains.kotlin", name = "kotlin-test", version.ref = "kotlin" } +kotlinx-datetime = { group = "org.jetbrains.kotlinx", name = "kotlinx-datetime", version.ref = "kotlinx-datetime" } kotlinx-serialization-core = { group = "org.jetbrains.kotlinx", name = "kotlinx-serialization-core", version.ref = "kotlinx-serialization" } kotlinx-serialization-json = { group = "org.jetbrains.kotlinx", name = "kotlinx-serialization-json", version.ref = "kotlinx-serialization" } +ktor-client-core = { group = "io.ktor", name = "ktor-client-core", version.ref = "ktor" } +ktor-client-cio = { group = "io.ktor", name = "ktor-client-cio", version.ref = "ktor" } +ktor-client-js = { group = "io.ktor", name = "ktor-client-js", version.ref = "ktor" } +mvikotlin-extensions-coroutines = { group = "com.arkivanov.mvikotlin", name = "mvikotlin-extensions-coroutines", version.ref = "mvikotlin" } +mvikotlin-logging = { group = "com.arkivanov.mvikotlin", name = "mvikotlin-logging", version.ref = "mvikotlin" } +mvikotlin-main = { group = "com.arkivanov.mvikotlin", name = "mvikotlin-main", version.ref = "mvikotlin" } +mvikotlin-mvikotlin = { group = "com.arkivanov.mvikotlin", name = "mvikotlin", version.ref = "mvikotlin" } +mvikotlin-timetravel = { group = "com.arkivanov.mvikotlin", name = "mvikotlin-timetravel", version.ref = "mvikotlin" } +oshai-logging = { group = "io.github.oshai", name = "kotlin-logging", version.ref = "oshai-logging" } semver4j-semver4j = { group = "org.semver4j", name = "semver4j", version.ref = "semver4j" } swagger3-annotations-jakarta = { group = "io.swagger.core.v3", name = "swagger-annotations-jakarta", version.ref = "swagger3" } swagger3-jaxrs2-jakarta = { group = "io.swagger.core.v3", name = "swagger-jaxrs2-jakarta", version.ref = "swagger3" } diff --git a/kotlin-js-store/yarn.lock b/kotlin-js-store/yarn.lock new file mode 100644 index 00000000000..62954ba92f2 --- /dev/null +++ b/kotlin-js-store/yarn.lock @@ -0,0 +1,3092 @@ +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + + +"@colors/colors@1.5.0": + version "1.5.0" + resolved "https://registry.yarnpkg.com/@colors/colors/-/colors-1.5.0.tgz#bb504579c1cae923e6576a4f5da43d25f97bdbd9" + integrity sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ== + +"@discoveryjs/json-ext@^0.5.0": + version "0.5.7" + resolved "https://registry.yarnpkg.com/@discoveryjs/json-ext/-/json-ext-0.5.7.tgz#1d572bfbbe14b7704e0ba0f39b74815b84870d70" + integrity sha512-dBVuXR082gk3jsFp7Rd/JI4kytwGHecnCoTtXFb7DB6CNHp4rg5k1bhg0nWdLGLnOV71lmDzGQaLMy8iPLY0pw== + +"@isaacs/cliui@^8.0.2": + version "8.0.2" + resolved "https://registry.yarnpkg.com/@isaacs/cliui/-/cliui-8.0.2.tgz#b37667b7bc181c168782259bab42474fbf52b550" + integrity sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA== + dependencies: + string-width "^5.1.2" + string-width-cjs "npm:string-width@^4.2.0" + strip-ansi "^7.0.1" + strip-ansi-cjs "npm:strip-ansi@^6.0.1" + wrap-ansi "^8.1.0" + wrap-ansi-cjs "npm:wrap-ansi@^7.0.0" + +"@jridgewell/gen-mapping@^0.3.5": + version "0.3.5" + resolved "https://registry.yarnpkg.com/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz#dcce6aff74bdf6dad1a95802b69b04a2fcb1fb36" + integrity sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg== + dependencies: + "@jridgewell/set-array" "^1.2.1" + "@jridgewell/sourcemap-codec" "^1.4.10" + "@jridgewell/trace-mapping" "^0.3.24" + +"@jridgewell/resolve-uri@^3.1.0": + version "3.1.2" + resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz#7a0ee601f60f99a20c7c7c5ff0c80388c1189bd6" + integrity sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw== + +"@jridgewell/set-array@^1.2.1": + version "1.2.1" + resolved "https://registry.yarnpkg.com/@jridgewell/set-array/-/set-array-1.2.1.tgz#558fb6472ed16a4c850b889530e6b36438c49280" + integrity sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A== + +"@jridgewell/source-map@^0.3.3": + version "0.3.6" + resolved "https://registry.yarnpkg.com/@jridgewell/source-map/-/source-map-0.3.6.tgz#9d71ca886e32502eb9362c9a74a46787c36df81a" + integrity sha512-1ZJTZebgqllO79ue2bm3rIGud/bOe0pP5BjSRCRxxYkEZS8STV7zN84UBbiYu7jy+eCKSnVIUgoWWE/tt+shMQ== + dependencies: + "@jridgewell/gen-mapping" "^0.3.5" + "@jridgewell/trace-mapping" "^0.3.25" + +"@jridgewell/sourcemap-codec@^1.4.10", "@jridgewell/sourcemap-codec@^1.4.14": + version "1.4.15" + resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz#d7c6e6755c78567a951e04ab52ef0fd26de59f32" + integrity sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg== + +"@jridgewell/trace-mapping@^0.3.20", "@jridgewell/trace-mapping@^0.3.24", "@jridgewell/trace-mapping@^0.3.25": + version "0.3.25" + resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz#15f190e98895f3fc23276ee14bc76b675c2e50f0" + integrity sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ== + dependencies: + "@jridgewell/resolve-uri" "^3.1.0" + "@jridgewell/sourcemap-codec" "^1.4.14" + +"@js-joda/core@3.2.0": + version "3.2.0" + resolved "https://registry.yarnpkg.com/@js-joda/core/-/core-3.2.0.tgz#3e61e21b7b2b8a6be746df1335cf91d70db2a273" + integrity sha512-PMqgJ0sw5B7FKb2d5bWYIoxjri+QlW/Pys7+Rw82jSH0QN3rB05jZ/VrrsUdh1w4+i2kw9JOejXGq/KhDOX7Kg== + +"@jsonjoy.com/base64@^1.1.1": + version "1.1.2" + resolved "https://registry.yarnpkg.com/@jsonjoy.com/base64/-/base64-1.1.2.tgz#cf8ea9dcb849b81c95f14fc0aaa151c6b54d2578" + integrity sha512-q6XAnWQDIMA3+FTiOYajoYqySkO+JSat0ytXGSuRdq9uXE7o92gzuQwQM14xaCRlBLGq3v5miDGC4vkVTn54xA== + +"@jsonjoy.com/json-pack@^1.0.3": + version "1.0.4" + resolved "https://registry.yarnpkg.com/@jsonjoy.com/json-pack/-/json-pack-1.0.4.tgz#ab59c642a2e5368e8bcfd815d817143d4f3035d0" + integrity sha512-aOcSN4MeAtFROysrbqG137b7gaDDSmVrl5mpo6sT/w+kcXpWnzhMjmY/Fh/sDx26NBxyIE7MB1seqLeCAzy9Sg== + dependencies: + "@jsonjoy.com/base64" "^1.1.1" + "@jsonjoy.com/util" "^1.1.2" + hyperdyperid "^1.2.0" + thingies "^1.20.0" + +"@jsonjoy.com/util@^1.1.2": + version "1.2.0" + resolved "https://registry.yarnpkg.com/@jsonjoy.com/util/-/util-1.2.0.tgz#0fe9a92de72308c566ebcebe8b5a3f01d3149df2" + integrity sha512-4B8B+3vFsY4eo33DMKyJPlQ3sBMpPFUZK2dr3O3rXrOGKKbYG44J0XSFkDo1VOQiri5HFEhIeVvItjR2xcazmg== + +"@leichtgewicht/ip-codec@^2.0.1": + version "2.0.5" + resolved "https://registry.yarnpkg.com/@leichtgewicht/ip-codec/-/ip-codec-2.0.5.tgz#4fc56c15c580b9adb7dc3c333a134e540b44bfb1" + integrity sha512-Vo+PSpZG2/fmgmiNzYK9qWRh8h/CHrwD0mo1h1DzL4yzHNSfWYujGTYsWGreD000gcgmZ7K4Ys6Tx9TxtsKdDw== + +"@pkgjs/parseargs@^0.11.0": + version "0.11.0" + resolved "https://registry.yarnpkg.com/@pkgjs/parseargs/-/parseargs-0.11.0.tgz#a77ea742fab25775145434eb1d2328cf5013ac33" + integrity sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg== + +"@socket.io/component-emitter@~3.1.0": + version "3.1.2" + resolved "https://registry.yarnpkg.com/@socket.io/component-emitter/-/component-emitter-3.1.2.tgz#821f8442f4175d8f0467b9daf26e3a18e2d02af2" + integrity sha512-9BCxFwvbGg/RsZK9tjXd8s4UcwR0MWeFQ1XEKIQVVvAGJyINdrqKMcTRyLoK8Rse1GjzLV9cwjWV1olXRWEXVA== + +"@types/body-parser@*": + version "1.19.5" + resolved "https://registry.yarnpkg.com/@types/body-parser/-/body-parser-1.19.5.tgz#04ce9a3b677dc8bd681a17da1ab9835dc9d3ede4" + integrity sha512-fB3Zu92ucau0iQ0JMCFQE7b/dv8Ot07NI3KaZIkIUNXq82k4eBAqUaneXfleGY9JWskeS9y+u0nXMyspcuQrCg== + dependencies: + "@types/connect" "*" + "@types/node" "*" + +"@types/bonjour@^3.5.13": + version "3.5.13" + resolved "https://registry.yarnpkg.com/@types/bonjour/-/bonjour-3.5.13.tgz#adf90ce1a105e81dd1f9c61fdc5afda1bfb92956" + integrity sha512-z9fJ5Im06zvUL548KvYNecEVlA7cVDkGUi6kZusb04mpyEFKCIZJvloCcmpmLaIahDpOQGHaHmG6imtPMmPXGQ== + dependencies: + "@types/node" "*" + +"@types/connect-history-api-fallback@^1.5.4": + version "1.5.4" + resolved "https://registry.yarnpkg.com/@types/connect-history-api-fallback/-/connect-history-api-fallback-1.5.4.tgz#7de71645a103056b48ac3ce07b3520b819c1d5b3" + integrity sha512-n6Cr2xS1h4uAulPRdlw6Jl6s1oG8KrVilPN2yUITEs+K48EzMJJ3W1xy8K5eWuFvjp3R74AOIGSmp2UfBJ8HFw== + dependencies: + "@types/express-serve-static-core" "*" + "@types/node" "*" + +"@types/connect@*": + version "3.4.38" + resolved "https://registry.yarnpkg.com/@types/connect/-/connect-3.4.38.tgz#5ba7f3bc4fbbdeaff8dded952e5ff2cc53f8d858" + integrity sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug== + dependencies: + "@types/node" "*" + +"@types/cookie@^0.4.1": + version "0.4.1" + resolved "https://registry.yarnpkg.com/@types/cookie/-/cookie-0.4.1.tgz#bfd02c1f2224567676c1545199f87c3a861d878d" + integrity sha512-XW/Aa8APYr6jSVVA1y/DEIZX0/GMKLEVekNG727R8cs56ahETkRAy/3DR7+fJyh7oUgGwNQaRfXCun0+KbWY7Q== + +"@types/cors@^2.8.12": + version "2.8.17" + resolved "https://registry.yarnpkg.com/@types/cors/-/cors-2.8.17.tgz#5d718a5e494a8166f569d986794e49c48b216b2b" + integrity sha512-8CGDvrBj1zgo2qE+oS3pOCyYNqCPryMWY2bGfwA0dcfopWGgxs+78df0Rs3rc9THP4JkOhLsAa+15VdpAqkcUA== + dependencies: + "@types/node" "*" + +"@types/eslint-scope@^3.7.3": + version "3.7.7" + resolved "https://registry.yarnpkg.com/@types/eslint-scope/-/eslint-scope-3.7.7.tgz#3108bd5f18b0cdb277c867b3dd449c9ed7079ac5" + integrity sha512-MzMFlSLBqNF2gcHWO0G1vP/YQyfvrxZ0bF+u7mzUdZ1/xK4A4sru+nraZz5i3iEIk1l1uyicaDVTB4QbbEkAYg== + dependencies: + "@types/eslint" "*" + "@types/estree" "*" + +"@types/eslint@*": + version "8.56.10" + resolved "https://registry.yarnpkg.com/@types/eslint/-/eslint-8.56.10.tgz#eb2370a73bf04a901eeba8f22595c7ee0f7eb58d" + integrity sha512-Shavhk87gCtY2fhXDctcfS3e6FdxWkCx1iUZ9eEUbh7rTqlZT0/IzOkCOVt0fCjcFuZ9FPYfuezTBImfHCDBGQ== + dependencies: + "@types/estree" "*" + "@types/json-schema" "*" + +"@types/estree@*", "@types/estree@^1.0.5": + version "1.0.5" + resolved "https://registry.yarnpkg.com/@types/estree/-/estree-1.0.5.tgz#a6ce3e556e00fd9895dd872dd172ad0d4bd687f4" + integrity sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw== + +"@types/express-serve-static-core@*", "@types/express-serve-static-core@^4.17.33": + version "4.19.5" + resolved "https://registry.yarnpkg.com/@types/express-serve-static-core/-/express-serve-static-core-4.19.5.tgz#218064e321126fcf9048d1ca25dd2465da55d9c6" + integrity sha512-y6W03tvrACO72aijJ5uF02FRq5cgDR9lUxddQ8vyF+GvmjJQqbzDcJngEjURc+ZsG31VI3hODNZJ2URj86pzmg== + dependencies: + "@types/node" "*" + "@types/qs" "*" + "@types/range-parser" "*" + "@types/send" "*" + +"@types/express@*", "@types/express@^4.17.21": + version "4.17.21" + resolved "https://registry.yarnpkg.com/@types/express/-/express-4.17.21.tgz#c26d4a151e60efe0084b23dc3369ebc631ed192d" + integrity sha512-ejlPM315qwLpaQlQDTjPdsUFSc6ZsP4AN6AlWnogPjQ7CVi7PYF3YVz+CY3jE2pwYf7E/7HlDAN0rV2GxTG0HQ== + dependencies: + "@types/body-parser" "*" + "@types/express-serve-static-core" "^4.17.33" + "@types/qs" "*" + "@types/serve-static" "*" + +"@types/http-errors@*": + version "2.0.4" + resolved "https://registry.yarnpkg.com/@types/http-errors/-/http-errors-2.0.4.tgz#7eb47726c391b7345a6ec35ad7f4de469cf5ba4f" + integrity sha512-D0CFMMtydbJAegzOyHjtiKPLlvnm3iTZyZRSZoLq2mRhDdmLfIWOCYPfQJ4cu2erKghU++QvjcUjp/5h7hESpA== + +"@types/http-proxy@^1.17.8": + version "1.17.14" + resolved "https://registry.yarnpkg.com/@types/http-proxy/-/http-proxy-1.17.14.tgz#57f8ccaa1c1c3780644f8a94f9c6b5000b5e2eec" + integrity sha512-SSrD0c1OQzlFX7pGu1eXxSEjemej64aaNPRhhVYUGqXh0BtldAAx37MG8btcumvpgKyZp1F5Gn3JkktdxiFv6w== + dependencies: + "@types/node" "*" + +"@types/json-schema@*", "@types/json-schema@^7.0.8", "@types/json-schema@^7.0.9": + version "7.0.15" + resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.15.tgz#596a1747233694d50f6ad8a7869fcb6f56cf5841" + integrity sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA== + +"@types/mime@^1": + version "1.3.5" + resolved "https://registry.yarnpkg.com/@types/mime/-/mime-1.3.5.tgz#1ef302e01cf7d2b5a0fa526790c9123bf1d06690" + integrity sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w== + +"@types/node-forge@^1.3.0": + version "1.3.11" + resolved "https://registry.yarnpkg.com/@types/node-forge/-/node-forge-1.3.11.tgz#0972ea538ddb0f4d9c2fa0ec5db5724773a604da" + integrity sha512-FQx220y22OKNTqaByeBGqHWYz4cl94tpcxeFdvBo3wjG6XPBuZ0BNgNZRV5J5TFmmcsJ4IzsLkmGRiQbnYsBEQ== + dependencies: + "@types/node" "*" + +"@types/node@*", "@types/node@>=10.0.0": + version "20.14.9" + resolved "https://registry.yarnpkg.com/@types/node/-/node-20.14.9.tgz#12e8e765ab27f8c421a1820c99f5f313a933b420" + integrity sha512-06OCtnTXtWOZBJlRApleWndH4JsRVs1pDCc8dLSQp+7PpUpX3ePdHyeNSFTeSe7FtKyQkrlPvHwJOW3SLd8Oyg== + dependencies: + undici-types "~5.26.4" + +"@types/qs@*": + version "6.9.15" + resolved "https://registry.yarnpkg.com/@types/qs/-/qs-6.9.15.tgz#adde8a060ec9c305a82de1babc1056e73bd64dce" + integrity sha512-uXHQKES6DQKKCLh441Xv/dwxOq1TVS3JPUMlEqoEglvlhR6Mxnlew/Xq/LRVHpLyk7iK3zODe1qYHIMltO7XGg== + +"@types/range-parser@*": + version "1.2.7" + resolved "https://registry.yarnpkg.com/@types/range-parser/-/range-parser-1.2.7.tgz#50ae4353eaaddc04044279812f52c8c65857dbcb" + integrity sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ== + +"@types/retry@0.12.2": + version "0.12.2" + resolved "https://registry.yarnpkg.com/@types/retry/-/retry-0.12.2.tgz#ed279a64fa438bb69f2480eda44937912bb7480a" + integrity sha512-XISRgDJ2Tc5q4TRqvgJtzsRkFYNJzZrhTdtMoGVBttwzzQJkPnS3WWTFc7kuDRoPtPakl+T+OfdEUjYJj7Jbow== + +"@types/send@*": + version "0.17.4" + resolved "https://registry.yarnpkg.com/@types/send/-/send-0.17.4.tgz#6619cd24e7270793702e4e6a4b958a9010cfc57a" + integrity sha512-x2EM6TJOybec7c52BX0ZspPodMsQUd5L6PRwOunVyVUhXiBSKf3AezDL8Dgvgt5o0UfKNfuA0eMLr2wLT4AiBA== + dependencies: + "@types/mime" "^1" + "@types/node" "*" + +"@types/serve-index@^1.9.4": + version "1.9.4" + resolved "https://registry.yarnpkg.com/@types/serve-index/-/serve-index-1.9.4.tgz#e6ae13d5053cb06ed36392110b4f9a49ac4ec898" + integrity sha512-qLpGZ/c2fhSs5gnYsQxtDEq3Oy8SXPClIXkW5ghvAvsNuVSA8k+gCONcUCS/UjLEYvYps+e8uBtfgXgvhwfNug== + dependencies: + "@types/express" "*" + +"@types/serve-static@*", "@types/serve-static@^1.15.5": + version "1.15.7" + resolved "https://registry.yarnpkg.com/@types/serve-static/-/serve-static-1.15.7.tgz#22174bbd74fb97fe303109738e9b5c2f3064f714" + integrity sha512-W8Ym+h8nhuRwaKPaDw34QUkwsGi6Rc4yYqvKFo5rm2FUEhCFbzVWrxXUxuKK8TASjWsysJY0nsmNCGhCOIsrOw== + dependencies: + "@types/http-errors" "*" + "@types/node" "*" + "@types/send" "*" + +"@types/sockjs@^0.3.36": + version "0.3.36" + resolved "https://registry.yarnpkg.com/@types/sockjs/-/sockjs-0.3.36.tgz#ce322cf07bcc119d4cbf7f88954f3a3bd0f67535" + integrity sha512-MK9V6NzAS1+Ud7JV9lJLFqW85VbC9dq3LmwZCuBe4wBDgKC0Kj/jd8Xl+nSviU+Qc3+m7umHHyHg//2KSa0a0Q== + dependencies: + "@types/node" "*" + +"@types/ws@^8.5.10": + version "8.5.10" + resolved "https://registry.yarnpkg.com/@types/ws/-/ws-8.5.10.tgz#4acfb517970853fa6574a3a6886791d04a396787" + integrity sha512-vmQSUcfalpIq0R9q7uTo2lXs6eGIpt9wtnLdMv9LVpIjCA/+ufZRozlVoVelIYixx1ugCBKDhn89vnsEGOCx9A== + dependencies: + "@types/node" "*" + +"@webassemblyjs/ast@1.12.1", "@webassemblyjs/ast@^1.12.1": + version "1.12.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/ast/-/ast-1.12.1.tgz#bb16a0e8b1914f979f45864c23819cc3e3f0d4bb" + integrity sha512-EKfMUOPRRUTy5UII4qJDGPpqfwjOmZ5jeGFwid9mnoqIFK+e0vqoi1qH56JpmZSzEL53jKnNzScdmftJyG5xWg== + dependencies: + "@webassemblyjs/helper-numbers" "1.11.6" + "@webassemblyjs/helper-wasm-bytecode" "1.11.6" + +"@webassemblyjs/floating-point-hex-parser@1.11.6": + version "1.11.6" + resolved "https://registry.yarnpkg.com/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.6.tgz#dacbcb95aff135c8260f77fa3b4c5fea600a6431" + integrity sha512-ejAj9hfRJ2XMsNHk/v6Fu2dGS+i4UaXBXGemOfQ/JfQ6mdQg/WXtwleQRLLS4OvfDhv8rYnVwH27YJLMyYsxhw== + +"@webassemblyjs/helper-api-error@1.11.6": + version "1.11.6" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.6.tgz#6132f68c4acd59dcd141c44b18cbebbd9f2fa768" + integrity sha512-o0YkoP4pVu4rN8aTJgAyj9hC2Sv5UlkzCHhxqWj8butaLvnpdc2jOwh4ewE6CX0txSfLn/UYaV/pheS2Txg//Q== + +"@webassemblyjs/helper-buffer@1.12.1": + version "1.12.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-buffer/-/helper-buffer-1.12.1.tgz#6df20d272ea5439bf20ab3492b7fb70e9bfcb3f6" + integrity sha512-nzJwQw99DNDKr9BVCOZcLuJJUlqkJh+kVzVl6Fmq/tI5ZtEyWT1KZMyOXltXLZJmDtvLCDgwsyrkohEtopTXCw== + +"@webassemblyjs/helper-numbers@1.11.6": + version "1.11.6" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.6.tgz#cbce5e7e0c1bd32cf4905ae444ef64cea919f1b5" + integrity sha512-vUIhZ8LZoIWHBohiEObxVm6hwP034jwmc9kuq5GdHZH0wiLVLIPcMCdpJzG4C11cHoQ25TFIQj9kaVADVX7N3g== + dependencies: + "@webassemblyjs/floating-point-hex-parser" "1.11.6" + "@webassemblyjs/helper-api-error" "1.11.6" + "@xtuc/long" "4.2.2" + +"@webassemblyjs/helper-wasm-bytecode@1.11.6": + version "1.11.6" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.6.tgz#bb2ebdb3b83aa26d9baad4c46d4315283acd51e9" + integrity sha512-sFFHKwcmBprO9e7Icf0+gddyWYDViL8bpPjJJl0WHxCdETktXdmtWLGVzoHbqUcY4Be1LkNfwTmXOJUFZYSJdA== + +"@webassemblyjs/helper-wasm-section@1.12.1": + version "1.12.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.12.1.tgz#3da623233ae1a60409b509a52ade9bc22a37f7bf" + integrity sha512-Jif4vfB6FJlUlSbgEMHUyk1j234GTNG9dBJ4XJdOySoj518Xj0oGsNi59cUQF4RRMS9ouBUxDDdyBVfPTypa5g== + dependencies: + "@webassemblyjs/ast" "1.12.1" + "@webassemblyjs/helper-buffer" "1.12.1" + "@webassemblyjs/helper-wasm-bytecode" "1.11.6" + "@webassemblyjs/wasm-gen" "1.12.1" + +"@webassemblyjs/ieee754@1.11.6": + version "1.11.6" + resolved "https://registry.yarnpkg.com/@webassemblyjs/ieee754/-/ieee754-1.11.6.tgz#bb665c91d0b14fffceb0e38298c329af043c6e3a" + integrity sha512-LM4p2csPNvbij6U1f19v6WR56QZ8JcHg3QIJTlSwzFcmx6WSORicYj6I63f9yU1kEUtrpG+kjkiIAkevHpDXrg== + dependencies: + "@xtuc/ieee754" "^1.2.0" + +"@webassemblyjs/leb128@1.11.6": + version "1.11.6" + resolved "https://registry.yarnpkg.com/@webassemblyjs/leb128/-/leb128-1.11.6.tgz#70e60e5e82f9ac81118bc25381a0b283893240d7" + integrity sha512-m7a0FhE67DQXgouf1tbN5XQcdWoNgaAuoULHIfGFIEVKA6tu/edls6XnIlkmS6FrXAquJRPni3ZZKjw6FSPjPQ== + dependencies: + "@xtuc/long" "4.2.2" + +"@webassemblyjs/utf8@1.11.6": + version "1.11.6" + resolved "https://registry.yarnpkg.com/@webassemblyjs/utf8/-/utf8-1.11.6.tgz#90f8bc34c561595fe156603be7253cdbcd0fab5a" + integrity sha512-vtXf2wTQ3+up9Zsg8sa2yWiQpzSsMyXj0qViVP6xKGCUT8p8YJ6HqI7l5eCnWx1T/FYdsv07HQs2wTFbbof/RA== + +"@webassemblyjs/wasm-edit@^1.12.1": + version "1.12.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-edit/-/wasm-edit-1.12.1.tgz#9f9f3ff52a14c980939be0ef9d5df9ebc678ae3b" + integrity sha512-1DuwbVvADvS5mGnXbE+c9NfA8QRcZ6iKquqjjmR10k6o+zzsRVesil54DKexiowcFCPdr/Q0qaMgB01+SQ1u6g== + dependencies: + "@webassemblyjs/ast" "1.12.1" + "@webassemblyjs/helper-buffer" "1.12.1" + "@webassemblyjs/helper-wasm-bytecode" "1.11.6" + "@webassemblyjs/helper-wasm-section" "1.12.1" + "@webassemblyjs/wasm-gen" "1.12.1" + "@webassemblyjs/wasm-opt" "1.12.1" + "@webassemblyjs/wasm-parser" "1.12.1" + "@webassemblyjs/wast-printer" "1.12.1" + +"@webassemblyjs/wasm-gen@1.12.1": + version "1.12.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-gen/-/wasm-gen-1.12.1.tgz#a6520601da1b5700448273666a71ad0a45d78547" + integrity sha512-TDq4Ojh9fcohAw6OIMXqiIcTq5KUXTGRkVxbSo1hQnSy6lAM5GSdfwWeSxpAo0YzgsgF182E/U0mDNhuA0tW7w== + dependencies: + "@webassemblyjs/ast" "1.12.1" + "@webassemblyjs/helper-wasm-bytecode" "1.11.6" + "@webassemblyjs/ieee754" "1.11.6" + "@webassemblyjs/leb128" "1.11.6" + "@webassemblyjs/utf8" "1.11.6" + +"@webassemblyjs/wasm-opt@1.12.1": + version "1.12.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-opt/-/wasm-opt-1.12.1.tgz#9e6e81475dfcfb62dab574ac2dda38226c232bc5" + integrity sha512-Jg99j/2gG2iaz3hijw857AVYekZe2SAskcqlWIZXjji5WStnOpVoat3gQfT/Q5tb2djnCjBtMocY/Su1GfxPBg== + dependencies: + "@webassemblyjs/ast" "1.12.1" + "@webassemblyjs/helper-buffer" "1.12.1" + "@webassemblyjs/wasm-gen" "1.12.1" + "@webassemblyjs/wasm-parser" "1.12.1" + +"@webassemblyjs/wasm-parser@1.12.1", "@webassemblyjs/wasm-parser@^1.12.1": + version "1.12.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-parser/-/wasm-parser-1.12.1.tgz#c47acb90e6f083391e3fa61d113650eea1e95937" + integrity sha512-xikIi7c2FHXysxXe3COrVUPSheuBtpcfhbpFj4gmu7KRLYOzANztwUU0IbsqvMqzuNK2+glRGWCEqZo1WCLyAQ== + dependencies: + "@webassemblyjs/ast" "1.12.1" + "@webassemblyjs/helper-api-error" "1.11.6" + "@webassemblyjs/helper-wasm-bytecode" "1.11.6" + "@webassemblyjs/ieee754" "1.11.6" + "@webassemblyjs/leb128" "1.11.6" + "@webassemblyjs/utf8" "1.11.6" + +"@webassemblyjs/wast-printer@1.12.1": + version "1.12.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wast-printer/-/wast-printer-1.12.1.tgz#bcecf661d7d1abdaf989d8341a4833e33e2b31ac" + integrity sha512-+X4WAlOisVWQMikjbcvY2e0rwPsKQ9F688lksZhBcPycBBuii3O7m8FACbDMWDojpAqvjIncrG8J0XHKyQfVeA== + dependencies: + "@webassemblyjs/ast" "1.12.1" + "@xtuc/long" "4.2.2" + +"@webpack-cli/configtest@^2.1.1": + version "2.1.1" + resolved "https://registry.yarnpkg.com/@webpack-cli/configtest/-/configtest-2.1.1.tgz#3b2f852e91dac6e3b85fb2a314fb8bef46d94646" + integrity sha512-wy0mglZpDSiSS0XHrVR+BAdId2+yxPSoJW8fsna3ZpYSlufjvxnP4YbKTCBZnNIcGN4r6ZPXV55X4mYExOfLmw== + +"@webpack-cli/info@^2.0.2": + version "2.0.2" + resolved "https://registry.yarnpkg.com/@webpack-cli/info/-/info-2.0.2.tgz#cc3fbf22efeb88ff62310cf885c5b09f44ae0fdd" + integrity sha512-zLHQdI/Qs1UyT5UBdWNqsARasIA+AaF8t+4u2aS2nEpBQh2mWIVb8qAklq0eUENnC5mOItrIB4LiS9xMtph18A== + +"@webpack-cli/serve@^2.0.5": + version "2.0.5" + resolved "https://registry.yarnpkg.com/@webpack-cli/serve/-/serve-2.0.5.tgz#325db42395cd49fe6c14057f9a900e427df8810e" + integrity sha512-lqaoKnRYBdo1UgDX8uF24AfGMifWK19TxPmM5FHc2vAGxrJ/qtyUyFBWoY1tISZdelsQ5fBcOusifo5o5wSJxQ== + +"@xtuc/ieee754@^1.2.0": + version "1.2.0" + resolved "https://registry.yarnpkg.com/@xtuc/ieee754/-/ieee754-1.2.0.tgz#eef014a3145ae477a1cbc00cd1e552336dceb790" + integrity sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA== + +"@xtuc/long@4.2.2": + version "4.2.2" + resolved "https://registry.yarnpkg.com/@xtuc/long/-/long-4.2.2.tgz#d291c6a4e97989b5c61d9acf396ae4fe133a718d" + integrity sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ== + +abort-controller@3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/abort-controller/-/abort-controller-3.0.0.tgz#eaf54d53b62bae4138e809ca225c8439a6efb392" + integrity sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg== + dependencies: + event-target-shim "^5.0.0" + +accepts@~1.3.4, accepts@~1.3.5, accepts@~1.3.8: + version "1.3.8" + resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.8.tgz#0bf0be125b67014adcb0b0921e62db7bffe16b2e" + integrity sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw== + dependencies: + mime-types "~2.1.34" + negotiator "0.6.3" + +acorn-import-assertions@^1.9.0: + version "1.9.0" + resolved "https://registry.yarnpkg.com/acorn-import-assertions/-/acorn-import-assertions-1.9.0.tgz#507276249d684797c84e0734ef84860334cfb1ac" + integrity sha512-cmMwop9x+8KFhxvKrKfPYmN6/pKTYYHBqLa0DfvVZcKMJWNyWLnaqND7dx/qn66R7ewM1UX5XMaDVP5wlVTaVA== + +acorn@^8.7.1, acorn@^8.8.2: + version "8.12.0" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.12.0.tgz#1627bfa2e058148036133b8d9b51a700663c294c" + integrity sha512-RTvkC4w+KNXrM39/lWCUaG0IbRkWdCv7W/IOW9oU6SawyxulvkQy5HQPVTKxEjczcUvapcrw3cFx/60VN/NRNw== + +ajv-formats@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/ajv-formats/-/ajv-formats-2.1.1.tgz#6e669400659eb74973bbf2e33327180a0996b520" + integrity sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA== + dependencies: + ajv "^8.0.0" + +ajv-keywords@^3.5.2: + version "3.5.2" + resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-3.5.2.tgz#31f29da5ab6e00d1c2d329acf7b5929614d5014d" + integrity sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ== + +ajv-keywords@^5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-5.1.0.tgz#69d4d385a4733cdbeab44964a1170a88f87f0e16" + integrity sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw== + dependencies: + fast-deep-equal "^3.1.3" + +ajv@^6.12.5: + version "6.12.6" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4" + integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g== + dependencies: + fast-deep-equal "^3.1.1" + fast-json-stable-stringify "^2.0.0" + json-schema-traverse "^0.4.1" + uri-js "^4.2.2" + +ajv@^8.0.0, ajv@^8.9.0: + version "8.16.0" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-8.16.0.tgz#22e2a92b94f005f7e0f9c9d39652ef0b8f6f0cb4" + integrity sha512-F0twR8U1ZU67JIEtekUcLkXkoO5mMMmgGD8sK/xUFzJ805jxHQl92hImFAqqXMyMYjSPOyUPAwHYhB72g5sTXw== + dependencies: + fast-deep-equal "^3.1.3" + json-schema-traverse "^1.0.0" + require-from-string "^2.0.2" + uri-js "^4.4.1" + +ansi-colors@4.1.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-4.1.1.tgz#cbb9ae256bf750af1eab344f229aa27fe94ba348" + integrity sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA== + +ansi-html-community@^0.0.8: + version "0.0.8" + resolved "https://registry.yarnpkg.com/ansi-html-community/-/ansi-html-community-0.0.8.tgz#69fbc4d6ccbe383f9736934ae34c3f8290f1bf41" + integrity sha512-1APHAyr3+PCamwNw3bXCPp4HFLONZt/yIH0sZp0/469KWNTEy+qN5jQ3GVX6DMZ1UXAi34yVwtTeaG/HpBuuzw== + +ansi-regex@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304" + integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ== + +ansi-regex@^6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-6.0.1.tgz#3183e38fae9a65d7cb5e53945cd5897d0260a06a" + integrity sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA== + +ansi-styles@^4.0.0, ansi-styles@^4.1.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.3.0.tgz#edd803628ae71c04c85ae7a0906edad34b648937" + integrity sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg== + dependencies: + color-convert "^2.0.1" + +ansi-styles@^6.1.0: + version "6.2.1" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-6.2.1.tgz#0e62320cf99c21afff3b3012192546aacbfb05c5" + integrity sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug== + +anymatch@~3.1.2: + version "3.1.3" + resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.3.tgz#790c58b19ba1720a84205b57c618d5ad8524973e" + integrity sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw== + dependencies: + normalize-path "^3.0.0" + picomatch "^2.0.4" + +argparse@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/argparse/-/argparse-2.0.1.tgz#246f50f3ca78a3240f6c997e8a9bd1eac49e4b38" + integrity sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q== + +array-flatten@1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/array-flatten/-/array-flatten-1.1.1.tgz#9a5f699051b1e7073328f2a008968b64ea2955d2" + integrity sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg== + +balanced-match@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" + integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== + +base64id@2.0.0, base64id@~2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/base64id/-/base64id-2.0.0.tgz#2770ac6bc47d312af97a8bf9a634342e0cd25cb6" + integrity sha512-lGe34o6EHj9y3Kts9R4ZYs/Gr+6N7MCaMlIFA3F1R2O5/m7K06AxfSeO5530PEERE6/WyEg3lsuyw4GHlPZHog== + +batch@0.6.1: + version "0.6.1" + resolved "https://registry.yarnpkg.com/batch/-/batch-0.6.1.tgz#dc34314f4e679318093fc760272525f94bf25c16" + integrity sha512-x+VAiMRL6UPkx+kudNvxTl6hB2XNNCG2r+7wixVfIYwu/2HKRXimwQyaumLjMveWvT2Hkd/cAJw+QBMfJ/EKVw== + +binary-extensions@^2.0.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.3.0.tgz#f6e14a97858d327252200242d4ccfe522c445522" + integrity sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw== + +body-parser@1.20.2, body-parser@^1.19.0: + version "1.20.2" + resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.20.2.tgz#6feb0e21c4724d06de7ff38da36dad4f57a747fd" + integrity sha512-ml9pReCu3M61kGlqoTm2umSXTlRTuGTx0bfYj+uIUKKYycG5NtSbeetV3faSU6R7ajOPw0g/J1PvK4qNy7s5bA== + dependencies: + bytes "3.1.2" + content-type "~1.0.5" + debug "2.6.9" + depd "2.0.0" + destroy "1.2.0" + http-errors "2.0.0" + iconv-lite "0.4.24" + on-finished "2.4.1" + qs "6.11.0" + raw-body "2.5.2" + type-is "~1.6.18" + unpipe "1.0.0" + +bonjour-service@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/bonjour-service/-/bonjour-service-1.2.1.tgz#eb41b3085183df3321da1264719fbada12478d02" + integrity sha512-oSzCS2zV14bh2kji6vNe7vrpJYCHGvcZnlffFQ1MEoX/WOeQ/teD8SYWKR942OI3INjq8OMNJlbPK5LLLUxFDw== + dependencies: + fast-deep-equal "^3.1.3" + multicast-dns "^7.2.5" + +brace-expansion@^1.1.7: + version "1.1.11" + resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" + integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA== + dependencies: + balanced-match "^1.0.0" + concat-map "0.0.1" + +brace-expansion@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-2.0.1.tgz#1edc459e0f0c548486ecf9fc99f2221364b9a0ae" + integrity sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA== + dependencies: + balanced-match "^1.0.0" + +braces@^3.0.2, braces@^3.0.3, braces@~3.0.2: + version "3.0.3" + resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.3.tgz#490332f40919452272d55a8480adc0c441358789" + integrity sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA== + dependencies: + fill-range "^7.1.1" + +browser-stdout@1.3.1: + version "1.3.1" + resolved "https://registry.yarnpkg.com/browser-stdout/-/browser-stdout-1.3.1.tgz#baa559ee14ced73452229bad7326467c61fabd60" + integrity sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw== + +browserslist@^4.21.10: + version "4.23.1" + resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.23.1.tgz#ce4af0534b3d37db5c1a4ca98b9080f985041e96" + integrity sha512-TUfofFo/KsK/bWZ9TWQ5O26tsWW4Uhmt8IYklbnUa70udB6P2wA7w7o4PY4muaEPBQaAX+CEnmmIA41NVHtPVw== + dependencies: + caniuse-lite "^1.0.30001629" + electron-to-chromium "^1.4.796" + node-releases "^2.0.14" + update-browserslist-db "^1.0.16" + +buffer-from@^1.0.0: + version "1.1.2" + resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.2.tgz#2b146a6fd72e80b4f55d255f35ed59a3a9a41bd5" + integrity sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ== + +bundle-name@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/bundle-name/-/bundle-name-4.1.0.tgz#f3b96b34160d6431a19d7688135af7cfb8797889" + integrity sha512-tjwM5exMg6BGRI+kNmTntNsvdZS1X8BFYS6tnJ2hdH0kVxM6/eVZ2xy+FqStSWvYmtfFMDLIxurorHwDKfDz5Q== + dependencies: + run-applescript "^7.0.0" + +bytes@3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.0.0.tgz#d32815404d689699f85a4ea4fa8755dd13a96048" + integrity sha512-pMhOfFDPiv9t5jjIXkHosWmkSyQbvsgEVNkz0ERHbuLh2T/7j4Mqqpz523Fe8MVY89KC6Sh/QfS2sM+SjgFDcw== + +bytes@3.1.2: + version "3.1.2" + resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.1.2.tgz#8b0beeb98605adf1b128fa4386403c009e0221a5" + integrity sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg== + +call-bind@^1.0.7: + version "1.0.7" + resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.7.tgz#06016599c40c56498c18769d2730be242b6fa3b9" + integrity sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w== + dependencies: + es-define-property "^1.0.0" + es-errors "^1.3.0" + function-bind "^1.1.2" + get-intrinsic "^1.2.4" + set-function-length "^1.2.1" + +camelcase@^6.0.0: + version "6.3.0" + resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-6.3.0.tgz#5685b95eb209ac9c0c177467778c9c84df58ba9a" + integrity sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA== + +caniuse-lite@^1.0.30001629: + version "1.0.30001638" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001638.tgz#598e1f0c2ac36f37ebc3f5b8887a32ca558e5d56" + integrity sha512-5SuJUJ7cZnhPpeLHaH0c/HPAnAHZvS6ElWyHK9GSIbVOQABLzowiI2pjmpvZ1WEbkyz46iFd4UXlOHR5SqgfMQ== + +chalk@^4.1.0: + version "4.1.2" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01" + integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA== + dependencies: + ansi-styles "^4.1.0" + supports-color "^7.1.0" + +chokidar@3.5.3: + version "3.5.3" + resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.5.3.tgz#1cf37c8707b932bd1af1ae22c0432e2acd1903bd" + integrity sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw== + dependencies: + anymatch "~3.1.2" + braces "~3.0.2" + glob-parent "~5.1.2" + is-binary-path "~2.1.0" + is-glob "~4.0.1" + normalize-path "~3.0.0" + readdirp "~3.6.0" + optionalDependencies: + fsevents "~2.3.2" + +chokidar@^3.5.1, chokidar@^3.6.0: + version "3.6.0" + resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.6.0.tgz#197c6cc669ef2a8dc5e7b4d97ee4e092c3eb0d5b" + integrity sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw== + dependencies: + anymatch "~3.1.2" + braces "~3.0.2" + glob-parent "~5.1.2" + is-binary-path "~2.1.0" + is-glob "~4.0.1" + normalize-path "~3.0.0" + readdirp "~3.6.0" + optionalDependencies: + fsevents "~2.3.2" + +chrome-trace-event@^1.0.2: + version "1.0.4" + resolved "https://registry.yarnpkg.com/chrome-trace-event/-/chrome-trace-event-1.0.4.tgz#05bffd7ff928465093314708c93bdfa9bd1f0f5b" + integrity sha512-rNjApaLzuwaOTjCiT8lSDdGN1APCiqkChLMJxJPWLunPAt5fy8xgU9/jNOchV84wfIxrA0lRQB7oCT8jrn/wrQ== + +cliui@^7.0.2: + version "7.0.4" + resolved "https://registry.yarnpkg.com/cliui/-/cliui-7.0.4.tgz#a0265ee655476fc807aea9df3df8df7783808b4f" + integrity sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ== + dependencies: + string-width "^4.2.0" + strip-ansi "^6.0.0" + wrap-ansi "^7.0.0" + +clone-deep@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/clone-deep/-/clone-deep-4.0.1.tgz#c19fd9bdbbf85942b4fd979c84dcf7d5f07c2387" + integrity sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ== + dependencies: + is-plain-object "^2.0.4" + kind-of "^6.0.2" + shallow-clone "^3.0.0" + +color-convert@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-2.0.1.tgz#72d3a68d598c9bdb3af2ad1e84f21d896abd4de3" + integrity sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ== + dependencies: + color-name "~1.1.4" + +color-name@~1.1.4: + version "1.1.4" + resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" + integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== + +colorette@^2.0.10, colorette@^2.0.14: + version "2.0.20" + resolved "https://registry.yarnpkg.com/colorette/-/colorette-2.0.20.tgz#9eb793e6833067f7235902fcd3b09917a000a95a" + integrity sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w== + +commander@^10.0.1: + version "10.0.1" + resolved "https://registry.yarnpkg.com/commander/-/commander-10.0.1.tgz#881ee46b4f77d1c1dccc5823433aa39b022cbe06" + integrity sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug== + +commander@^2.20.0: + version "2.20.3" + resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33" + integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ== + +compressible@~2.0.16: + version "2.0.18" + resolved "https://registry.yarnpkg.com/compressible/-/compressible-2.0.18.tgz#af53cca6b070d4c3c0750fbd77286a6d7cc46fba" + integrity sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg== + dependencies: + mime-db ">= 1.43.0 < 2" + +compression@^1.7.4: + version "1.7.4" + resolved "https://registry.yarnpkg.com/compression/-/compression-1.7.4.tgz#95523eff170ca57c29a0ca41e6fe131f41e5bb8f" + integrity sha512-jaSIDzP9pZVS4ZfQ+TzvtiWhdpFhE2RDHz8QJkpX9SIpLq88VueF5jJw6t+6CUQcAoA6t+x89MLrWAqpfDE8iQ== + dependencies: + accepts "~1.3.5" + bytes "3.0.0" + compressible "~2.0.16" + debug "2.6.9" + on-headers "~1.0.2" + safe-buffer "5.1.2" + vary "~1.1.2" + +concat-map@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" + integrity sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg== + +connect-history-api-fallback@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/connect-history-api-fallback/-/connect-history-api-fallback-2.0.0.tgz#647264845251a0daf25b97ce87834cace0f5f1c8" + integrity sha512-U73+6lQFmfiNPrYbXqr6kZ1i1wiRqXnp2nhMsINseWXO8lDau0LGEffJ8kQi4EjLZympVgRdvqjAgiZ1tgzDDA== + +connect@^3.7.0: + version "3.7.0" + resolved "https://registry.yarnpkg.com/connect/-/connect-3.7.0.tgz#5d49348910caa5e07a01800b030d0c35f20484f8" + integrity sha512-ZqRXc+tZukToSNmh5C2iWMSoV3X1YUcPbqEM4DkEG5tNQXrQUZCNVGGv3IuicnkMtPfGf3Xtp8WCXs295iQ1pQ== + dependencies: + debug "2.6.9" + finalhandler "1.1.2" + parseurl "~1.3.3" + utils-merge "1.0.1" + +content-disposition@0.5.4: + version "0.5.4" + resolved "https://registry.yarnpkg.com/content-disposition/-/content-disposition-0.5.4.tgz#8b82b4efac82512a02bb0b1dcec9d2c5e8eb5bfe" + integrity sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ== + dependencies: + safe-buffer "5.2.1" + +content-type@~1.0.4, content-type@~1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.5.tgz#8b773162656d1d1086784c8f23a54ce6d73d7918" + integrity sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA== + +cookie-signature@1.0.6: + version "1.0.6" + resolved "https://registry.yarnpkg.com/cookie-signature/-/cookie-signature-1.0.6.tgz#e303a882b342cc3ee8ca513a79999734dab3ae2c" + integrity sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ== + +cookie@0.6.0: + version "0.6.0" + resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.6.0.tgz#2798b04b071b0ecbff0dbb62a505a8efa4e19051" + integrity sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw== + +cookie@~0.4.1: + version "0.4.2" + resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.4.2.tgz#0e41f24de5ecf317947c82fc789e06a884824432" + integrity sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA== + +core-util-is@~1.0.0: + version "1.0.3" + resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.3.tgz#a6042d3634c2b27e9328f837b965fac83808db85" + integrity sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ== + +cors@~2.8.5: + version "2.8.5" + resolved "https://registry.yarnpkg.com/cors/-/cors-2.8.5.tgz#eac11da51592dd86b9f06f6e7ac293b3df875d29" + integrity sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g== + dependencies: + object-assign "^4" + vary "^1" + +cross-spawn@^7.0.0, cross-spawn@^7.0.3: + version "7.0.3" + resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6" + integrity sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w== + dependencies: + path-key "^3.1.0" + shebang-command "^2.0.0" + which "^2.0.1" + +custom-event@~1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/custom-event/-/custom-event-1.0.1.tgz#5d02a46850adf1b4a317946a3928fccb5bfd0425" + integrity sha512-GAj5FOq0Hd+RsCGVJxZuKaIDXDf3h6GQoNEjFgbLLI/trgtavwUbSnZ5pVfg27DVCaWjIohryS0JFwIJyT2cMg== + +date-format@^4.0.14: + version "4.0.14" + resolved "https://registry.yarnpkg.com/date-format/-/date-format-4.0.14.tgz#7a8e584434fb169a521c8b7aa481f355810d9400" + integrity sha512-39BOQLs9ZjKh0/patS9nrT8wc3ioX3/eA/zgbKNopnF2wCqJEoxywwwElATYvRsXdnOxA/OQeQoFZ3rFjVajhg== + +debug@2.6.9: + version "2.6.9" + resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" + integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA== + dependencies: + ms "2.0.0" + +debug@4.3.4: + version "4.3.4" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865" + integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ== + dependencies: + ms "2.1.2" + +debug@^4.1.0, debug@^4.3.4, debug@~4.3.1, debug@~4.3.2, debug@~4.3.4: + version "4.3.5" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.5.tgz#e83444eceb9fedd4a1da56d671ae2446a01a6e1e" + integrity sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg== + dependencies: + ms "2.1.2" + +decamelize@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-4.0.0.tgz#aa472d7bf660eb15f3494efd531cab7f2a709837" + integrity sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ== + +default-browser-id@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/default-browser-id/-/default-browser-id-5.0.0.tgz#a1d98bf960c15082d8a3fa69e83150ccccc3af26" + integrity sha512-A6p/pu/6fyBcA1TRz/GqWYPViplrftcW2gZC9q79ngNCKAeR/X3gcEdXQHl4KNXV+3wgIJ1CPkJQ3IHM6lcsyA== + +default-browser@^5.2.1: + version "5.2.1" + resolved "https://registry.yarnpkg.com/default-browser/-/default-browser-5.2.1.tgz#7b7ba61204ff3e425b556869ae6d3e9d9f1712cf" + integrity sha512-WY/3TUME0x3KPYdRRxEJJvXRHV4PyPoUsxtZa78lwItwRQRHhd2U9xOscaT/YTf8uCXIAjeJOFBVEh/7FtD8Xg== + dependencies: + bundle-name "^4.1.0" + default-browser-id "^5.0.0" + +default-gateway@^6.0.3: + version "6.0.3" + resolved "https://registry.yarnpkg.com/default-gateway/-/default-gateway-6.0.3.tgz#819494c888053bdb743edbf343d6cdf7f2943a71" + integrity sha512-fwSOJsbbNzZ/CUFpqFBqYfYNLj1NbMPm8MMCIzHjC83iSJRBEGmDUxU+WP661BaBQImeC2yHwXtz+P/O9o+XEg== + dependencies: + execa "^5.0.0" + +define-data-property@^1.1.4: + version "1.1.4" + resolved "https://registry.yarnpkg.com/define-data-property/-/define-data-property-1.1.4.tgz#894dc141bb7d3060ae4366f6a0107e68fbe48c5e" + integrity sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A== + dependencies: + es-define-property "^1.0.0" + es-errors "^1.3.0" + gopd "^1.0.1" + +define-lazy-prop@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/define-lazy-prop/-/define-lazy-prop-3.0.0.tgz#dbb19adfb746d7fc6d734a06b72f4a00d021255f" + integrity sha512-N+MeXYoqr3pOgn8xfyRPREN7gHakLYjhsHhWGT3fWAiL4IkAt0iDw14QiiEm2bE30c5XX5q0FtAA3CK5f9/BUg== + +depd@2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/depd/-/depd-2.0.0.tgz#b696163cc757560d09cf22cc8fad1571b79e76df" + integrity sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw== + +depd@~1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/depd/-/depd-1.1.2.tgz#9bcd52e14c097763e749b274c4346ed2e560b5a9" + integrity sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ== + +destroy@1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/destroy/-/destroy-1.2.0.tgz#4803735509ad8be552934c67df614f94e66fa015" + integrity sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg== + +detect-node@^2.0.4: + version "2.1.0" + resolved "https://registry.yarnpkg.com/detect-node/-/detect-node-2.1.0.tgz#c9c70775a49c3d03bc2c06d9a73be550f978f8b1" + integrity sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g== + +di@^0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/di/-/di-0.0.1.tgz#806649326ceaa7caa3306d75d985ea2748ba913c" + integrity sha512-uJaamHkagcZtHPqCIHZxnFrXlunQXgBOsZSUOWwFw31QJCAbyTBoHMW75YOTur5ZNx8pIeAKgf6GWIgaqqiLhA== + +diff@5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/diff/-/diff-5.0.0.tgz#7ed6ad76d859d030787ec35855f5b1daf31d852b" + integrity sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w== + +dns-packet@^5.2.2: + version "5.6.1" + resolved "https://registry.yarnpkg.com/dns-packet/-/dns-packet-5.6.1.tgz#ae888ad425a9d1478a0674256ab866de1012cf2f" + integrity sha512-l4gcSouhcgIKRvyy99RNVOgxXiicE+2jZoNmaNmZ6JXiGajBOJAesk1OBlJuM5k2c+eudGdLxDqXuPCKIj6kpw== + dependencies: + "@leichtgewicht/ip-codec" "^2.0.1" + +dom-serialize@^2.2.1: + version "2.2.1" + resolved "https://registry.yarnpkg.com/dom-serialize/-/dom-serialize-2.2.1.tgz#562ae8999f44be5ea3076f5419dcd59eb43ac95b" + integrity sha512-Yra4DbvoW7/Z6LBN560ZwXMjoNOSAN2wRsKFGc4iBeso+mpIA6qj1vfdf9HpMaKAqG6wXTy+1SYEzmNpKXOSsQ== + dependencies: + custom-event "~1.0.0" + ent "~2.2.0" + extend "^3.0.0" + void-elements "^2.0.0" + +eastasianwidth@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/eastasianwidth/-/eastasianwidth-0.2.0.tgz#696ce2ec0aa0e6ea93a397ffcf24aa7840c827cb" + integrity sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA== + +ee-first@1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d" + integrity sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow== + +electron-to-chromium@^1.4.796: + version "1.4.814" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.814.tgz#176535a0b899c9c473464502ab77576aa8bb1cbe" + integrity sha512-GVulpHjFu1Y9ZvikvbArHmAhZXtm3wHlpjTMcXNGKl4IQ4jMQjlnz8yMQYYqdLHKi/jEL2+CBC2akWVCoIGUdw== + +emoji-regex@^8.0.0: + version "8.0.0" + resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" + integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A== + +emoji-regex@^9.2.2: + version "9.2.2" + resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-9.2.2.tgz#840c8803b0d8047f4ff0cf963176b32d4ef3ed72" + integrity sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg== + +encodeurl@~1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59" + integrity sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w== + +engine.io-parser@~5.2.1: + version "5.2.2" + resolved "https://registry.yarnpkg.com/engine.io-parser/-/engine.io-parser-5.2.2.tgz#37b48e2d23116919a3453738c5720455e64e1c49" + integrity sha512-RcyUFKA93/CXH20l4SoVvzZfrSDMOTUS3bWVpTt2FuFP+XYrL8i8oonHP7WInRyVHXh0n/ORtoeiE1os+8qkSw== + +engine.io@~6.5.2: + version "6.5.5" + resolved "https://registry.yarnpkg.com/engine.io/-/engine.io-6.5.5.tgz#430b80d8840caab91a50e9e23cb551455195fc93" + integrity sha512-C5Pn8Wk+1vKBoHghJODM63yk8MvrO9EWZUfkAt5HAqIgPE4/8FF0PEGHXtEd40l223+cE5ABWuPzm38PHFXfMA== + dependencies: + "@types/cookie" "^0.4.1" + "@types/cors" "^2.8.12" + "@types/node" ">=10.0.0" + accepts "~1.3.4" + base64id "2.0.0" + cookie "~0.4.1" + cors "~2.8.5" + debug "~4.3.1" + engine.io-parser "~5.2.1" + ws "~8.17.1" + +enhanced-resolve@^5.16.0: + version "5.17.0" + resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-5.17.0.tgz#d037603789dd9555b89aaec7eb78845c49089bc5" + integrity sha512-dwDPwZL0dmye8Txp2gzFmA6sxALaSvdRDjPH0viLcKrtlOL3tw62nWWweVD1SdILDTJrbrL6tdWVN58Wo6U3eA== + dependencies: + graceful-fs "^4.2.4" + tapable "^2.2.0" + +ent@~2.2.0: + version "2.2.1" + resolved "https://registry.yarnpkg.com/ent/-/ent-2.2.1.tgz#68dc99a002f115792c26239baedaaea9e70c0ca2" + integrity sha512-QHuXVeZx9d+tIQAz/XztU0ZwZf2Agg9CcXcgE1rurqvdBeDBrpSwjl8/6XUqMg7tw2Y7uAdKb2sRv+bSEFqQ5A== + dependencies: + punycode "^1.4.1" + +envinfo@^7.7.3: + version "7.13.0" + resolved "https://registry.yarnpkg.com/envinfo/-/envinfo-7.13.0.tgz#81fbb81e5da35d74e814941aeab7c325a606fb31" + integrity sha512-cvcaMr7KqXVh4nyzGTVqTum+gAiL265x5jUWQIDLq//zOGbW+gSW/C+OWLleY/rs9Qole6AZLMXPbtIFQbqu+Q== + +es-define-property@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/es-define-property/-/es-define-property-1.0.0.tgz#c7faefbdff8b2696cf5f46921edfb77cc4ba3845" + integrity sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ== + dependencies: + get-intrinsic "^1.2.4" + +es-errors@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/es-errors/-/es-errors-1.3.0.tgz#05f75a25dab98e4fb1dcd5e1472c0546d5057c8f" + integrity sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw== + +es-module-lexer@^1.2.1: + version "1.5.4" + resolved "https://registry.yarnpkg.com/es-module-lexer/-/es-module-lexer-1.5.4.tgz#a8efec3a3da991e60efa6b633a7cad6ab8d26b78" + integrity sha512-MVNK56NiMrOwitFB7cqDwq0CQutbw+0BvLshJSse0MUNU+y1FC3bUS/AQg7oUng+/wKrrki7JfmwtVHkVfPLlw== + +escalade@^3.1.1, escalade@^3.1.2: + version "3.1.2" + resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.2.tgz#54076e9ab29ea5bf3d8f1ed62acffbb88272df27" + integrity sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA== + +escape-html@~1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988" + integrity sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow== + +escape-string-regexp@4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz#14ba83a5d373e3d311e5afca29cf5bfad965bf34" + integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA== + +eslint-scope@5.1.1: + version "5.1.1" + resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-5.1.1.tgz#e786e59a66cb92b3f6c1fb0d508aab174848f48c" + integrity sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw== + dependencies: + esrecurse "^4.3.0" + estraverse "^4.1.1" + +esrecurse@^4.3.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/esrecurse/-/esrecurse-4.3.0.tgz#7ad7964d679abb28bee72cec63758b1c5d2c9921" + integrity sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag== + dependencies: + estraverse "^5.2.0" + +estraverse@^4.1.1: + version "4.3.0" + resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-4.3.0.tgz#398ad3f3c5a24948be7725e83d11a7de28cdbd1d" + integrity sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw== + +estraverse@^5.2.0: + version "5.3.0" + resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-5.3.0.tgz#2eea5290702f26ab8fe5370370ff86c965d21123" + integrity sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA== + +etag@~1.8.1: + version "1.8.1" + resolved "https://registry.yarnpkg.com/etag/-/etag-1.8.1.tgz#41ae2eeb65efa62268aebfea83ac7d79299b0887" + integrity sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg== + +event-target-shim@^5.0.0: + version "5.0.1" + resolved "https://registry.yarnpkg.com/event-target-shim/-/event-target-shim-5.0.1.tgz#5d4d3ebdf9583d63a5333ce2deb7480ab2b05789" + integrity sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ== + +eventemitter3@^4.0.0: + version "4.0.7" + resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-4.0.7.tgz#2de9b68f6528d5644ef5c59526a1b4a07306169f" + integrity sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw== + +events@^3.2.0: + version "3.3.0" + resolved "https://registry.yarnpkg.com/events/-/events-3.3.0.tgz#31a95ad0a924e2d2c419a813aeb2c4e878ea7400" + integrity sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q== + +execa@^5.0.0: + version "5.1.1" + resolved "https://registry.yarnpkg.com/execa/-/execa-5.1.1.tgz#f80ad9cbf4298f7bd1d4c9555c21e93741c411dd" + integrity sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg== + dependencies: + cross-spawn "^7.0.3" + get-stream "^6.0.0" + human-signals "^2.1.0" + is-stream "^2.0.0" + merge-stream "^2.0.0" + npm-run-path "^4.0.1" + onetime "^5.1.2" + signal-exit "^3.0.3" + strip-final-newline "^2.0.0" + +express@^4.17.3: + version "4.19.2" + resolved "https://registry.yarnpkg.com/express/-/express-4.19.2.tgz#e25437827a3aa7f2a827bc8171bbbb664a356465" + integrity sha512-5T6nhjsT+EOMzuck8JjBHARTHfMht0POzlA60WV2pMD3gyXw2LZnZ+ueGdNxG+0calOJcWKbpFcuzLZ91YWq9Q== + dependencies: + accepts "~1.3.8" + array-flatten "1.1.1" + body-parser "1.20.2" + content-disposition "0.5.4" + content-type "~1.0.4" + cookie "0.6.0" + cookie-signature "1.0.6" + debug "2.6.9" + depd "2.0.0" + encodeurl "~1.0.2" + escape-html "~1.0.3" + etag "~1.8.1" + finalhandler "1.2.0" + fresh "0.5.2" + http-errors "2.0.0" + merge-descriptors "1.0.1" + methods "~1.1.2" + on-finished "2.4.1" + parseurl "~1.3.3" + path-to-regexp "0.1.7" + proxy-addr "~2.0.7" + qs "6.11.0" + range-parser "~1.2.1" + safe-buffer "5.2.1" + send "0.18.0" + serve-static "1.15.0" + setprototypeof "1.2.0" + statuses "2.0.1" + type-is "~1.6.18" + utils-merge "1.0.1" + vary "~1.1.2" + +extend@^3.0.0: + version "3.0.2" + resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.2.tgz#f8b1136b4071fbd8eb140aff858b1019ec2915fa" + integrity sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g== + +fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3: + version "3.1.3" + resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" + integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q== + +fast-json-stable-stringify@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633" + integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw== + +fastest-levenshtein@^1.0.12: + version "1.0.16" + resolved "https://registry.yarnpkg.com/fastest-levenshtein/-/fastest-levenshtein-1.0.16.tgz#210e61b6ff181de91ea9b3d1b84fdedd47e034e5" + integrity sha512-eRnCtTTtGZFpQCwhJiUOuxPQWRXVKYDn0b2PeHfXL6/Zi53SLAzAHfVhVWK2AryC/WH05kGfxhFIPvTF0SXQzg== + +faye-websocket@^0.11.3: + version "0.11.4" + resolved "https://registry.yarnpkg.com/faye-websocket/-/faye-websocket-0.11.4.tgz#7f0d9275cfdd86a1c963dc8b65fcc451edcbb1da" + integrity sha512-CzbClwlXAuiRQAlUyfqPgvPoNKTckTPGfwZV4ZdAhVcP2lh9KUxJg2b5GkE7XbjKQ3YJnQ9z6D9ntLAlB+tP8g== + dependencies: + websocket-driver ">=0.5.1" + +fill-range@^7.1.1: + version "7.1.1" + resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.1.1.tgz#44265d3cac07e3ea7dc247516380643754a05292" + integrity sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg== + dependencies: + to-regex-range "^5.0.1" + +finalhandler@1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-1.1.2.tgz#b7e7d000ffd11938d0fdb053506f6ebabe9f587d" + integrity sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA== + dependencies: + debug "2.6.9" + encodeurl "~1.0.2" + escape-html "~1.0.3" + on-finished "~2.3.0" + parseurl "~1.3.3" + statuses "~1.5.0" + unpipe "~1.0.0" + +finalhandler@1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-1.2.0.tgz#7d23fe5731b207b4640e4fcd00aec1f9207a7b32" + integrity sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg== + dependencies: + debug "2.6.9" + encodeurl "~1.0.2" + escape-html "~1.0.3" + on-finished "2.4.1" + parseurl "~1.3.3" + statuses "2.0.1" + unpipe "~1.0.0" + +find-up@5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/find-up/-/find-up-5.0.0.tgz#4c92819ecb7083561e4f4a240a86be5198f536fc" + integrity sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng== + dependencies: + locate-path "^6.0.0" + path-exists "^4.0.0" + +find-up@^4.0.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/find-up/-/find-up-4.1.0.tgz#97afe7d6cdc0bc5928584b7c8d7b16e8a9aa5d19" + integrity sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw== + dependencies: + locate-path "^5.0.0" + path-exists "^4.0.0" + +flat@^5.0.2: + version "5.0.2" + resolved "https://registry.yarnpkg.com/flat/-/flat-5.0.2.tgz#8ca6fe332069ffa9d324c327198c598259ceb241" + integrity sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ== + +flatted@^3.2.7: + version "3.3.1" + resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.3.1.tgz#21db470729a6734d4997002f439cb308987f567a" + integrity sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw== + +follow-redirects@^1.0.0: + version "1.15.6" + resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.6.tgz#7f815c0cda4249c74ff09e95ef97c23b5fd0399b" + integrity sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA== + +foreground-child@^3.1.0: + version "3.2.1" + resolved "https://registry.yarnpkg.com/foreground-child/-/foreground-child-3.2.1.tgz#767004ccf3a5b30df39bed90718bab43fe0a59f7" + integrity sha512-PXUUyLqrR2XCWICfv6ukppP96sdFwWbNEnfEMt7jNsISjMsvaLNinAHNDYyvkyU+SZG2BTSbT5NjG+vZslfGTA== + dependencies: + cross-spawn "^7.0.0" + signal-exit "^4.0.1" + +format-util@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/format-util/-/format-util-1.0.5.tgz#1ffb450c8a03e7bccffe40643180918cc297d271" + integrity sha512-varLbTj0e0yVyRpqQhuWV+8hlePAgaoFRhNFj50BNjEIrw1/DphHSObtqwskVCPWNgzwPoQrZAbfa/SBiicNeg== + +forwarded@0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/forwarded/-/forwarded-0.2.0.tgz#2269936428aad4c15c7ebe9779a84bf0b2a81811" + integrity sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow== + +fresh@0.5.2: + version "0.5.2" + resolved "https://registry.yarnpkg.com/fresh/-/fresh-0.5.2.tgz#3d8cadd90d976569fa835ab1f8e4b23a105605a7" + integrity sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q== + +fs-extra@^8.1.0: + version "8.1.0" + resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-8.1.0.tgz#49d43c45a88cd9677668cb7be1b46efdb8d2e1c0" + integrity sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g== + dependencies: + graceful-fs "^4.2.0" + jsonfile "^4.0.0" + universalify "^0.1.0" + +fs.realpath@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" + integrity sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw== + +fsevents@~2.3.2: + version "2.3.3" + resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.3.tgz#cac6407785d03675a2a5e1a5305c697b347d90d6" + integrity sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw== + +function-bind@^1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.2.tgz#2c02d864d97f3ea6c8830c464cbd11ab6eab7a1c" + integrity sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA== + +get-caller-file@^2.0.5: + version "2.0.5" + resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" + integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg== + +get-intrinsic@^1.1.3, get-intrinsic@^1.2.4: + version "1.2.4" + resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.2.4.tgz#e385f5a4b5227d449c3eabbad05494ef0abbeadd" + integrity sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ== + dependencies: + es-errors "^1.3.0" + function-bind "^1.1.2" + has-proto "^1.0.1" + has-symbols "^1.0.3" + hasown "^2.0.0" + +get-stream@^6.0.0: + version "6.0.1" + resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-6.0.1.tgz#a262d8eef67aced57c2852ad6167526a43cbf7b7" + integrity sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg== + +glob-parent@~5.1.2: + version "5.1.2" + resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4" + integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow== + dependencies: + is-glob "^4.0.1" + +glob-to-regexp@^0.4.1: + version "0.4.1" + resolved "https://registry.yarnpkg.com/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz#c75297087c851b9a578bd217dd59a92f59fe546e" + integrity sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw== + +glob@8.1.0: + version "8.1.0" + resolved "https://registry.yarnpkg.com/glob/-/glob-8.1.0.tgz#d388f656593ef708ee3e34640fdfb99a9fd1c33e" + integrity sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ== + dependencies: + fs.realpath "^1.0.0" + inflight "^1.0.4" + inherits "2" + minimatch "^5.0.1" + once "^1.3.0" + +glob@^10.3.7: + version "10.4.2" + resolved "https://registry.yarnpkg.com/glob/-/glob-10.4.2.tgz#bed6b95dade5c1f80b4434daced233aee76160e5" + integrity sha512-GwMlUF6PkPo3Gk21UxkCohOv0PLcIXVtKyLlpEI28R/cO/4eNOdmLk3CMW1wROV/WR/EsZOWAfBbBOqYvs88/w== + dependencies: + foreground-child "^3.1.0" + jackspeak "^3.1.2" + minimatch "^9.0.4" + minipass "^7.1.2" + package-json-from-dist "^1.0.0" + path-scurry "^1.11.1" + +glob@^7.1.3, glob@^7.1.7: + version "7.2.3" + resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.3.tgz#b8df0fb802bbfa8e89bd1d938b4e16578ed44f2b" + integrity sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q== + dependencies: + fs.realpath "^1.0.0" + inflight "^1.0.4" + inherits "2" + minimatch "^3.1.1" + once "^1.3.0" + path-is-absolute "^1.0.0" + +gopd@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/gopd/-/gopd-1.0.1.tgz#29ff76de69dac7489b7c0918a5788e56477c332c" + integrity sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA== + dependencies: + get-intrinsic "^1.1.3" + +graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.2.0, graceful-fs@^4.2.10, graceful-fs@^4.2.11, graceful-fs@^4.2.4, graceful-fs@^4.2.6: + version "4.2.11" + resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.11.tgz#4183e4e8bf08bb6e05bbb2f7d2e0c8f712ca40e3" + integrity sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ== + +handle-thing@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/handle-thing/-/handle-thing-2.0.1.tgz#857f79ce359580c340d43081cc648970d0bb234e" + integrity sha512-9Qn4yBxelxoh2Ow62nP+Ka/kMnOXRi8BXnRaUwezLNhqelnN49xKz4F/dPP8OYLxLxq6JDtZb2i9XznUQbNPTg== + +has-flag@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b" + integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== + +has-property-descriptors@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz#963ed7d071dc7bf5f084c5bfbe0d1b6222586854" + integrity sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg== + dependencies: + es-define-property "^1.0.0" + +has-proto@^1.0.1: + version "1.0.3" + resolved "https://registry.yarnpkg.com/has-proto/-/has-proto-1.0.3.tgz#b31ddfe9b0e6e9914536a6ab286426d0214f77fd" + integrity sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q== + +has-symbols@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.3.tgz#bb7b2c4349251dce87b125f7bdf874aa7c8b39f8" + integrity sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A== + +hasown@^2.0.0, hasown@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/hasown/-/hasown-2.0.2.tgz#003eaf91be7adc372e84ec59dc37252cedb80003" + integrity sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ== + dependencies: + function-bind "^1.1.2" + +he@1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/he/-/he-1.2.0.tgz#84ae65fa7eafb165fddb61566ae14baf05664f0f" + integrity sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw== + +hpack.js@^2.1.6: + version "2.1.6" + resolved "https://registry.yarnpkg.com/hpack.js/-/hpack.js-2.1.6.tgz#87774c0949e513f42e84575b3c45681fade2a0b2" + integrity sha512-zJxVehUdMGIKsRaNt7apO2Gqp0BdqW5yaiGHXXmbpvxgBYVZnAql+BJb4RO5ad2MgpbZKn5G6nMnegrH1FcNYQ== + dependencies: + inherits "^2.0.1" + obuf "^1.0.0" + readable-stream "^2.0.1" + wbuf "^1.1.0" + +html-entities@^2.4.0: + version "2.5.2" + resolved "https://registry.yarnpkg.com/html-entities/-/html-entities-2.5.2.tgz#201a3cf95d3a15be7099521620d19dfb4f65359f" + integrity sha512-K//PSRMQk4FZ78Kyau+mZurHn3FH0Vwr+H36eE0rPbeYkRRi9YxceYPhuN60UwWorxyKHhqoAJl2OFKa4BVtaA== + +http-deceiver@^1.2.7: + version "1.2.7" + resolved "https://registry.yarnpkg.com/http-deceiver/-/http-deceiver-1.2.7.tgz#fa7168944ab9a519d337cb0bec7284dc3e723d87" + integrity sha512-LmpOGxTfbpgtGVxJrj5k7asXHCgNZp5nLfp+hWc8QQRqtb7fUy6kRY3BO1h9ddF6yIPYUARgxGOwB42DnxIaNw== + +http-errors@2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-2.0.0.tgz#b7774a1486ef73cf7667ac9ae0858c012c57b9d3" + integrity sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ== + dependencies: + depd "2.0.0" + inherits "2.0.4" + setprototypeof "1.2.0" + statuses "2.0.1" + toidentifier "1.0.1" + +http-errors@~1.6.2: + version "1.6.3" + resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.6.3.tgz#8b55680bb4be283a0b5bf4ea2e38580be1d9320d" + integrity sha512-lks+lVC8dgGyh97jxvxeYTWQFvh4uw4yC12gVl63Cg30sjPX4wuGcdkICVXDAESr6OJGjqGA8Iz5mkeN6zlD7A== + dependencies: + depd "~1.1.2" + inherits "2.0.3" + setprototypeof "1.1.0" + statuses ">= 1.4.0 < 2" + +http-parser-js@>=0.5.1: + version "0.5.8" + resolved "https://registry.yarnpkg.com/http-parser-js/-/http-parser-js-0.5.8.tgz#af23090d9ac4e24573de6f6aecc9d84a48bf20e3" + integrity sha512-SGeBX54F94Wgu5RH3X5jsDtf4eHyRogWX1XGT3b4HuW3tQPM4AaBzoUji/4AAJNXCEOWZ5O0DgZmJw1947gD5Q== + +http-proxy-middleware@^2.0.3: + version "2.0.6" + resolved "https://registry.yarnpkg.com/http-proxy-middleware/-/http-proxy-middleware-2.0.6.tgz#e1a4dd6979572c7ab5a4e4b55095d1f32a74963f" + integrity sha512-ya/UeJ6HVBYxrgYotAZo1KvPWlgB48kUJLDePFeneHsVujFaW5WNj2NgWCAE//B1Dl02BIfYlpNgBy8Kf8Rjmw== + dependencies: + "@types/http-proxy" "^1.17.8" + http-proxy "^1.18.1" + is-glob "^4.0.1" + is-plain-obj "^3.0.0" + micromatch "^4.0.2" + +http-proxy@^1.18.1: + version "1.18.1" + resolved "https://registry.yarnpkg.com/http-proxy/-/http-proxy-1.18.1.tgz#401541f0534884bbf95260334e72f88ee3976549" + integrity sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ== + dependencies: + eventemitter3 "^4.0.0" + follow-redirects "^1.0.0" + requires-port "^1.0.0" + +human-signals@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-2.1.0.tgz#dc91fcba42e4d06e4abaed33b3e7a3c02f514ea0" + integrity sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw== + +hyperdyperid@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/hyperdyperid/-/hyperdyperid-1.2.0.tgz#59668d323ada92228d2a869d3e474d5a33b69e6b" + integrity sha512-Y93lCzHYgGWdrJ66yIktxiaGULYc6oGiABxhcO5AufBeOyoIdZF7bIfLaOrbM0iGIOXQQgxxRrFEnb+Y6w1n4A== + +iconv-lite@0.4.24: + version "0.4.24" + resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b" + integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA== + dependencies: + safer-buffer ">= 2.1.2 < 3" + +iconv-lite@^0.6.3: + version "0.6.3" + resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.6.3.tgz#a52f80bf38da1952eb5c681790719871a1a72501" + integrity sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw== + dependencies: + safer-buffer ">= 2.1.2 < 3.0.0" + +import-local@^3.0.2: + version "3.1.0" + resolved "https://registry.yarnpkg.com/import-local/-/import-local-3.1.0.tgz#b4479df8a5fd44f6cdce24070675676063c95cb4" + integrity sha512-ASB07uLtnDs1o6EHjKpX34BKYDSqnFerfTOJL2HvMqF70LnxpjkzDB8J44oT9pu4AMPkQwf8jl6szgvNd2tRIg== + dependencies: + pkg-dir "^4.2.0" + resolve-cwd "^3.0.0" + +inflight@^1.0.4: + version "1.0.6" + resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" + integrity sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA== + dependencies: + once "^1.3.0" + wrappy "1" + +inherits@2, inherits@2.0.4, inherits@^2.0.1, inherits@^2.0.3, inherits@~2.0.3: + version "2.0.4" + resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" + integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== + +inherits@2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de" + integrity sha512-x00IRNXNy63jwGkJmzPigoySHbaqpNuzKbBOmzK+g2OdZpQ9w+sxCN+VSB3ja7IAge2OP2qpfxTjeNcyjmW1uw== + +interpret@^3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/interpret/-/interpret-3.1.1.tgz#5be0ceed67ca79c6c4bc5cf0d7ee843dcea110c4" + integrity sha512-6xwYfHbajpoF0xLW+iwLkhwgvLoZDfjYfoFNu8ftMoXINzwuymNLd9u/KmwtdT2GbR+/Cz66otEGEVVUHX9QLQ== + +ipaddr.js@1.9.1: + version "1.9.1" + resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-1.9.1.tgz#bff38543eeb8984825079ff3a2a8e6cbd46781b3" + integrity sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g== + +ipaddr.js@^2.1.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-2.2.0.tgz#d33fa7bac284f4de7af949638c9d68157c6b92e8" + integrity sha512-Ag3wB2o37wslZS19hZqorUnrnzSkpOVy+IiiDEiTqNubEYpYuHWIf6K4psgN2ZWKExS4xhVCrRVfb/wfW8fWJA== + +is-binary-path@~2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-2.1.0.tgz#ea1f7f3b80f064236e83470f86c09c254fb45b09" + integrity sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw== + dependencies: + binary-extensions "^2.0.0" + +is-core-module@^2.13.0: + version "2.14.0" + resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.14.0.tgz#43b8ef9f46a6a08888db67b1ffd4ec9e3dfd59d1" + integrity sha512-a5dFJih5ZLYlRtDc0dZWP7RiKr6xIKzmn/oAYCDvdLThadVgyJwlaoQPmRtMSpz+rk0OGAgIu+TcM9HUF0fk1A== + dependencies: + hasown "^2.0.2" + +is-docker@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/is-docker/-/is-docker-3.0.0.tgz#90093aa3106277d8a77a5910dbae71747e15a200" + integrity sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ== + +is-extglob@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" + integrity sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ== + +is-fullwidth-code-point@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d" + integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg== + +is-glob@^4.0.1, is-glob@~4.0.1: + version "4.0.3" + resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.3.tgz#64f61e42cbbb2eec2071a9dac0b28ba1e65d5084" + integrity sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg== + dependencies: + is-extglob "^2.1.1" + +is-inside-container@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-inside-container/-/is-inside-container-1.0.0.tgz#e81fba699662eb31dbdaf26766a61d4814717ea4" + integrity sha512-KIYLCCJghfHZxqjYBE7rEy0OBuTd5xCHS7tHVgvCLkx7StIoaxwNW3hCALgEUjFfeRk+MG/Qxmp/vtETEF3tRA== + dependencies: + is-docker "^3.0.0" + +is-network-error@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/is-network-error/-/is-network-error-1.1.0.tgz#d26a760e3770226d11c169052f266a4803d9c997" + integrity sha512-tUdRRAnhT+OtCZR/LxZelH/C7QtjtFrTu5tXCA8pl55eTUElUHT+GPYV8MBMBvea/j+NxQqVt3LbWMRir7Gx9g== + +is-number@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b" + integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng== + +is-plain-obj@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-2.1.0.tgz#45e42e37fccf1f40da8e5f76ee21515840c09287" + integrity sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA== + +is-plain-obj@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-3.0.0.tgz#af6f2ea14ac5a646183a5bbdb5baabbc156ad9d7" + integrity sha512-gwsOE28k+23GP1B6vFl1oVh/WOzmawBrKwo5Ev6wMKzPkaXaCDIQKzLnvsA42DRlbVTWorkgTKIviAKCWkfUwA== + +is-plain-object@^2.0.4: + version "2.0.4" + resolved "https://registry.yarnpkg.com/is-plain-object/-/is-plain-object-2.0.4.tgz#2c163b3fafb1b606d9d17928f05c2a1c38e07677" + integrity sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og== + dependencies: + isobject "^3.0.1" + +is-stream@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-2.0.1.tgz#fac1e3d53b97ad5a9d0ae9cef2389f5810a5c077" + integrity sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg== + +is-unicode-supported@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz#3f26c76a809593b52bfa2ecb5710ed2779b522a7" + integrity sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw== + +is-wsl@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/is-wsl/-/is-wsl-3.1.0.tgz#e1c657e39c10090afcbedec61720f6b924c3cbd2" + integrity sha512-UcVfVfaK4Sc4m7X3dUSoHoozQGBEFeDC+zVo06t98xe8CzHSZZBekNXH+tu0NalHolcJ/QAGqS46Hef7QXBIMw== + dependencies: + is-inside-container "^1.0.0" + +isarray@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" + integrity sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ== + +isbinaryfile@^4.0.8: + version "4.0.10" + resolved "https://registry.yarnpkg.com/isbinaryfile/-/isbinaryfile-4.0.10.tgz#0c5b5e30c2557a2f06febd37b7322946aaee42b3" + integrity sha512-iHrqe5shvBUcFbmZq9zOQHBoeOhZJu6RQGrDpBgenUm/Am+F3JM2MgQj+rK3Z601fzrL5gLZWtAPH2OBaSVcyw== + +isexe@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" + integrity sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw== + +isobject@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/isobject/-/isobject-3.0.1.tgz#4e431e92b11a9731636aa1f9c8d1ccbcfdab78df" + integrity sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg== + +jackspeak@^3.1.2: + version "3.4.0" + resolved "https://registry.yarnpkg.com/jackspeak/-/jackspeak-3.4.0.tgz#a75763ff36ad778ede6a156d8ee8b124de445b4a" + integrity sha512-JVYhQnN59LVPFCEcVa2C3CrEKYacvjRfqIQl+h8oi91aLYQVWRYbxjPcv1bUiUy/kLmQaANrYfNMCO3kuEDHfw== + dependencies: + "@isaacs/cliui" "^8.0.2" + optionalDependencies: + "@pkgjs/parseargs" "^0.11.0" + +jest-worker@^27.4.5: + version "27.5.1" + resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-27.5.1.tgz#8d146f0900e8973b106b6f73cc1e9a8cb86f8db0" + integrity sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg== + dependencies: + "@types/node" "*" + merge-stream "^2.0.0" + supports-color "^8.0.0" + +js-yaml@4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-4.1.0.tgz#c1fb65f8f5017901cdd2c951864ba18458a10602" + integrity sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA== + dependencies: + argparse "^2.0.1" + +json-parse-even-better-errors@^2.3.1: + version "2.3.1" + resolved "https://registry.yarnpkg.com/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz#7c47805a94319928e05777405dc12e1f7a4ee02d" + integrity sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w== + +json-schema-traverse@^0.4.1: + version "0.4.1" + resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660" + integrity sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg== + +json-schema-traverse@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz#ae7bcb3656ab77a73ba5c49bf654f38e6b6860e2" + integrity sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug== + +jsonfile@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-4.0.0.tgz#8771aae0799b64076b76640fca058f9c10e33ecb" + integrity sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg== + optionalDependencies: + graceful-fs "^4.1.6" + +karma-chrome-launcher@3.2.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/karma-chrome-launcher/-/karma-chrome-launcher-3.2.0.tgz#eb9c95024f2d6dfbb3748d3415ac9b381906b9a9" + integrity sha512-rE9RkUPI7I9mAxByQWkGJFXfFD6lE4gC5nPuZdobf/QdTEJI6EU4yIay/cfU/xV4ZxlM5JiTv7zWYgA64NpS5Q== + dependencies: + which "^1.2.1" + +karma-mocha@2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/karma-mocha/-/karma-mocha-2.0.1.tgz#4b0254a18dfee71bdbe6188d9a6861bf86b0cd7d" + integrity sha512-Tzd5HBjm8his2OA4bouAsATYEpZrp9vC7z5E5j4C5Of5Rrs1jY67RAwXNcVmd/Bnk1wgvQRou0zGVLey44G4tQ== + dependencies: + minimist "^1.2.3" + +karma-sourcemap-loader@0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/karma-sourcemap-loader/-/karma-sourcemap-loader-0.4.0.tgz#b01d73f8f688f533bcc8f5d273d43458e13b5488" + integrity sha512-xCRL3/pmhAYF3I6qOrcn0uhbQevitc2DERMPH82FMnG+4WReoGcGFZb1pURf2a5apyrOHRdvD+O6K7NljqKHyA== + dependencies: + graceful-fs "^4.2.10" + +karma-webpack@5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/karma-webpack/-/karma-webpack-5.0.1.tgz#4eafd31bbe684a747a6e8f3e4ad373e53979ced4" + integrity sha512-oo38O+P3W2mSPCSUrQdySSPv1LvPpXP+f+bBimNomS5sW+1V4SuhCuW8TfJzV+rDv921w2fDSDw0xJbPe6U+kQ== + dependencies: + glob "^7.1.3" + minimatch "^9.0.3" + webpack-merge "^4.1.5" + +karma@6.4.3: + version "6.4.3" + resolved "https://registry.yarnpkg.com/karma/-/karma-6.4.3.tgz#763e500f99597218bbb536de1a14acc4ceea7ce8" + integrity sha512-LuucC/RE92tJ8mlCwqEoRWXP38UMAqpnq98vktmS9SznSoUPPUJQbc91dHcxcunROvfQjdORVA/YFviH+Xci9Q== + dependencies: + "@colors/colors" "1.5.0" + body-parser "^1.19.0" + braces "^3.0.2" + chokidar "^3.5.1" + connect "^3.7.0" + di "^0.0.1" + dom-serialize "^2.2.1" + glob "^7.1.7" + graceful-fs "^4.2.6" + http-proxy "^1.18.1" + isbinaryfile "^4.0.8" + lodash "^4.17.21" + log4js "^6.4.1" + mime "^2.5.2" + minimatch "^3.0.4" + mkdirp "^0.5.5" + qjobs "^1.2.0" + range-parser "^1.2.1" + rimraf "^3.0.2" + socket.io "^4.7.2" + source-map "^0.6.1" + tmp "^0.2.1" + ua-parser-js "^0.7.30" + yargs "^16.1.1" + +kind-of@^6.0.2: + version "6.0.3" + resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.3.tgz#07c05034a6c349fa06e24fa35aa76db4580ce4dd" + integrity sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw== + +launch-editor@^2.6.1: + version "2.8.0" + resolved "https://registry.yarnpkg.com/launch-editor/-/launch-editor-2.8.0.tgz#7255d90bdba414448e2138faa770a74f28451305" + integrity sha512-vJranOAJrI/llyWGRQqiDM+adrw+k83fvmmx3+nV47g3+36xM15jE+zyZ6Ffel02+xSvuM0b2GDRosXZkbb6wA== + dependencies: + picocolors "^1.0.0" + shell-quote "^1.8.1" + +loader-runner@^4.2.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/loader-runner/-/loader-runner-4.3.0.tgz#c1b4a163b99f614830353b16755e7149ac2314e1" + integrity sha512-3R/1M+yS3j5ou80Me59j7F9IMs4PXs3VqRrm0TU3AbKPxlmpoY1TNscJV/oGJXo8qCatFGTfDbY6W6ipGOYXfg== + +locate-path@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-5.0.0.tgz#1afba396afd676a6d42504d0a67a3a7eb9f62aa0" + integrity sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g== + dependencies: + p-locate "^4.1.0" + +locate-path@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-6.0.0.tgz#55321eb309febbc59c4801d931a72452a681d286" + integrity sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw== + dependencies: + p-locate "^5.0.0" + +lodash@^4.17.15, lodash@^4.17.21: + version "4.17.21" + resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" + integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== + +log-symbols@4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-4.1.0.tgz#3fbdbb95b4683ac9fc785111e792e558d4abd503" + integrity sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg== + dependencies: + chalk "^4.1.0" + is-unicode-supported "^0.1.0" + +log4js@^6.4.1: + version "6.9.1" + resolved "https://registry.yarnpkg.com/log4js/-/log4js-6.9.1.tgz#aba5a3ff4e7872ae34f8b4c533706753709e38b6" + integrity sha512-1somDdy9sChrr9/f4UlzhdaGfDR2c/SaD2a4T7qEkG4jTS57/B3qmnjLYePwQ8cqWnUHZI0iAKxMBpCZICiZ2g== + dependencies: + date-format "^4.0.14" + debug "^4.3.4" + flatted "^3.2.7" + rfdc "^1.3.0" + streamroller "^3.1.5" + +lru-cache@^10.2.0: + version "10.3.0" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-10.3.0.tgz#4a4aaf10c84658ab70f79a85a9a3f1e1fb11196b" + integrity sha512-CQl19J/g+Hbjbv4Y3mFNNXFEL/5t/KCg8POCuUqd4rMKjGG+j1ybER83hxV58zL+dFI1PTkt3GNFSHRt+d8qEQ== + +media-typer@0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748" + integrity sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ== + +memfs@^4.6.0: + version "4.9.3" + resolved "https://registry.yarnpkg.com/memfs/-/memfs-4.9.3.tgz#41a3218065fe3911d9eba836250c8f4e43f816bc" + integrity sha512-bsYSSnirtYTWi1+OPMFb0M048evMKyUYe0EbtuGQgq6BVQM1g1W8/KIUJCCvjgI/El0j6Q4WsmMiBwLUBSw8LA== + dependencies: + "@jsonjoy.com/json-pack" "^1.0.3" + "@jsonjoy.com/util" "^1.1.2" + tree-dump "^1.0.1" + tslib "^2.0.0" + +merge-descriptors@1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/merge-descriptors/-/merge-descriptors-1.0.1.tgz#b00aaa556dd8b44568150ec9d1b953f3f90cbb61" + integrity sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w== + +merge-stream@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/merge-stream/-/merge-stream-2.0.0.tgz#52823629a14dd00c9770fb6ad47dc6310f2c1f60" + integrity sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w== + +methods@~1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/methods/-/methods-1.1.2.tgz#5529a4d67654134edcc5266656835b0f851afcee" + integrity sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w== + +micromatch@^4.0.2: + version "4.0.7" + resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.7.tgz#33e8190d9fe474a9895525f5618eee136d46c2e5" + integrity sha512-LPP/3KorzCwBxfeUuZmaR6bG2kdeHSbe0P2tY3FLRU4vYrjYz5hI4QZwV0njUx3jeuKe67YukQ1LSPZBKDqO/Q== + dependencies: + braces "^3.0.3" + picomatch "^2.3.1" + +mime-db@1.52.0, "mime-db@>= 1.43.0 < 2": + version "1.52.0" + resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.52.0.tgz#bbabcdc02859f4987301c856e3387ce5ec43bf70" + integrity sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg== + +mime-types@^2.1.27, mime-types@^2.1.31, mime-types@~2.1.17, mime-types@~2.1.24, mime-types@~2.1.34: + version "2.1.35" + resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.35.tgz#381a871b62a734450660ae3deee44813f70d959a" + integrity sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw== + dependencies: + mime-db "1.52.0" + +mime@1.6.0: + version "1.6.0" + resolved "https://registry.yarnpkg.com/mime/-/mime-1.6.0.tgz#32cd9e5c64553bd58d19a568af452acff04981b1" + integrity sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg== + +mime@^2.5.2: + version "2.6.0" + resolved "https://registry.yarnpkg.com/mime/-/mime-2.6.0.tgz#a2a682a95cd4d0cb1d6257e28f83da7e35800367" + integrity sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg== + +mimic-fn@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b" + integrity sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg== + +minimalistic-assert@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz#2e194de044626d4a10e7f7fbc00ce73e83e4d5c7" + integrity sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A== + +minimatch@5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-5.0.1.tgz#fb9022f7528125187c92bd9e9b6366be1cf3415b" + integrity sha512-nLDxIFRyhDblz3qMuq+SoRZED4+miJ/G+tdDrjkkkRnjAsBexeGpgjLEQ0blJy7rHhR2b93rhQY4SvyWu9v03g== + dependencies: + brace-expansion "^2.0.1" + +minimatch@^3.0.4, minimatch@^3.1.1: + version "3.1.2" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b" + integrity sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw== + dependencies: + brace-expansion "^1.1.7" + +minimatch@^5.0.1: + version "5.1.6" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-5.1.6.tgz#1cfcb8cf5522ea69952cd2af95ae09477f122a96" + integrity sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g== + dependencies: + brace-expansion "^2.0.1" + +minimatch@^9.0.3, minimatch@^9.0.4: + version "9.0.5" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-9.0.5.tgz#d74f9dd6b57d83d8e98cfb82133b03978bc929e5" + integrity sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow== + dependencies: + brace-expansion "^2.0.1" + +minimist@^1.2.3, minimist@^1.2.6: + version "1.2.8" + resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.8.tgz#c1a464e7693302e082a075cee0c057741ac4772c" + integrity sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA== + +"minipass@^5.0.0 || ^6.0.2 || ^7.0.0", minipass@^7.1.2: + version "7.1.2" + resolved "https://registry.yarnpkg.com/minipass/-/minipass-7.1.2.tgz#93a9626ce5e5e66bd4db86849e7515e92340a707" + integrity sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw== + +mkdirp@^0.5.5: + version "0.5.6" + resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.6.tgz#7def03d2432dcae4ba1d611445c48396062255f6" + integrity sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw== + dependencies: + minimist "^1.2.6" + +mocha@10.3.0: + version "10.3.0" + resolved "https://registry.yarnpkg.com/mocha/-/mocha-10.3.0.tgz#0e185c49e6dccf582035c05fa91084a4ff6e3fe9" + integrity sha512-uF2XJs+7xSLsrmIvn37i/wnc91nw7XjOQB8ccyx5aEgdnohr7n+rEiZP23WkCYHjilR6+EboEnbq/ZQDz4LSbg== + dependencies: + ansi-colors "4.1.1" + browser-stdout "1.3.1" + chokidar "3.5.3" + debug "4.3.4" + diff "5.0.0" + escape-string-regexp "4.0.0" + find-up "5.0.0" + glob "8.1.0" + he "1.2.0" + js-yaml "4.1.0" + log-symbols "4.1.0" + minimatch "5.0.1" + ms "2.1.3" + serialize-javascript "6.0.0" + strip-json-comments "3.1.1" + supports-color "8.1.1" + workerpool "6.2.1" + yargs "16.2.0" + yargs-parser "20.2.4" + yargs-unparser "2.0.0" + +ms@2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" + integrity sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A== + +ms@2.1.2: + version "2.1.2" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" + integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== + +ms@2.1.3: + version "2.1.3" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" + integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== + +multicast-dns@^7.2.5: + version "7.2.5" + resolved "https://registry.yarnpkg.com/multicast-dns/-/multicast-dns-7.2.5.tgz#77eb46057f4d7adbd16d9290fa7299f6fa64cced" + integrity sha512-2eznPJP8z2BFLX50tf0LuODrpINqP1RVIm/CObbTcBRITQgmC/TjcREF1NeTBzIcR5XO/ukWo+YHOjBbFwIupg== + dependencies: + dns-packet "^5.2.2" + thunky "^1.0.2" + +negotiator@0.6.3: + version "0.6.3" + resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.3.tgz#58e323a72fedc0d6f9cd4d31fe49f51479590ccd" + integrity sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg== + +neo-async@^2.6.2: + version "2.6.2" + resolved "https://registry.yarnpkg.com/neo-async/-/neo-async-2.6.2.tgz#b4aafb93e3aeb2d8174ca53cf163ab7d7308305f" + integrity sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw== + +node-fetch@2.6.7: + version "2.6.7" + resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.7.tgz#24de9fba827e3b4ae44dc8b20256a379160052ad" + integrity sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ== + dependencies: + whatwg-url "^5.0.0" + +node-forge@^1: + version "1.3.1" + resolved "https://registry.yarnpkg.com/node-forge/-/node-forge-1.3.1.tgz#be8da2af243b2417d5f646a770663a92b7e9ded3" + integrity sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA== + +node-releases@^2.0.14: + version "2.0.14" + resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.14.tgz#2ffb053bceb8b2be8495ece1ab6ce600c4461b0b" + integrity sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw== + +normalize-path@^3.0.0, normalize-path@~3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65" + integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA== + +npm-run-path@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-4.0.1.tgz#b7ecd1e5ed53da8e37a55e1c2269e0b97ed748ea" + integrity sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw== + dependencies: + path-key "^3.0.0" + +object-assign@^4: + version "4.1.1" + resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" + integrity sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg== + +object-inspect@^1.13.1: + version "1.13.2" + resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.13.2.tgz#dea0088467fb991e67af4058147a24824a3043ff" + integrity sha512-IRZSRuzJiynemAXPYtPe5BoI/RESNYR7TYm50MC5Mqbd3Jmw5y790sErYw3V6SryFJD64b74qQQs9wn5Bg/k3g== + +obuf@^1.0.0, obuf@^1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/obuf/-/obuf-1.1.2.tgz#09bea3343d41859ebd446292d11c9d4db619084e" + integrity sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg== + +on-finished@2.4.1, on-finished@^2.4.1: + version "2.4.1" + resolved "https://registry.yarnpkg.com/on-finished/-/on-finished-2.4.1.tgz#58c8c44116e54845ad57f14ab10b03533184ac3f" + integrity sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg== + dependencies: + ee-first "1.1.1" + +on-finished@~2.3.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/on-finished/-/on-finished-2.3.0.tgz#20f1336481b083cd75337992a16971aa2d906947" + integrity sha512-ikqdkGAAyf/X/gPhXGvfgAytDZtDbr+bkNUJ0N9h5MI/dmdgCs3l6hoHrcUv41sRKew3jIwrp4qQDXiK99Utww== + dependencies: + ee-first "1.1.1" + +on-headers@~1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/on-headers/-/on-headers-1.0.2.tgz#772b0ae6aaa525c399e489adfad90c403eb3c28f" + integrity sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA== + +once@^1.3.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" + integrity sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w== + dependencies: + wrappy "1" + +onetime@^5.1.2: + version "5.1.2" + resolved "https://registry.yarnpkg.com/onetime/-/onetime-5.1.2.tgz#d0e96ebb56b07476df1dd9c4806e5237985ca45e" + integrity sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg== + dependencies: + mimic-fn "^2.1.0" + +open@^10.0.3: + version "10.1.0" + resolved "https://registry.yarnpkg.com/open/-/open-10.1.0.tgz#a7795e6e5d519abe4286d9937bb24b51122598e1" + integrity sha512-mnkeQ1qP5Ue2wd+aivTD3NHd/lZ96Lu0jgf0pwktLPtx6cTZiH7tyeGRRHs0zX0rbrahXPnXlUnbeXyaBBuIaw== + dependencies: + default-browser "^5.2.1" + define-lazy-prop "^3.0.0" + is-inside-container "^1.0.0" + is-wsl "^3.1.0" + +p-limit@^2.2.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.3.0.tgz#3dd33c647a214fdfffd835933eb086da0dc21db1" + integrity sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w== + dependencies: + p-try "^2.0.0" + +p-limit@^3.0.2: + version "3.1.0" + resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-3.1.0.tgz#e1daccbe78d0d1388ca18c64fea38e3e57e3706b" + integrity sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ== + dependencies: + yocto-queue "^0.1.0" + +p-locate@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-4.1.0.tgz#a3428bb7088b3a60292f66919278b7c297ad4f07" + integrity sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A== + dependencies: + p-limit "^2.2.0" + +p-locate@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-5.0.0.tgz#83c8315c6785005e3bd021839411c9e110e6d834" + integrity sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw== + dependencies: + p-limit "^3.0.2" + +p-retry@^6.2.0: + version "6.2.0" + resolved "https://registry.yarnpkg.com/p-retry/-/p-retry-6.2.0.tgz#8d6df01af298750009691ce2f9b3ad2d5968f3bd" + integrity sha512-JA6nkq6hKyWLLasXQXUrO4z8BUZGUt/LjlJxx8Gb2+2ntodU/SS63YZ8b0LUTbQ8ZB9iwOfhEPhg4ykKnn2KsA== + dependencies: + "@types/retry" "0.12.2" + is-network-error "^1.0.0" + retry "^0.13.1" + +p-try@^2.0.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.2.0.tgz#cb2868540e313d61de58fafbe35ce9004d5540e6" + integrity sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ== + +package-json-from-dist@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/package-json-from-dist/-/package-json-from-dist-1.0.0.tgz#e501cd3094b278495eb4258d4c9f6d5ac3019f00" + integrity sha512-dATvCeZN/8wQsGywez1mzHtTlP22H8OEfPrVMLNr4/eGa+ijtLn/6M5f0dY8UKNrC2O9UCU6SSoG3qRKnt7STw== + +parseurl@~1.3.2, parseurl@~1.3.3: + version "1.3.3" + resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.3.tgz#9da19e7bee8d12dff0513ed5b76957793bc2e8d4" + integrity sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ== + +path-exists@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-4.0.0.tgz#513bdbe2d3b95d7762e8c1137efa195c6c61b5b3" + integrity sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w== + +path-is-absolute@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" + integrity sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg== + +path-key@^3.0.0, path-key@^3.1.0: + version "3.1.1" + resolved "https://registry.yarnpkg.com/path-key/-/path-key-3.1.1.tgz#581f6ade658cbba65a0d3380de7753295054f375" + integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q== + +path-parse@^1.0.7: + version "1.0.7" + resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735" + integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw== + +path-scurry@^1.11.1: + version "1.11.1" + resolved "https://registry.yarnpkg.com/path-scurry/-/path-scurry-1.11.1.tgz#7960a668888594a0720b12a911d1a742ab9f11d2" + integrity sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA== + dependencies: + lru-cache "^10.2.0" + minipass "^5.0.0 || ^6.0.2 || ^7.0.0" + +path-to-regexp@0.1.7: + version "0.1.7" + resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-0.1.7.tgz#df604178005f522f15eb4490e7247a1bfaa67f8c" + integrity sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ== + +picocolors@^1.0.0, picocolors@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.0.1.tgz#a8ad579b571952f0e5d25892de5445bcfe25aaa1" + integrity sha512-anP1Z8qwhkbmu7MFP5iTt+wQKXgwzf7zTyGlcdzabySa9vd0Xt392U0rVmz9poOaBj0uHJKyyo9/upk0HrEQew== + +picomatch@^2.0.4, picomatch@^2.2.1, picomatch@^2.3.1: + version "2.3.1" + resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42" + integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== + +pkg-dir@^4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-4.2.0.tgz#f099133df7ede422e81d1d8448270eeb3e4261f3" + integrity sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ== + dependencies: + find-up "^4.0.0" + +process-nextick-args@~2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2" + integrity sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag== + +proxy-addr@~2.0.7: + version "2.0.7" + resolved "https://registry.yarnpkg.com/proxy-addr/-/proxy-addr-2.0.7.tgz#f19fe69ceab311eeb94b42e70e8c2070f9ba1025" + integrity sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg== + dependencies: + forwarded "0.2.0" + ipaddr.js "1.9.1" + +punycode@^1.4.1: + version "1.4.1" + resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.4.1.tgz#c0d5a63b2718800ad8e1eb0fa5269c84dd41845e" + integrity sha512-jmYNElW7yvO7TV33CjSmvSiE2yco3bV2czu/OzDKdMNVZQWfxCblURLhf+47syQRBntjfLdd/H0egrzIG+oaFQ== + +punycode@^2.1.0: + version "2.3.1" + resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.3.1.tgz#027422e2faec0b25e1549c3e1bd8309b9133b6e5" + integrity sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg== + +qjobs@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/qjobs/-/qjobs-1.2.0.tgz#c45e9c61800bd087ef88d7e256423bdd49e5d071" + integrity sha512-8YOJEHtxpySA3fFDyCRxA+UUV+fA+rTWnuWvylOK/NCjhY+b4ocCtmu8TtsWb+mYeU+GCHf/S66KZF/AsteKHg== + +qs@6.11.0: + version "6.11.0" + resolved "https://registry.yarnpkg.com/qs/-/qs-6.11.0.tgz#fd0d963446f7a65e1367e01abd85429453f0c37a" + integrity sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q== + dependencies: + side-channel "^1.0.4" + +randombytes@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/randombytes/-/randombytes-2.1.0.tgz#df6f84372f0270dc65cdf6291349ab7a473d4f2a" + integrity sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ== + dependencies: + safe-buffer "^5.1.0" + +range-parser@^1.2.1, range-parser@~1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.1.tgz#3cf37023d199e1c24d1a55b84800c2f3e6468031" + integrity sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg== + +raw-body@2.5.2: + version "2.5.2" + resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.5.2.tgz#99febd83b90e08975087e8f1f9419a149366b68a" + integrity sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA== + dependencies: + bytes "3.1.2" + http-errors "2.0.0" + iconv-lite "0.4.24" + unpipe "1.0.0" + +readable-stream@^2.0.1: + version "2.3.8" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.8.tgz#91125e8042bba1b9887f49345f6277027ce8be9b" + integrity sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA== + dependencies: + core-util-is "~1.0.0" + inherits "~2.0.3" + isarray "~1.0.0" + process-nextick-args "~2.0.0" + safe-buffer "~5.1.1" + string_decoder "~1.1.1" + util-deprecate "~1.0.1" + +readable-stream@^3.0.6: + version "3.6.2" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.2.tgz#56a9b36ea965c00c5a93ef31eb111a0f11056967" + integrity sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA== + dependencies: + inherits "^2.0.3" + string_decoder "^1.1.1" + util-deprecate "^1.0.1" + +readdirp@~3.6.0: + version "3.6.0" + resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.6.0.tgz#74a370bd857116e245b29cc97340cd431a02a6c7" + integrity sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA== + dependencies: + picomatch "^2.2.1" + +rechoir@^0.8.0: + version "0.8.0" + resolved "https://registry.yarnpkg.com/rechoir/-/rechoir-0.8.0.tgz#49f866e0d32146142da3ad8f0eff352b3215ff22" + integrity sha512-/vxpCXddiX8NGfGO/mTafwjq4aFa/71pvamip0++IQk3zG8cbCj0fifNPrjjF1XMXUne91jL9OoxmdykoEtifQ== + dependencies: + resolve "^1.20.0" + +require-directory@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" + integrity sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q== + +require-from-string@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/require-from-string/-/require-from-string-2.0.2.tgz#89a7fdd938261267318eafe14f9c32e598c36909" + integrity sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw== + +requires-port@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/requires-port/-/requires-port-1.0.0.tgz#925d2601d39ac485e091cf0da5c6e694dc3dcaff" + integrity sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ== + +resolve-cwd@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/resolve-cwd/-/resolve-cwd-3.0.0.tgz#0f0075f1bb2544766cf73ba6a6e2adfebcb13f2d" + integrity sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg== + dependencies: + resolve-from "^5.0.0" + +resolve-from@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-5.0.0.tgz#c35225843df8f776df21c57557bc087e9dfdfc69" + integrity sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw== + +resolve@^1.20.0: + version "1.22.8" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.8.tgz#b6c87a9f2aa06dfab52e3d70ac8cde321fa5a48d" + integrity sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw== + dependencies: + is-core-module "^2.13.0" + path-parse "^1.0.7" + supports-preserve-symlinks-flag "^1.0.0" + +retry@^0.13.1: + version "0.13.1" + resolved "https://registry.yarnpkg.com/retry/-/retry-0.13.1.tgz#185b1587acf67919d63b357349e03537b2484658" + integrity sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg== + +rfdc@^1.3.0: + version "1.4.1" + resolved "https://registry.yarnpkg.com/rfdc/-/rfdc-1.4.1.tgz#778f76c4fb731d93414e8f925fbecf64cce7f6ca" + integrity sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA== + +rimraf@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-3.0.2.tgz#f1a5402ba6220ad52cc1282bac1ae3aa49fd061a" + integrity sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA== + dependencies: + glob "^7.1.3" + +rimraf@^5.0.5: + version "5.0.7" + resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-5.0.7.tgz#27bddf202e7d89cb2e0381656380d1734a854a74" + integrity sha512-nV6YcJo5wbLW77m+8KjH8aB/7/rxQy9SZ0HY5shnwULfS+9nmTtVXAJET5NdZmCzA4fPI/Hm1wo/Po/4mopOdg== + dependencies: + glob "^10.3.7" + +run-applescript@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/run-applescript/-/run-applescript-7.0.0.tgz#e5a553c2bffd620e169d276c1cd8f1b64778fbeb" + integrity sha512-9by4Ij99JUr/MCFBUkDKLWK3G9HVXmabKz9U5MlIAIuvuzkiOicRYs8XJLxX+xahD+mLiiCYDqF9dKAgtzKP1A== + +safe-buffer@5.1.2, safe-buffer@~5.1.0, safe-buffer@~5.1.1: + version "5.1.2" + resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" + integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== + +safe-buffer@5.2.1, safe-buffer@>=5.1.0, safe-buffer@^5.1.0, safe-buffer@~5.2.0: + version "5.2.1" + resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" + integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== + +"safer-buffer@>= 2.1.2 < 3", "safer-buffer@>= 2.1.2 < 3.0.0": + version "2.1.2" + resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" + integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== + +schema-utils@^3.1.1, schema-utils@^3.2.0: + version "3.3.0" + resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-3.3.0.tgz#f50a88877c3c01652a15b622ae9e9795df7a60fe" + integrity sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg== + dependencies: + "@types/json-schema" "^7.0.8" + ajv "^6.12.5" + ajv-keywords "^3.5.2" + +schema-utils@^4.0.0, schema-utils@^4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-4.2.0.tgz#70d7c93e153a273a805801882ebd3bff20d89c8b" + integrity sha512-L0jRsrPpjdckP3oPug3/VxNKt2trR8TcabrM6FOAAlvC/9Phcmm+cuAgTlxBqdBR1WJx7Naj9WHw+aOmheSVbw== + dependencies: + "@types/json-schema" "^7.0.9" + ajv "^8.9.0" + ajv-formats "^2.1.1" + ajv-keywords "^5.1.0" + +select-hose@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/select-hose/-/select-hose-2.0.0.tgz#625d8658f865af43ec962bfc376a37359a4994ca" + integrity sha512-mEugaLK+YfkijB4fx0e6kImuJdCIt2LxCRcbEYPqRGCs4F2ogyfZU5IAZRdjCP8JPq2AtdNoC/Dux63d9Kiryg== + +selfsigned@^2.4.1: + version "2.4.1" + resolved "https://registry.yarnpkg.com/selfsigned/-/selfsigned-2.4.1.tgz#560d90565442a3ed35b674034cec4e95dceb4ae0" + integrity sha512-th5B4L2U+eGLq1TVh7zNRGBapioSORUeymIydxgFpwww9d2qyKvtuPU2jJuHvYAwwqi2Y596QBL3eEqcPEYL8Q== + dependencies: + "@types/node-forge" "^1.3.0" + node-forge "^1" + +send@0.18.0: + version "0.18.0" + resolved "https://registry.yarnpkg.com/send/-/send-0.18.0.tgz#670167cc654b05f5aa4a767f9113bb371bc706be" + integrity sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg== + dependencies: + debug "2.6.9" + depd "2.0.0" + destroy "1.2.0" + encodeurl "~1.0.2" + escape-html "~1.0.3" + etag "~1.8.1" + fresh "0.5.2" + http-errors "2.0.0" + mime "1.6.0" + ms "2.1.3" + on-finished "2.4.1" + range-parser "~1.2.1" + statuses "2.0.1" + +serialize-javascript@6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-6.0.0.tgz#efae5d88f45d7924141da8b5c3a7a7e663fefeb8" + integrity sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag== + dependencies: + randombytes "^2.1.0" + +serialize-javascript@^6.0.1: + version "6.0.2" + resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-6.0.2.tgz#defa1e055c83bf6d59ea805d8da862254eb6a6c2" + integrity sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g== + dependencies: + randombytes "^2.1.0" + +serve-index@^1.9.1: + version "1.9.1" + resolved "https://registry.yarnpkg.com/serve-index/-/serve-index-1.9.1.tgz#d3768d69b1e7d82e5ce050fff5b453bea12a9239" + integrity sha512-pXHfKNP4qujrtteMrSBb0rc8HJ9Ms/GrXwcUtUtD5s4ewDJI8bT3Cz2zTVRMKtri49pLx2e0Ya8ziP5Ya2pZZw== + dependencies: + accepts "~1.3.4" + batch "0.6.1" + debug "2.6.9" + escape-html "~1.0.3" + http-errors "~1.6.2" + mime-types "~2.1.17" + parseurl "~1.3.2" + +serve-static@1.15.0: + version "1.15.0" + resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-1.15.0.tgz#faaef08cffe0a1a62f60cad0c4e513cff0ac9540" + integrity sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g== + dependencies: + encodeurl "~1.0.2" + escape-html "~1.0.3" + parseurl "~1.3.3" + send "0.18.0" + +set-function-length@^1.2.1: + version "1.2.2" + resolved "https://registry.yarnpkg.com/set-function-length/-/set-function-length-1.2.2.tgz#aac72314198eaed975cf77b2c3b6b880695e5449" + integrity sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg== + dependencies: + define-data-property "^1.1.4" + es-errors "^1.3.0" + function-bind "^1.1.2" + get-intrinsic "^1.2.4" + gopd "^1.0.1" + has-property-descriptors "^1.0.2" + +setprototypeof@1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.1.0.tgz#d0bd85536887b6fe7c0d818cb962d9d91c54e656" + integrity sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ== + +setprototypeof@1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.2.0.tgz#66c9a24a73f9fc28cbe66b09fed3d33dcaf1b424" + integrity sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw== + +shallow-clone@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/shallow-clone/-/shallow-clone-3.0.1.tgz#8f2981ad92531f55035b01fb230769a40e02efa3" + integrity sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA== + dependencies: + kind-of "^6.0.2" + +shebang-command@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-2.0.0.tgz#ccd0af4f8835fbdc265b82461aaf0c36663f34ea" + integrity sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA== + dependencies: + shebang-regex "^3.0.0" + +shebang-regex@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172" + integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A== + +shell-quote@^1.8.1: + version "1.8.1" + resolved "https://registry.yarnpkg.com/shell-quote/-/shell-quote-1.8.1.tgz#6dbf4db75515ad5bac63b4f1894c3a154c766680" + integrity sha512-6j1W9l1iAs/4xYBI1SYOVZyFcCis9b4KCLQ8fgAGG07QvzaRLVVRQvAy85yNmmZSjYjg4MWh4gNvlPujU/5LpA== + +side-channel@^1.0.4: + version "1.0.6" + resolved "https://registry.yarnpkg.com/side-channel/-/side-channel-1.0.6.tgz#abd25fb7cd24baf45466406b1096b7831c9215f2" + integrity sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA== + dependencies: + call-bind "^1.0.7" + es-errors "^1.3.0" + get-intrinsic "^1.2.4" + object-inspect "^1.13.1" + +signal-exit@^3.0.3: + version "3.0.7" + resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.7.tgz#a9a1767f8af84155114eaabd73f99273c8f59ad9" + integrity sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ== + +signal-exit@^4.0.1: + version "4.1.0" + resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-4.1.0.tgz#952188c1cbd546070e2dd20d0f41c0ae0530cb04" + integrity sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw== + +socket.io-adapter@~2.5.2: + version "2.5.5" + resolved "https://registry.yarnpkg.com/socket.io-adapter/-/socket.io-adapter-2.5.5.tgz#c7a1f9c703d7756844751b6ff9abfc1780664082" + integrity sha512-eLDQas5dzPgOWCk9GuuJC2lBqItuhKI4uxGgo9aIV7MYbk2h9Q6uULEh8WBzThoI7l+qU9Ast9fVUmkqPP9wYg== + dependencies: + debug "~4.3.4" + ws "~8.17.1" + +socket.io-parser@~4.2.4: + version "4.2.4" + resolved "https://registry.yarnpkg.com/socket.io-parser/-/socket.io-parser-4.2.4.tgz#c806966cf7270601e47469ddeec30fbdfda44c83" + integrity sha512-/GbIKmo8ioc+NIWIhwdecY0ge+qVBSMdgxGygevmdHj24bsfgtCmcUUcQ5ZzcylGFHsN3k4HB4Cgkl96KVnuew== + dependencies: + "@socket.io/component-emitter" "~3.1.0" + debug "~4.3.1" + +socket.io@^4.7.2: + version "4.7.5" + resolved "https://registry.yarnpkg.com/socket.io/-/socket.io-4.7.5.tgz#56eb2d976aef9d1445f373a62d781a41c7add8f8" + integrity sha512-DmeAkF6cwM9jSfmp6Dr/5/mfMwb5Z5qRrSXLpo3Fq5SqyU8CMF15jIN4ZhfSwu35ksM1qmHZDQ/DK5XTccSTvA== + dependencies: + accepts "~1.3.4" + base64id "~2.0.0" + cors "~2.8.5" + debug "~4.3.2" + engine.io "~6.5.2" + socket.io-adapter "~2.5.2" + socket.io-parser "~4.2.4" + +sockjs@^0.3.24: + version "0.3.24" + resolved "https://registry.yarnpkg.com/sockjs/-/sockjs-0.3.24.tgz#c9bc8995f33a111bea0395ec30aa3206bdb5ccce" + integrity sha512-GJgLTZ7vYb/JtPSSZ10hsOYIvEYsjbNU+zPdIHcUaWVNUEPivzxku31865sSSud0Da0W4lEeOPlmw93zLQchuQ== + dependencies: + faye-websocket "^0.11.3" + uuid "^8.3.2" + websocket-driver "^0.7.4" + +source-map-js@^1.0.2: + version "1.2.0" + resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-1.2.0.tgz#16b809c162517b5b8c3e7dcd315a2a5c2612b2af" + integrity sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg== + +source-map-loader@5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/source-map-loader/-/source-map-loader-5.0.0.tgz#f593a916e1cc54471cfc8851b905c8a845fc7e38" + integrity sha512-k2Dur7CbSLcAH73sBcIkV5xjPV4SzqO1NJ7+XaQl8if3VODDUj3FNchNGpqgJSKbvUfJuhVdv8K2Eu8/TNl2eA== + dependencies: + iconv-lite "^0.6.3" + source-map-js "^1.0.2" + +source-map-support@~0.5.20: + version "0.5.21" + resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.21.tgz#04fe7c7f9e1ed2d662233c28cb2b35b9f63f6e4f" + integrity sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w== + dependencies: + buffer-from "^1.0.0" + source-map "^0.6.0" + +source-map@^0.6.0, source-map@^0.6.1: + version "0.6.1" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" + integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== + +spdy-transport@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/spdy-transport/-/spdy-transport-3.0.0.tgz#00d4863a6400ad75df93361a1608605e5dcdcf31" + integrity sha512-hsLVFE5SjA6TCisWeJXFKniGGOpBgMLmerfO2aCyCU5s7nJ/rpAepqmFifv/GCbSbueEeAJJnmSQ2rKC/g8Fcw== + dependencies: + debug "^4.1.0" + detect-node "^2.0.4" + hpack.js "^2.1.6" + obuf "^1.1.2" + readable-stream "^3.0.6" + wbuf "^1.7.3" + +spdy@^4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/spdy/-/spdy-4.0.2.tgz#b74f466203a3eda452c02492b91fb9e84a27677b" + integrity sha512-r46gZQZQV+Kl9oItvl1JZZqJKGr+oEkB08A6BzkiR7593/7IbtuncXHd2YoYeTsG4157ZssMu9KYvUHLcjcDoA== + dependencies: + debug "^4.1.0" + handle-thing "^2.0.0" + http-deceiver "^1.2.7" + select-hose "^2.0.0" + spdy-transport "^3.0.0" + +statuses@2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/statuses/-/statuses-2.0.1.tgz#55cb000ccf1d48728bd23c685a063998cf1a1b63" + integrity sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ== + +"statuses@>= 1.4.0 < 2", statuses@~1.5.0: + version "1.5.0" + resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.5.0.tgz#161c7dac177659fd9811f43771fa99381478628c" + integrity sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA== + +streamroller@^3.1.5: + version "3.1.5" + resolved "https://registry.yarnpkg.com/streamroller/-/streamroller-3.1.5.tgz#1263182329a45def1ffaef58d31b15d13d2ee7ff" + integrity sha512-KFxaM7XT+irxvdqSP1LGLgNWbYN7ay5owZ3r/8t77p+EtSUAfUgtl7be3xtqtOmGUl9K9YPO2ca8133RlTjvKw== + dependencies: + date-format "^4.0.14" + debug "^4.3.4" + fs-extra "^8.1.0" + +"string-width-cjs@npm:string-width@^4.2.0", string-width@^4.1.0, string-width@^4.2.0: + version "4.2.3" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" + integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== + dependencies: + emoji-regex "^8.0.0" + is-fullwidth-code-point "^3.0.0" + strip-ansi "^6.0.1" + +string-width@^5.0.1, string-width@^5.1.2: + version "5.1.2" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-5.1.2.tgz#14f8daec6d81e7221d2a357e668cab73bdbca794" + integrity sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA== + dependencies: + eastasianwidth "^0.2.0" + emoji-regex "^9.2.2" + strip-ansi "^7.0.1" + +string_decoder@^1.1.1: + version "1.3.0" + resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.3.0.tgz#42f114594a46cf1a8e30b0a84f56c78c3edac21e" + integrity sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA== + dependencies: + safe-buffer "~5.2.0" + +string_decoder@~1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.1.1.tgz#9cf1611ba62685d7030ae9e4ba34149c3af03fc8" + integrity sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg== + dependencies: + safe-buffer "~5.1.0" + +"strip-ansi-cjs@npm:strip-ansi@^6.0.1", strip-ansi@^6.0.0, strip-ansi@^6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" + integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== + dependencies: + ansi-regex "^5.0.1" + +strip-ansi@^7.0.1: + version "7.1.0" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-7.1.0.tgz#d5b6568ca689d8561370b0707685d22434faff45" + integrity sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ== + dependencies: + ansi-regex "^6.0.1" + +strip-final-newline@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/strip-final-newline/-/strip-final-newline-2.0.0.tgz#89b852fb2fcbe936f6f4b3187afb0a12c1ab58ad" + integrity sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA== + +strip-json-comments@3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006" + integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig== + +supports-color@8.1.1, supports-color@^8.0.0: + version "8.1.1" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-8.1.1.tgz#cd6fc17e28500cff56c1b86c0a7fd4a54a73005c" + integrity sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q== + dependencies: + has-flag "^4.0.0" + +supports-color@^7.1.0: + version "7.2.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.2.0.tgz#1b7dcdcb32b8138801b3e478ba6a51caa89648da" + integrity sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw== + dependencies: + has-flag "^4.0.0" + +supports-preserve-symlinks-flag@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz#6eda4bd344a3c94aea376d4cc31bc77311039e09" + integrity sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w== + +tapable@^2.1.1, tapable@^2.2.0: + version "2.2.1" + resolved "https://registry.yarnpkg.com/tapable/-/tapable-2.2.1.tgz#1967a73ef4060a82f12ab96af86d52fdb76eeca0" + integrity sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ== + +terser-webpack-plugin@^5.3.10: + version "5.3.10" + resolved "https://registry.yarnpkg.com/terser-webpack-plugin/-/terser-webpack-plugin-5.3.10.tgz#904f4c9193c6fd2a03f693a2150c62a92f40d199" + integrity sha512-BKFPWlPDndPs+NGGCr1U59t0XScL5317Y0UReNrHaw9/FwhPENlq6bfgs+4yPfyP51vqC1bQ4rp1EfXW5ZSH9w== + dependencies: + "@jridgewell/trace-mapping" "^0.3.20" + jest-worker "^27.4.5" + schema-utils "^3.1.1" + serialize-javascript "^6.0.1" + terser "^5.26.0" + +terser@^5.26.0: + version "5.31.1" + resolved "https://registry.yarnpkg.com/terser/-/terser-5.31.1.tgz#735de3c987dd671e95190e6b98cfe2f07f3cf0d4" + integrity sha512-37upzU1+viGvuFtBo9NPufCb9dwM0+l9hMxYyWfBA+fbwrPqNJAhbZ6W47bBFnZHKHTUBnMvi87434qq+qnxOg== + dependencies: + "@jridgewell/source-map" "^0.3.3" + acorn "^8.8.2" + commander "^2.20.0" + source-map-support "~0.5.20" + +thingies@^1.20.0: + version "1.21.0" + resolved "https://registry.yarnpkg.com/thingies/-/thingies-1.21.0.tgz#e80fbe58fd6fdaaab8fad9b67bd0a5c943c445c1" + integrity sha512-hsqsJsFMsV+aD4s3CWKk85ep/3I9XzYV/IXaSouJMYIoDlgyi11cBhsqYe9/geRfB0YIikBQg6raRaM+nIMP9g== + +thunky@^1.0.2: + version "1.1.0" + resolved "https://registry.yarnpkg.com/thunky/-/thunky-1.1.0.tgz#5abaf714a9405db0504732bbccd2cedd9ef9537d" + integrity sha512-eHY7nBftgThBqOyHGVN+l8gF0BucP09fMo0oO/Lb0w1OF80dJv+lDVpXG60WMQvkcxAkNybKsrEIE3ZtKGmPrA== + +tmp@^0.2.1: + version "0.2.3" + resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.2.3.tgz#eb783cc22bc1e8bebd0671476d46ea4eb32a79ae" + integrity sha512-nZD7m9iCPC5g0pYmcaxogYKggSfLsdxl8of3Q/oIbqCqLLIO9IAF0GWjX1z9NZRHPiXv8Wex4yDCaZsgEw0Y8w== + +to-regex-range@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4" + integrity sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ== + dependencies: + is-number "^7.0.0" + +toidentifier@1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.1.tgz#3be34321a88a820ed1bd80dfaa33e479fbb8dd35" + integrity sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA== + +tr46@~0.0.3: + version "0.0.3" + resolved "https://registry.yarnpkg.com/tr46/-/tr46-0.0.3.tgz#8184fd347dac9cdc185992f3a6622e14b9d9ab6a" + integrity sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw== + +tree-dump@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/tree-dump/-/tree-dump-1.0.2.tgz#c460d5921caeb197bde71d0e9a7b479848c5b8ac" + integrity sha512-dpev9ABuLWdEubk+cIaI9cHwRNNDjkBBLXTwI4UCUFdQ5xXKqNXoK4FEciw/vxf+NQ7Cb7sGUyeUtORvHIdRXQ== + +tslib@^2.0.0: + version "2.6.3" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.6.3.tgz#0438f810ad7a9edcde7a241c3d80db693c8cbfe0" + integrity sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ== + +type-is@~1.6.18: + version "1.6.18" + resolved "https://registry.yarnpkg.com/type-is/-/type-is-1.6.18.tgz#4e552cd05df09467dcbc4ef739de89f2cf37c131" + integrity sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g== + dependencies: + media-typer "0.3.0" + mime-types "~2.1.24" + +typescript@5.4.3: + version "5.4.3" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.4.3.tgz#5c6fedd4c87bee01cd7a528a30145521f8e0feff" + integrity sha512-KrPd3PKaCLr78MalgiwJnA25Nm8HAmdwN3mYUYZgG/wizIo9EainNVQI9/yDavtVFRN2h3k8uf3GLHuhDMgEHg== + +ua-parser-js@^0.7.30: + version "0.7.38" + resolved "https://registry.yarnpkg.com/ua-parser-js/-/ua-parser-js-0.7.38.tgz#f497d8a4dc1fec6e854e5caa4b2f9913422ef054" + integrity sha512-fYmIy7fKTSFAhG3fuPlubeGaMoAd6r0rSnfEsO5nEY55i26KSLt9EH7PLQiiqPUhNqYIJvSkTy1oArIcXAbPbA== + +undici-types@~5.26.4: + version "5.26.5" + resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-5.26.5.tgz#bcd539893d00b56e964fd2657a4866b221a65617" + integrity sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA== + +universalify@^0.1.0: + version "0.1.2" + resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.1.2.tgz#b646f69be3942dabcecc9d6639c80dc105efaa66" + integrity sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg== + +unpipe@1.0.0, unpipe@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec" + integrity sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ== + +update-browserslist-db@^1.0.16: + version "1.0.16" + resolved "https://registry.yarnpkg.com/update-browserslist-db/-/update-browserslist-db-1.0.16.tgz#f6d489ed90fb2f07d67784eb3f53d7891f736356" + integrity sha512-KVbTxlBYlckhF5wgfyZXTWnMn7MMZjMu9XG8bPlliUOP9ThaF4QnhP8qrjrH7DRzHfSk0oQv1wToW+iA5GajEQ== + dependencies: + escalade "^3.1.2" + picocolors "^1.0.1" + +uri-js@^4.2.2, uri-js@^4.4.1: + version "4.4.1" + resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.4.1.tgz#9b1a52595225859e55f669d928f88c6c57f2a77e" + integrity sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg== + dependencies: + punycode "^2.1.0" + +util-deprecate@^1.0.1, util-deprecate@~1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" + integrity sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw== + +utils-merge@1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/utils-merge/-/utils-merge-1.0.1.tgz#9f95710f50a267947b2ccc124741c1028427e713" + integrity sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA== + +uuid@^8.3.2: + version "8.3.2" + resolved "https://registry.yarnpkg.com/uuid/-/uuid-8.3.2.tgz#80d5b5ced271bb9af6c445f21a1a04c606cefbe2" + integrity sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg== + +vary@^1, vary@~1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc" + integrity sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg== + +void-elements@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/void-elements/-/void-elements-2.0.1.tgz#c066afb582bb1cb4128d60ea92392e94d5e9dbec" + integrity sha512-qZKX4RnBzH2ugr8Lxa7x+0V6XD9Sb/ouARtiasEQCHB1EVU4NXtmHsDDrx1dO4ne5fc3J6EW05BP1Dl0z0iung== + +watchpack@^2.4.1: + version "2.4.1" + resolved "https://registry.yarnpkg.com/watchpack/-/watchpack-2.4.1.tgz#29308f2cac150fa8e4c92f90e0ec954a9fed7fff" + integrity sha512-8wrBCMtVhqcXP2Sup1ctSkga6uc2Bx0IIvKyT7yTFier5AXHooSI+QyQQAtTb7+E0IUCCKyTFmXqdqgum2XWGg== + dependencies: + glob-to-regexp "^0.4.1" + graceful-fs "^4.1.2" + +wbuf@^1.1.0, wbuf@^1.7.3: + version "1.7.3" + resolved "https://registry.yarnpkg.com/wbuf/-/wbuf-1.7.3.tgz#c1d8d149316d3ea852848895cb6a0bfe887b87df" + integrity sha512-O84QOnr0icsbFGLS0O3bI5FswxzRr8/gHwWkDlQFskhSPryQXvrTMxjxGP4+iWYoauLoBvfDpkrOauZ+0iZpDA== + dependencies: + minimalistic-assert "^1.0.0" + +webidl-conversions@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-3.0.1.tgz#24534275e2a7bc6be7bc86611cc16ae0a5654871" + integrity sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ== + +webpack-cli@5.1.4: + version "5.1.4" + resolved "https://registry.yarnpkg.com/webpack-cli/-/webpack-cli-5.1.4.tgz#c8e046ba7eaae4911d7e71e2b25b776fcc35759b" + integrity sha512-pIDJHIEI9LR0yxHXQ+Qh95k2EvXpWzZ5l+d+jIo+RdSm9MiHfzazIxwwni/p7+x4eJZuvG1AJwgC4TNQ7NRgsg== + dependencies: + "@discoveryjs/json-ext" "^0.5.0" + "@webpack-cli/configtest" "^2.1.1" + "@webpack-cli/info" "^2.0.2" + "@webpack-cli/serve" "^2.0.5" + colorette "^2.0.14" + commander "^10.0.1" + cross-spawn "^7.0.3" + envinfo "^7.7.3" + fastest-levenshtein "^1.0.12" + import-local "^3.0.2" + interpret "^3.1.1" + rechoir "^0.8.0" + webpack-merge "^5.7.3" + +webpack-dev-middleware@^7.1.0: + version "7.2.1" + resolved "https://registry.yarnpkg.com/webpack-dev-middleware/-/webpack-dev-middleware-7.2.1.tgz#2af00538b6e4eda05f5afdd5d711dbebc05958f7" + integrity sha512-hRLz+jPQXo999Nx9fXVdKlg/aehsw1ajA9skAneGmT03xwmyuhvF93p6HUKKbWhXdcERtGTzUCtIQr+2IQegrA== + dependencies: + colorette "^2.0.10" + memfs "^4.6.0" + mime-types "^2.1.31" + on-finished "^2.4.1" + range-parser "^1.2.1" + schema-utils "^4.0.0" + +webpack-dev-server@5.0.4: + version "5.0.4" + resolved "https://registry.yarnpkg.com/webpack-dev-server/-/webpack-dev-server-5.0.4.tgz#cb6ea47ff796b9251ec49a94f24a425e12e3c9b8" + integrity sha512-dljXhUgx3HqKP2d8J/fUMvhxGhzjeNVarDLcbO/EWMSgRizDkxHQDZQaLFL5VJY9tRBj2Gz+rvCEYYvhbqPHNA== + dependencies: + "@types/bonjour" "^3.5.13" + "@types/connect-history-api-fallback" "^1.5.4" + "@types/express" "^4.17.21" + "@types/serve-index" "^1.9.4" + "@types/serve-static" "^1.15.5" + "@types/sockjs" "^0.3.36" + "@types/ws" "^8.5.10" + ansi-html-community "^0.0.8" + bonjour-service "^1.2.1" + chokidar "^3.6.0" + colorette "^2.0.10" + compression "^1.7.4" + connect-history-api-fallback "^2.0.0" + default-gateway "^6.0.3" + express "^4.17.3" + graceful-fs "^4.2.6" + html-entities "^2.4.0" + http-proxy-middleware "^2.0.3" + ipaddr.js "^2.1.0" + launch-editor "^2.6.1" + open "^10.0.3" + p-retry "^6.2.0" + rimraf "^5.0.5" + schema-utils "^4.2.0" + selfsigned "^2.4.1" + serve-index "^1.9.1" + sockjs "^0.3.24" + spdy "^4.0.2" + webpack-dev-middleware "^7.1.0" + ws "^8.16.0" + +webpack-merge@^4.1.5: + version "4.2.2" + resolved "https://registry.yarnpkg.com/webpack-merge/-/webpack-merge-4.2.2.tgz#a27c52ea783d1398afd2087f547d7b9d2f43634d" + integrity sha512-TUE1UGoTX2Cd42j3krGYqObZbOD+xF7u28WB7tfUordytSjbWTIjK/8V0amkBfTYN4/pB/GIDlJZZ657BGG19g== + dependencies: + lodash "^4.17.15" + +webpack-merge@^5.7.3: + version "5.10.0" + resolved "https://registry.yarnpkg.com/webpack-merge/-/webpack-merge-5.10.0.tgz#a3ad5d773241e9c682803abf628d4cd62b8a4177" + integrity sha512-+4zXKdx7UnO+1jaN4l2lHVD+mFvnlZQP/6ljaJVb4SZiwIKeUnrT5l0gkT8z+n4hKpC+jpOv6O9R+gLtag7pSA== + dependencies: + clone-deep "^4.0.1" + flat "^5.0.2" + wildcard "^2.0.0" + +webpack-sources@^3.2.3: + version "3.2.3" + resolved "https://registry.yarnpkg.com/webpack-sources/-/webpack-sources-3.2.3.tgz#2d4daab8451fd4b240cc27055ff6a0c2ccea0cde" + integrity sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w== + +webpack@5.91.0: + version "5.91.0" + resolved "https://registry.yarnpkg.com/webpack/-/webpack-5.91.0.tgz#ffa92c1c618d18c878f06892bbdc3373c71a01d9" + integrity sha512-rzVwlLeBWHJbmgTC/8TvAcu5vpJNII+MelQpylD4jNERPwpBJOE2lEcko1zJX3QJeLjTTAnQxn/OJ8bjDzVQaw== + dependencies: + "@types/eslint-scope" "^3.7.3" + "@types/estree" "^1.0.5" + "@webassemblyjs/ast" "^1.12.1" + "@webassemblyjs/wasm-edit" "^1.12.1" + "@webassemblyjs/wasm-parser" "^1.12.1" + acorn "^8.7.1" + acorn-import-assertions "^1.9.0" + browserslist "^4.21.10" + chrome-trace-event "^1.0.2" + enhanced-resolve "^5.16.0" + es-module-lexer "^1.2.1" + eslint-scope "5.1.1" + events "^3.2.0" + glob-to-regexp "^0.4.1" + graceful-fs "^4.2.11" + json-parse-even-better-errors "^2.3.1" + loader-runner "^4.2.0" + mime-types "^2.1.27" + neo-async "^2.6.2" + schema-utils "^3.2.0" + tapable "^2.1.1" + terser-webpack-plugin "^5.3.10" + watchpack "^2.4.1" + webpack-sources "^3.2.3" + +websocket-driver@>=0.5.1, websocket-driver@^0.7.4: + version "0.7.4" + resolved "https://registry.yarnpkg.com/websocket-driver/-/websocket-driver-0.7.4.tgz#89ad5295bbf64b480abcba31e4953aca706f5760" + integrity sha512-b17KeDIQVjvb0ssuSDF2cYXSg2iztliJ4B9WdsuB6J952qCPKmnVq4DyW5motImXHDC1cBT/1UezrJVsKw5zjg== + dependencies: + http-parser-js ">=0.5.1" + safe-buffer ">=5.1.0" + websocket-extensions ">=0.1.1" + +websocket-extensions@>=0.1.1: + version "0.1.4" + resolved "https://registry.yarnpkg.com/websocket-extensions/-/websocket-extensions-0.1.4.tgz#7f8473bc839dfd87608adb95d7eb075211578a42" + integrity sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg== + +whatwg-url@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-5.0.0.tgz#966454e8765462e37644d3626f6742ce8b70965d" + integrity sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw== + dependencies: + tr46 "~0.0.3" + webidl-conversions "^3.0.0" + +which@^1.2.1: + version "1.3.1" + resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a" + integrity sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ== + dependencies: + isexe "^2.0.0" + +which@^2.0.1: + version "2.0.2" + resolved "https://registry.yarnpkg.com/which/-/which-2.0.2.tgz#7c6a8dd0a636a0327e10b59c9286eee93f3f51b1" + integrity sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA== + dependencies: + isexe "^2.0.0" + +wildcard@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/wildcard/-/wildcard-2.0.1.tgz#5ab10d02487198954836b6349f74fff961e10f67" + integrity sha512-CC1bOL87PIWSBhDcTrdeLo6eGT7mCFtrg0uIJtqJUFyK+eJnzl8A1niH56uu7KMa5XFrtiV+AQuHO3n7DsHnLQ== + +workerpool@6.2.1: + version "6.2.1" + resolved "https://registry.yarnpkg.com/workerpool/-/workerpool-6.2.1.tgz#46fc150c17d826b86a008e5a4508656777e9c343" + integrity sha512-ILEIE97kDZvF9Wb9f6h5aXK4swSlKGUcOEGiIYb2OOu/IrDU9iwj0fD//SsA6E5ibwJxpEvhullJY4Sl4GcpAw== + +"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0", wrap-ansi@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" + integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== + dependencies: + ansi-styles "^4.0.0" + string-width "^4.1.0" + strip-ansi "^6.0.0" + +wrap-ansi@^8.1.0: + version "8.1.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-8.1.0.tgz#56dc22368ee570face1b49819975d9b9a5ead214" + integrity sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ== + dependencies: + ansi-styles "^6.1.0" + string-width "^5.0.1" + strip-ansi "^7.0.1" + +wrappy@1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" + integrity sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ== + +ws@8.5.0: + version "8.5.0" + resolved "https://registry.yarnpkg.com/ws/-/ws-8.5.0.tgz#bfb4be96600757fe5382de12c670dab984a1ed4f" + integrity sha512-BWX0SWVgLPzYwF8lTzEy1egjhS4S4OEAHfsO8o65WOVsrnSRGaSiUaa9e0ggGlkMTtBlmOpEXiie9RUcBO86qg== + +ws@^8.16.0, ws@~8.17.1: + version "8.17.1" + resolved "https://registry.yarnpkg.com/ws/-/ws-8.17.1.tgz#9293da530bb548febc95371d90f9c878727d919b" + integrity sha512-6XQFvXTkbfUOZOKKILFG1PDK2NDQs4azKQl26T0YS5CxqWLgXajbPZ+h4gZekJyRqFU8pvnbAbbs/3TgRPy+GQ== + +y18n@^5.0.5: + version "5.0.8" + resolved "https://registry.yarnpkg.com/y18n/-/y18n-5.0.8.tgz#7f4934d0f7ca8c56f95314939ddcd2dd91ce1d55" + integrity sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA== + +yargs-parser@20.2.4: + version "20.2.4" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-20.2.4.tgz#b42890f14566796f85ae8e3a25290d205f154a54" + integrity sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA== + +yargs-parser@^20.2.2: + version "20.2.9" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-20.2.9.tgz#2eb7dc3b0289718fc295f362753845c41a0c94ee" + integrity sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w== + +yargs-unparser@2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/yargs-unparser/-/yargs-unparser-2.0.0.tgz#f131f9226911ae5d9ad38c432fe809366c2325eb" + integrity sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA== + dependencies: + camelcase "^6.0.0" + decamelize "^4.0.0" + flat "^5.0.2" + is-plain-obj "^2.1.0" + +yargs@16.2.0, yargs@^16.1.1: + version "16.2.0" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-16.2.0.tgz#1c82bf0f6b6a66eafce7ef30e376f49a12477f66" + integrity sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw== + dependencies: + cliui "^7.0.2" + escalade "^3.1.1" + get-caller-file "^2.0.5" + require-directory "^2.1.1" + string-width "^4.2.0" + y18n "^5.0.5" + yargs-parser "^20.2.2" + +yocto-queue@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b" + integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q== diff --git a/settings.gradle b/settings.gradle index a9dd4a99ba1..5ceeaa233b5 100644 --- a/settings.gradle +++ b/settings.gradle @@ -32,6 +32,7 @@ plugins { apply from: file('gradle/develocity.gradle') rootProject.name = "solr-root" +enableFeaturePreview("TYPESAFE_PROJECT_ACCESSORS") includeBuild("build-tools/missing-doclet") @@ -66,6 +67,7 @@ include "solr:packaging" include "solr:distribution" include "solr:docker" include "solr:prometheus-exporter" +include "solr:compose-ui" // Configures development for joint Lucene/ Solr composite build. apply from: file('gradle/lucene-dev/lucene-dev-repo-composite.gradle') diff --git a/solr/compose-ui/build.gradle.kts b/solr/compose-ui/build.gradle.kts new file mode 100644 index 00000000000..5203ef37423 --- /dev/null +++ b/solr/compose-ui/build.gradle.kts @@ -0,0 +1,126 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import org.jetbrains.compose.desktop.application.dsl.TargetFormat +import org.jetbrains.kotlin.gradle.targets.js.dsl.ExperimentalWasmDsl +import org.jetbrains.kotlin.gradle.targets.js.webpack.KotlinWebpackConfig + +repositories { + google { + mavenContent { + includeGroupAndSubgroups("androidx") + includeGroupAndSubgroups("com.android") + includeGroupAndSubgroups("com.google") + } + } + mavenCentral() +} + +plugins { + alias(libs.plugins.kotlinMultiplatform) + alias(libs.plugins.jetbrainsCompose) + alias(libs.plugins.compose.compiler) +} + +kotlin { + + // Add targets to support + @OptIn(ExperimentalWasmDsl::class) + wasmJs { + moduleName = "composeApp" + browser { + commonWebpackConfig { + outputFileName = "composeApp.js" + devServer = (devServer ?: KotlinWebpackConfig.DevServer()).apply { + static = (static ?: mutableListOf()).apply { + // Serve sources to debug inside browser + add(project.projectDir.path) + } + } + } + } + binaries.executable() + } + + jvm("desktop") + + sourceSets { + // Shared multiplatform dependencies + val commonMain by getting { + dependencies { + implementation(compose.runtime) + implementation(compose.foundation) + implementation(compose.material3) + implementation(compose.ui) + implementation(compose.components.resources) + implementation(compose.components.uiToolingPreview) + implementation(compose.materialIconsExtended) + + implementation(libs.kotlinx.datetime) + implementation(libs.decompose.decompose) + implementation(libs.essenty.lifecycle) + implementation(libs.decompose.extensions.compose) + implementation(libs.mvikotlin.mvikotlin) + implementation(libs.mvikotlin.main) + implementation(libs.mvikotlin.logging) + + implementation(libs.ktor.client.core) + + implementation(libs.oshai.logging) + implementation(libs.slf4j.api) + } + } + + val commonTest by getting { + dependencies { + implementation(kotlin("test")) + } + } + + val desktopMain by getting { + dependencies { + implementation(compose.desktop.currentOs) + implementation(libs.ktor.client.cio) + } + } + + val wasmJsMain by getting { + dependencies { + implementation(libs.ktor.client.js) + } + } + } +} + +configurations { + all { + // Exclude old material dependencies + exclude(group = "org.jetbrains.compose.material", module = "material") + } +} + +compose.desktop { + application { + mainClass = "org.apache.solr.composeui.MainKt" + + nativeDistributions { + targetFormats(TargetFormat.Dmg, TargetFormat.Msi, TargetFormat.Deb) + packageName = "org.apache.solr.composeui" + packageVersion = "1.0.0" + } + } +} diff --git a/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/components/root/RootComponent.kt b/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/components/root/RootComponent.kt new file mode 100644 index 00000000000..676e3672443 --- /dev/null +++ b/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/components/root/RootComponent.kt @@ -0,0 +1,20 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.solr.composeui.components.root + +interface RootComponent \ No newline at end of file diff --git a/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/components/root/integration/DefaultRootComponent.kt b/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/components/root/integration/DefaultRootComponent.kt new file mode 100644 index 00000000000..c177bff7d30 --- /dev/null +++ b/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/components/root/integration/DefaultRootComponent.kt @@ -0,0 +1,29 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.solr.composeui.components.root.integration + +import com.arkivanov.mvikotlin.core.store.StoreFactory +import org.apache.solr.composeui.components.root.RootComponent +import org.apache.solr.composeui.utils.AppComponentContext + +class DefaultRootComponent( + componentContext: AppComponentContext, + storeFactory: StoreFactory, +) : RootComponent, AppComponentContext by componentContext { + +} diff --git a/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/ui/root/RootContent.kt b/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/ui/root/RootContent.kt new file mode 100644 index 00000000000..2d720f294ab --- /dev/null +++ b/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/ui/root/RootContent.kt @@ -0,0 +1,35 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.solr.composeui.ui.root + +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import org.apache.solr.composeui.components.root.RootComponent + +/** + * The root composable of the Compose application. This function is used as the shared entry + * point of all targets. + * + * @param component Component that manages the state of the root composable. + */ +@Composable +fun RootContent( + component: RootComponent, +) { + Text("Hello World!") +} diff --git a/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/ui/theme/Colors.kt b/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/ui/theme/Colors.kt new file mode 100644 index 00000000000..14c4a8e83fe --- /dev/null +++ b/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/ui/theme/Colors.kt @@ -0,0 +1,20 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.solr.composeui.ui.theme + +// TODO Add Solr base colors here diff --git a/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/ui/theme/Fonts.kt b/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/ui/theme/Fonts.kt new file mode 100644 index 00000000000..66b96886544 --- /dev/null +++ b/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/ui/theme/Fonts.kt @@ -0,0 +1,29 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.solr.composeui.ui.theme + +import androidx.compose.material3.Typography + +/** + * Custom typography that styles headlines and titles with a different font. + */ +val SolrCodeTypography = Typography( + // TODO Override headlines and titles +) + +// TODO Add fonts for code blocks diff --git a/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/ui/theme/Shapes.kt b/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/ui/theme/Shapes.kt new file mode 100644 index 00000000000..65edf500b00 --- /dev/null +++ b/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/ui/theme/Shapes.kt @@ -0,0 +1,31 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.solr.composeui.ui.theme + +import androidx.compose.foundation.shape.CutCornerShape +import androidx.compose.material3.Shapes +import androidx.compose.ui.unit.dp + +/** + * Custom shapes that do not use rounded corners for elements. + */ +internal val SolrShapes = Shapes( + small = CutCornerShape(0.dp), + medium = CutCornerShape(0.dp), + large = CutCornerShape(0.dp), +) diff --git a/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/ui/theme/Theme.kt b/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/ui/theme/Theme.kt new file mode 100644 index 00000000000..d16f8ee73cd --- /dev/null +++ b/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/ui/theme/Theme.kt @@ -0,0 +1,48 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.solr.composeui.ui.theme + +import androidx.compose.foundation.isSystemInDarkTheme +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.darkColorScheme +import androidx.compose.material3.lightColorScheme +import androidx.compose.runtime.Composable + +private val LightColors = lightColorScheme( + // TODO Override light theme colors here +) + +private val DarkColors = darkColorScheme( + // TODO Override dark theme colors here +) + +@Composable +fun SolrTheme( + useDarkTheme: Boolean = isSystemInDarkTheme(), + content: @Composable () -> Unit +) { + val colors = if (useDarkTheme) DarkColors + else LightColors + + MaterialTheme( + colorScheme = colors, + shapes = SolrShapes, + typography = SolrCodeTypography, + content = content + ) +} \ No newline at end of file diff --git a/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/utils/AppComponentContext.kt b/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/utils/AppComponentContext.kt new file mode 100644 index 00000000000..19efd6c8364 --- /dev/null +++ b/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/utils/AppComponentContext.kt @@ -0,0 +1,26 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.solr.composeui.utils + +import com.arkivanov.decompose.GenericComponentContext + +/** + * The application component context that provides basic functionality to all components, including + * a lifecycle, state preservation, navigation handling and coroutine contexts. + */ +interface AppComponentContext : GenericComponentContext, CoroutineContextOwner diff --git a/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/utils/CoroutineContextOwner.kt b/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/utils/CoroutineContextOwner.kt new file mode 100644 index 00000000000..a39de3dfcaf --- /dev/null +++ b/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/utils/CoroutineContextOwner.kt @@ -0,0 +1,37 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.solr.composeui.utils + +import kotlin.coroutines.CoroutineContext + +/** + * Coroutine context owner that holds two coroutine contexts, main and IO. + */ +interface CoroutineContextOwner { + + /** + * Main coroutine context that is used for operations closely related to UI. + * These operations typically don't fail. + */ + val mainContext: CoroutineContext + + /** + * [CoroutineContext] used for IO operations. These operations are more likely to fail. + */ + val ioContext: CoroutineContext +} diff --git a/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/utils/DefaultAppComponentContext.kt b/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/utils/DefaultAppComponentContext.kt new file mode 100644 index 00000000000..4fea772bc68 --- /dev/null +++ b/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/utils/DefaultAppComponentContext.kt @@ -0,0 +1,56 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.solr.composeui.utils + +import com.arkivanov.decompose.ComponentContext +import com.arkivanov.decompose.ComponentContextFactory +import com.arkivanov.essenty.backhandler.BackHandlerOwner +import com.arkivanov.essenty.instancekeeper.InstanceKeeperOwner +import com.arkivanov.essenty.lifecycle.LifecycleOwner +import com.arkivanov.essenty.statekeeper.StateKeeperOwner +import kotlin.coroutines.CoroutineContext + +/** + * Default implementation of the [AppComponentContext]. Can be also used in tests with test-specific + * coroutine contexts. + */ +class DefaultAppComponentContext( + componentContext: ComponentContext, + override val mainContext: CoroutineContext, + override val ioContext: CoroutineContext, +) : AppComponentContext, + LifecycleOwner by componentContext, + StateKeeperOwner by componentContext, + InstanceKeeperOwner by componentContext, + BackHandlerOwner by componentContext { + + override val componentContextFactory: ComponentContextFactory = + ComponentContextFactory { lifecycle, stateKeeper, instanceKeeper, backHandler -> + val ctx = componentContext.componentContextFactory( + lifecycle = lifecycle, + stateKeeper = stateKeeper, + instanceKeeper = instanceKeeper, + backHandler = backHandler, + ) + DefaultAppComponentContext( + componentContext = ctx, + mainContext = mainContext, + ioContext = ioContext, + ) + } +} diff --git a/solr/compose-ui/src/desktopMain/kotlin/org/apache/solr/composeui/Main.kt b/solr/compose-ui/src/desktopMain/kotlin/org/apache/solr/composeui/Main.kt new file mode 100644 index 00000000000..2a71fe35d57 --- /dev/null +++ b/solr/compose-ui/src/desktopMain/kotlin/org/apache/solr/composeui/Main.kt @@ -0,0 +1,83 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.solr.composeui + +import androidx.compose.foundation.isSystemInDarkTheme +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.material3.Surface +import androidx.compose.ui.Modifier +import androidx.compose.ui.window.Window +import androidx.compose.ui.window.application +import androidx.compose.ui.window.rememberWindowState +import com.arkivanov.decompose.DefaultComponentContext +import com.arkivanov.decompose.extensions.compose.lifecycle.LifecycleController +import com.arkivanov.essenty.lifecycle.LifecycleRegistry +import com.arkivanov.mvikotlin.core.utils.setMainThreadId +import com.arkivanov.mvikotlin.main.store.DefaultStoreFactory +import java.awt.Dimension +import kotlinx.coroutines.Dispatchers +import org.apache.solr.composeui.components.root.RootComponent +import org.apache.solr.composeui.components.root.integration.DefaultRootComponent +import org.apache.solr.composeui.ui.root.RootContent +import org.apache.solr.composeui.ui.theme.SolrTheme +import org.apache.solr.composeui.utils.DefaultAppComponentContext + +/** + * Entry point of the Compose application for all JVM-based (desktop) targets. + * + * This function sets up the lifecycle management and instantiates the [RootComponent] with the + * [DefaultAppComponentContext] that is used by all child components. + */ +fun main() { + val lifecycle = LifecycleRegistry() + val componentContext = DefaultAppComponentContext( + componentContext = DefaultComponentContext(lifecycle = lifecycle), + mainContext = Dispatchers.Main, + ioContext = Dispatchers.IO, + ) + + val storeFactory = DefaultStoreFactory() + + val root: RootComponent = runOnUiThread { + setMainThreadId(Thread.currentThread().id) + + DefaultRootComponent( + componentContext = componentContext, + storeFactory = storeFactory, + ) + } + + application { + val windowState = rememberWindowState() + LifecycleController(lifecycle, windowState) + + Window( + onCloseRequest = ::exitApplication, + state = windowState, + title = "Solr Admin UI" + ) { + window.minimumSize = Dimension(720, 560) + + SolrTheme(useDarkTheme = isSystemInDarkTheme()) { + Surface(modifier = Modifier.fillMaxSize()) { + RootContent(root) + } + } + } + } +} diff --git a/solr/compose-ui/src/desktopMain/kotlin/org/apache/solr/composeui/Utils.kt b/solr/compose-ui/src/desktopMain/kotlin/org/apache/solr/composeui/Utils.kt new file mode 100644 index 00000000000..4f351f201bf --- /dev/null +++ b/solr/compose-ui/src/desktopMain/kotlin/org/apache/solr/composeui/Utils.kt @@ -0,0 +1,45 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.solr.composeui + +import javax.swing.SwingUtilities + +/** + * Ensures that a code [block] is executed on the UI thread. + */ +internal fun runOnUiThread(block: () -> T): T { + if (SwingUtilities.isEventDispatchThread()) { + return block() + } + + var error: Throwable? = null + var result: T? = null + + SwingUtilities.invokeAndWait { + try { + result = block() + } catch (e: Throwable) { + error = e + } + } + + error?.also { throw it } + + @Suppress("UNCHECKED_CAST") + return result as T +} diff --git a/solr/compose-ui/src/wasmJsMain/kotlin/org/apache/solr/composeui/Main.kt b/solr/compose-ui/src/wasmJsMain/kotlin/org/apache/solr/composeui/Main.kt new file mode 100644 index 00000000000..54e3a1f3011 --- /dev/null +++ b/solr/compose-ui/src/wasmJsMain/kotlin/org/apache/solr/composeui/Main.kt @@ -0,0 +1,65 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.solr.composeui + +import androidx.compose.foundation.isSystemInDarkTheme +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.material3.Surface +import androidx.compose.material3.Text +import androidx.compose.ui.ExperimentalComposeUiApi +import androidx.compose.ui.Modifier +import androidx.compose.ui.window.ComposeViewport +import com.arkivanov.decompose.DefaultComponentContext +import com.arkivanov.essenty.lifecycle.LifecycleRegistry +import com.arkivanov.mvikotlin.main.store.DefaultStoreFactory +import kotlinx.browser.document +import kotlinx.coroutines.Dispatchers +import org.apache.solr.composeui.components.root.RootComponent +import org.apache.solr.composeui.components.root.integration.DefaultRootComponent +import org.apache.solr.composeui.ui.root.RootContent +import org.apache.solr.composeui.ui.theme.SolrTheme +import org.apache.solr.composeui.utils.DefaultAppComponentContext + +/** + * Entry point of the Compose application for all wasmJs (browser) targets. + * + * This function sets up the lifecycle management and instantiates the [RootComponent] with the + * [DefaultAppComponentContext] that is used by all child components. + */ +@OptIn(ExperimentalComposeUiApi::class) +fun main() { + val lifecycle = LifecycleRegistry() + val componentContext = DefaultAppComponentContext( + componentContext = DefaultComponentContext(lifecycle = lifecycle), + mainContext = Dispatchers.Main, + ioContext = Dispatchers.Default, + ) + + val component: RootComponent = DefaultRootComponent( + componentContext = componentContext, + storeFactory = DefaultStoreFactory(), + ) + + ComposeViewport(document.body!!) { + SolrTheme(useDarkTheme = isSystemInDarkTheme()) { + Surface(modifier = Modifier.fillMaxSize()) { + RootContent(component) + } + } + } +} diff --git a/solr/compose-ui/src/wasmJsMain/resources/index.html b/solr/compose-ui/src/wasmJsMain/resources/index.html new file mode 100644 index 00000000000..efae91da354 --- /dev/null +++ b/solr/compose-ui/src/wasmJsMain/resources/index.html @@ -0,0 +1,12 @@ + + + + + + Solr Admin UI + + + + + + diff --git a/solr/compose-ui/src/wasmJsMain/resources/styles.css b/solr/compose-ui/src/wasmJsMain/resources/styles.css new file mode 100644 index 00000000000..0549b10f86d --- /dev/null +++ b/solr/compose-ui/src/wasmJsMain/resources/styles.css @@ -0,0 +1,7 @@ +html, body { + width: 100%; + height: 100%; + margin: 0; + padding: 0; + overflow: hidden; +} \ No newline at end of file diff --git a/solr/core/src/java/org/apache/solr/servlet/LoadAdminUiServlet.java b/solr/core/src/java/org/apache/solr/servlet/LoadAdminUiServlet.java index 9da4bc84775..eca9126a921 100644 --- a/solr/core/src/java/org/apache/solr/servlet/LoadAdminUiServlet.java +++ b/solr/core/src/java/org/apache/solr/servlet/LoadAdminUiServlet.java @@ -71,7 +71,7 @@ public void doGet(HttpServletRequest _request, HttpServletResponse _response) th HttpHeaders.CONTENT_SECURITY_POLICY, "default-src 'none'; base-uri 'none'; connect-src " + connectSrc - + "; form-action 'self'; font-src 'self'; frame-ancestors 'none'; img-src 'self' data:; media-src 'self'; style-src 'self' 'unsafe-inline'; script-src 'self'; worker-src 'self';"); + + "; form-action 'self'; font-src 'self'; frame-ancestors 'none'; img-src 'self' data:; media-src 'self'; style-src 'self' 'unsafe-inline'; script-src 'self' 'wasm-unsafe-eval'; worker-src 'self';"); // We have to close this to flush OutputStreamWriter buffer try (Writer out = diff --git a/solr/server/etc/jetty.xml b/solr/server/etc/jetty.xml index ee3d3f0246f..47c8aab4327 100644 --- a/solr/server/etc/jetty.xml +++ b/solr/server/etc/jetty.xml @@ -96,7 +96,7 @@ /solr/* Content-Security-Policy - default-src 'none'; base-uri 'none'; connect-src 'self'; form-action 'self'; font-src 'self'; frame-ancestors 'none'; img-src 'self' data:; media-src 'self'; style-src 'self' 'unsafe-inline'; script-src 'self'; worker-src 'self'; + default-src 'none'; base-uri 'none'; connect-src 'self'; form-action 'self'; font-src 'self'; frame-ancestors 'none'; img-src 'self' data:; media-src 'self'; style-src 'self' 'unsafe-inline'; script-src 'self' 'wasm-unsafe-eval'; worker-src 'self'; diff --git a/solr/webapp/build.gradle b/solr/webapp/build.gradle index f2b830f544f..964981e6164 100644 --- a/solr/webapp/build.gradle +++ b/solr/webapp/build.gradle @@ -95,6 +95,13 @@ task downloadBrowserify(type: NpmTask) { outputs.dir("${nodeProjectDir}/node_modules/browserify") } +task generateComposeUiFiles { + // Generate and add files of new UI to outputs for later referencing + dependsOn project(":solr:compose-ui").tasks.wasmJsBrowserDistribution + + outputs.dir(project(':solr:compose-ui').file('build/dist/wasmJs/productionExecutable/')) +} + task generateJsClientBundle(type: NpxTask) { group = 'Solr JS Client' dependsOn tasks.downloadBrowserify @@ -137,6 +144,11 @@ war { from (configurations.generatedJSClientBundle, { into "libs/solr" }) + + // Include new UI files in webapp + from (tasks.generateComposeUiFiles, { + into "compose" + }) } // Expose 'war' archive as an artifact so that it can be packaged in the distribution. diff --git a/solr/webapp/web/js/angular/app.js b/solr/webapp/web/js/angular/app.js index 0cb3bf529b9..57814595145 100644 --- a/solr/webapp/web/js/angular/app.js +++ b/solr/webapp/web/js/angular/app.js @@ -67,6 +67,9 @@ solrAdminApp.config([ templateUrl: 'partials/index.html', controller: 'IndexController' }). + when('/compose', { + redirectTo: 'compose/index.html' + }). when('/unknown', { templateUrl: 'partials/unknown.html', controller: 'UnknownController' From 3cb969dfcefe931d2d9670fd8fc945cfae0cb123 Mon Sep 17 00:00:00 2001 From: Christos Malliaridis Date: Thu, 4 Jul 2024 19:50:20 +0200 Subject: [PATCH 03/66] Add Solr initial theme colors --- .../solr/composeui/ui/theme/ColorFamily.kt | 29 ++ .../apache/solr/composeui/ui/theme/Colors.kt | 320 +++++++++++++- .../apache/solr/composeui/ui/theme/Theme.kt | 411 +++++++++++++++++- 3 files changed, 750 insertions(+), 10 deletions(-) create mode 100644 solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/ui/theme/ColorFamily.kt diff --git a/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/ui/theme/ColorFamily.kt b/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/ui/theme/ColorFamily.kt new file mode 100644 index 00000000000..1d67d153a29 --- /dev/null +++ b/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/ui/theme/ColorFamily.kt @@ -0,0 +1,29 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.solr.composeui.ui.theme + +import androidx.compose.runtime.Immutable +import androidx.compose.ui.graphics.Color + +@Immutable +data class ColorFamily( + val color: Color, + val onColor: Color, + val colorContainer: Color, + val onColorContainer: Color, +) diff --git a/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/ui/theme/Colors.kt b/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/ui/theme/Colors.kt index 14c4a8e83fe..13cf1cc8931 100644 --- a/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/ui/theme/Colors.kt +++ b/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/ui/theme/Colors.kt @@ -17,4 +17,322 @@ package org.apache.solr.composeui.ui.theme -// TODO Add Solr base colors here +import androidx.compose.ui.graphics.Color + +val primaryLight = Color(0xFF9C1F00) +val onPrimaryLight = Color(0xFFFFFFFF) +val primaryContainerLight = Color(0xFFD53E1B) +val onPrimaryContainerLight = Color(0xFFFFFFFF) +val secondaryLight = Color(0xFF9B442F) +val onSecondaryLight = Color(0xFFFFFFFF) +val secondaryContainerLight = Color(0xFFFF9E87) +val onSecondaryContainerLight = Color(0xFF561103) +val tertiaryLight = Color(0xFF674C00) +val onTertiaryLight = Color(0xFFFFFFFF) +val tertiaryContainerLight = Color(0xFF946F00) +val onTertiaryContainerLight = Color(0xFFFFFFFF) +val errorLight = Color(0xFFBA1A1A) +val onErrorLight = Color(0xFFFFFFFF) +val errorContainerLight = Color(0xFFFFDAD6) +val onErrorContainerLight = Color(0xFF410002) +val backgroundLight = Color(0xFFFFF8F6) +val onBackgroundLight = Color(0xFF271814) +val surfaceLight = Color(0xFFFCF8F8) +val onSurfaceLight = Color(0xFF1C1B1B) +val surfaceVariantLight = Color(0xFFE0E3E3) +val onSurfaceVariantLight = Color(0xFF444748) +val outlineLight = Color(0xFF747878) +val outlineVariantLight = Color(0xFFC4C7C7) +val scrimLight = Color(0xFF000000) +val inverseSurfaceLight = Color(0xFF313030) +val inverseOnSurfaceLight = Color(0xFFF4F0EF) +val inversePrimaryLight = Color(0xFFFFB4A3) +val surfaceDimLight = Color(0xFFDDD9D9) +val surfaceBrightLight = Color(0xFFFCF8F8) +val surfaceContainerLowestLight = Color(0xFFFFFFFF) +val surfaceContainerLowLight = Color(0xFFF7F3F2) +val surfaceContainerLight = Color(0xFFF1EDEC) +val surfaceContainerHighLight = Color(0xFFEBE7E7) +val surfaceContainerHighestLight = Color(0xFFE5E2E1) + +val primaryLightMediumContrast = Color(0xFF841800) +val onPrimaryLightMediumContrast = Color(0xFFFFFFFF) +val primaryContainerLightMediumContrast = Color(0xFFD53E1B) +val onPrimaryContainerLightMediumContrast = Color(0xFFFFFFFF) +val secondaryLightMediumContrast = Color(0xFF772917) +val onSecondaryLightMediumContrast = Color(0xFFFFFFFF) +val secondaryContainerLightMediumContrast = Color(0xFFB75943) +val onSecondaryContainerLightMediumContrast = Color(0xFFFFFFFF) +val tertiaryLightMediumContrast = Color(0xFF563F00) +val onTertiaryLightMediumContrast = Color(0xFFFFFFFF) +val tertiaryContainerLightMediumContrast = Color(0xFF946F00) +val onTertiaryContainerLightMediumContrast = Color(0xFFFFFFFF) +val errorLightMediumContrast = Color(0xFF8C0009) +val onErrorLightMediumContrast = Color(0xFFFFFFFF) +val errorContainerLightMediumContrast = Color(0xFFDA342E) +val onErrorContainerLightMediumContrast = Color(0xFFFFFFFF) +val backgroundLightMediumContrast = Color(0xFFFFF8F6) +val onBackgroundLightMediumContrast = Color(0xFF271814) +val surfaceLightMediumContrast = Color(0xFFFCF8F8) +val onSurfaceLightMediumContrast = Color(0xFF1C1B1B) +val surfaceVariantLightMediumContrast = Color(0xFFE0E3E3) +val onSurfaceVariantLightMediumContrast = Color(0xFF404344) +val outlineLightMediumContrast = Color(0xFF5C6060) +val outlineVariantLightMediumContrast = Color(0xFF787B7C) +val scrimLightMediumContrast = Color(0xFF000000) +val inverseSurfaceLightMediumContrast = Color(0xFF313030) +val inverseOnSurfaceLightMediumContrast = Color(0xFFF4F0EF) +val inversePrimaryLightMediumContrast = Color(0xFFFFB4A3) +val surfaceDimLightMediumContrast = Color(0xFFDDD9D9) +val surfaceBrightLightMediumContrast = Color(0xFFFCF8F8) +val surfaceContainerLowestLightMediumContrast = Color(0xFFFFFFFF) +val surfaceContainerLowLightMediumContrast = Color(0xFFF7F3F2) +val surfaceContainerLightMediumContrast = Color(0xFFF1EDEC) +val surfaceContainerHighLightMediumContrast = Color(0xFFEBE7E7) +val surfaceContainerHighestLightMediumContrast = Color(0xFFE5E2E1) + +val primaryLightHighContrast = Color(0xFF490900) +val onPrimaryLightHighContrast = Color(0xFFFFFFFF) +val primaryContainerLightHighContrast = Color(0xFF841800) +val onPrimaryContainerLightHighContrast = Color(0xFFFFFFFF) +val secondaryLightHighContrast = Color(0xFF490900) +val onSecondaryLightHighContrast = Color(0xFFFFFFFF) +val secondaryContainerLightHighContrast = Color(0xFF772917) +val onSecondaryContainerLightHighContrast = Color(0xFFFFFFFF) +val tertiaryLightHighContrast = Color(0xFF2E2000) +val onTertiaryLightHighContrast = Color(0xFFFFFFFF) +val tertiaryContainerLightHighContrast = Color(0xFF563F00) +val onTertiaryContainerLightHighContrast = Color(0xFFFFFFFF) +val errorLightHighContrast = Color(0xFF4E0002) +val onErrorLightHighContrast = Color(0xFFFFFFFF) +val errorContainerLightHighContrast = Color(0xFF8C0009) +val onErrorContainerLightHighContrast = Color(0xFFFFFFFF) +val backgroundLightHighContrast = Color(0xFFFFF8F6) +val onBackgroundLightHighContrast = Color(0xFF271814) +val surfaceLightHighContrast = Color(0xFFFCF8F8) +val onSurfaceLightHighContrast = Color(0xFF000000) +val surfaceVariantLightHighContrast = Color(0xFFE0E3E3) +val onSurfaceVariantLightHighContrast = Color(0xFF212525) +val outlineLightHighContrast = Color(0xFF404344) +val outlineVariantLightHighContrast = Color(0xFF404344) +val scrimLightHighContrast = Color(0xFF000000) +val inverseSurfaceLightHighContrast = Color(0xFF313030) +val inverseOnSurfaceLightHighContrast = Color(0xFFFFFFFF) +val inversePrimaryLightHighContrast = Color(0xFFFFE7E2) +val surfaceDimLightHighContrast = Color(0xFFDDD9D9) +val surfaceBrightLightHighContrast = Color(0xFFFCF8F8) +val surfaceContainerLowestLightHighContrast = Color(0xFFFFFFFF) +val surfaceContainerLowLightHighContrast = Color(0xFFF7F3F2) +val surfaceContainerLightHighContrast = Color(0xFFF1EDEC) +val surfaceContainerHighLightHighContrast = Color(0xFFEBE7E7) +val surfaceContainerHighestLightHighContrast = Color(0xFFE5E2E1) + +val primaryDark = Color(0xFFFFB4A3) +val onPrimaryDark = Color(0xFF631000) +val primaryContainerDark = Color(0xFFCD3916) +val onPrimaryContainerDark = Color(0xFFFFFFFF) +val secondaryDark = Color(0xFFFFB4A3) +val onSecondaryDark = Color(0xFF5E1707) +val secondaryContainerDark = Color(0xFF732615) +val onSecondaryContainerDark = Color(0xFFFFC9BD) +val tertiaryDark = Color(0xFFEFC054) +val onTertiaryDark = Color(0xFF3F2E00) +val tertiaryContainerDark = Color(0xFF8D6900) +val onTertiaryContainerDark = Color(0xFFFFFFFF) +val errorDark = Color(0xFFFFB4AB) +val onErrorDark = Color(0xFF690005) +val errorContainerDark = Color(0xFF93000A) +val onErrorContainerDark = Color(0xFFFFDAD6) +val backgroundDark = Color(0xFF1E100D) +val onBackgroundDark = Color(0xFFF9DCD6) +val surfaceDark = Color(0xFF141313) +val onSurfaceDark = Color(0xFFE5E2E1) +val surfaceVariantDark = Color(0xFF444748) +val onSurfaceVariantDark = Color(0xFFC4C7C7) +val outlineDark = Color(0xFF8E9192) +val outlineVariantDark = Color(0xFF444748) +val scrimDark = Color(0xFF000000) +val inverseSurfaceDark = Color(0xFFE5E2E1) +val inverseOnSurfaceDark = Color(0xFF313030) +val inversePrimaryDark = Color(0xFFB52703) +val surfaceDimDark = Color(0xFF141313) +val surfaceBrightDark = Color(0xFF3A3939) +val surfaceContainerLowestDark = Color(0xFF0E0E0E) +val surfaceContainerLowDark = Color(0xFF1C1B1B) +val surfaceContainerDark = Color(0xFF201F1F) +val surfaceContainerHighDark = Color(0xFF2A2A2A) +val surfaceContainerHighestDark = Color(0xFF353434) + +val primaryDarkMediumContrast = Color(0xFFFFBAAA) +val onPrimaryDarkMediumContrast = Color(0xFF330500) +val primaryContainerDarkMediumContrast = Color(0xFFFC5934) +val onPrimaryContainerDarkMediumContrast = Color(0xFF000000) +val secondaryDarkMediumContrast = Color(0xFFFFBAAA) +val onSecondaryDarkMediumContrast = Color(0xFF330500) +val secondaryContainerDarkMediumContrast = Color(0xFFDA745C) +val onSecondaryContainerDarkMediumContrast = Color(0xFF000000) +val tertiaryDarkMediumContrast = Color(0xFFF3C458) +val onTertiaryDarkMediumContrast = Color(0xFF1F1500) +val tertiaryContainerDarkMediumContrast = Color(0xFFB48B22) +val onTertiaryContainerDarkMediumContrast = Color(0xFF000000) +val errorDarkMediumContrast = Color(0xFFFFBAB1) +val onErrorDarkMediumContrast = Color(0xFF370001) +val errorContainerDarkMediumContrast = Color(0xFFFF5449) +val onErrorContainerDarkMediumContrast = Color(0xFF000000) +val backgroundDarkMediumContrast = Color(0xFF1E100D) +val onBackgroundDarkMediumContrast = Color(0xFFF9DCD6) +val surfaceDarkMediumContrast = Color(0xFF141313) +val onSurfaceDarkMediumContrast = Color(0xFFFEFAF9) +val surfaceVariantDarkMediumContrast = Color(0xFF444748) +val onSurfaceVariantDarkMediumContrast = Color(0xFFC8CBCC) +val outlineDarkMediumContrast = Color(0xFFA0A3A4) +val outlineVariantDarkMediumContrast = Color(0xFF808484) +val scrimDarkMediumContrast = Color(0xFF000000) +val inverseSurfaceDarkMediumContrast = Color(0xFFE5E2E1) +val inverseOnSurfaceDarkMediumContrast = Color(0xFF2A2A2A) +val inversePrimaryDarkMediumContrast = Color(0xFF8D1B00) +val surfaceDimDarkMediumContrast = Color(0xFF141313) +val surfaceBrightDarkMediumContrast = Color(0xFF3A3939) +val surfaceContainerLowestDarkMediumContrast = Color(0xFF0E0E0E) +val surfaceContainerLowDarkMediumContrast = Color(0xFF1C1B1B) +val surfaceContainerDarkMediumContrast = Color(0xFF201F1F) +val surfaceContainerHighDarkMediumContrast = Color(0xFF2A2A2A) +val surfaceContainerHighestDarkMediumContrast = Color(0xFF353434) + +val primaryDarkHighContrast = Color(0xFFFFF9F8) +val onPrimaryDarkHighContrast = Color(0xFF000000) +val primaryContainerDarkHighContrast = Color(0xFFFFBAAA) +val onPrimaryContainerDarkHighContrast = Color(0xFF000000) +val secondaryDarkHighContrast = Color(0xFFFFF9F8) +val onSecondaryDarkHighContrast = Color(0xFF000000) +val secondaryContainerDarkHighContrast = Color(0xFFFFBAAA) +val onSecondaryContainerDarkHighContrast = Color(0xFF000000) +val tertiaryDarkHighContrast = Color(0xFFFFFAF7) +val onTertiaryDarkHighContrast = Color(0xFF000000) +val tertiaryContainerDarkHighContrast = Color(0xFFF3C458) +val onTertiaryContainerDarkHighContrast = Color(0xFF000000) +val errorDarkHighContrast = Color(0xFFFFF9F9) +val onErrorDarkHighContrast = Color(0xFF000000) +val errorContainerDarkHighContrast = Color(0xFFFFBAB1) +val onErrorContainerDarkHighContrast = Color(0xFF000000) +val backgroundDarkHighContrast = Color(0xFF1E100D) +val onBackgroundDarkHighContrast = Color(0xFFF9DCD6) +val surfaceDarkHighContrast = Color(0xFF141313) +val onSurfaceDarkHighContrast = Color(0xFFFFFFFF) +val surfaceVariantDarkHighContrast = Color(0xFF444748) +val onSurfaceVariantDarkHighContrast = Color(0xFFF9FBFC) +val outlineDarkHighContrast = Color(0xFFC8CBCC) +val outlineVariantDarkHighContrast = Color(0xFFC8CBCC) +val scrimDarkHighContrast = Color(0xFF000000) +val inverseSurfaceDarkHighContrast = Color(0xFFE5E2E1) +val inverseOnSurfaceDarkHighContrast = Color(0xFF000000) +val inversePrimaryDarkHighContrast = Color(0xFF570D00) +val surfaceDimDarkHighContrast = Color(0xFF141313) +val surfaceBrightDarkHighContrast = Color(0xFF3A3939) +val surfaceContainerLowestDarkHighContrast = Color(0xFF0E0E0E) +val surfaceContainerLowDarkHighContrast = Color(0xFF1C1B1B) +val surfaceContainerDarkHighContrast = Color(0xFF201F1F) +val surfaceContainerHighDarkHighContrast = Color(0xFF2A2A2A) +val surfaceContainerHighestDarkHighContrast = Color(0xFF353434) + +val warningLight = Color(0xFF745B00) +val onWarningLight = Color(0xFFFFFFFF) +val warningContainerLight = Color(0xFFFFD450) +val onWarningContainerLight = Color(0xFF524000) +val healthyLight = Color(0xFF176D23) +val onHealthyLight = Color(0xFFFFFFFF) +val healthyContainerLight = Color(0xFF64B663) +val onHealthyContainerLight = Color(0xFF001F03) +val replicaLight = Color(0xFF005474) +val onReplicaLight = Color(0xFFFFFFFF) +val replicaContainerLight = Color(0xFF007BA7) +val onReplicaContainerLight = Color(0xFFFFFFFF) +val recoveryLight = Color(0xFF5F6300) +val onRecoveryLight = Color(0xFFFFFFFF) +val recoveryContainerLight = Color(0xFFDBE311) +val onRecoveryContainerLight = Color(0xFF434600) + +val warningLightMediumContrast = Color(0xFF534100) +val onWarningLightMediumContrast = Color(0xFFFFFFFF) +val warningContainerLightMediumContrast = Color(0xFF8F7100) +val onWarningContainerLightMediumContrast = Color(0xFFFFFFFF) +val healthyLightMediumContrast = Color(0xFF004F12) +val onHealthyLightMediumContrast = Color(0xFFFFFFFF) +val healthyContainerLightMediumContrast = Color(0xFF338437) +val onHealthyContainerLightMediumContrast = Color(0xFFFFFFFF) +val replicaLightMediumContrast = Color(0xFF004864) +val onReplicaLightMediumContrast = Color(0xFFFFFFFF) +val replicaContainerLightMediumContrast = Color(0xFF007BA7) +val onReplicaContainerLightMediumContrast = Color(0xFFFFFFFF) +val recoveryLightMediumContrast = Color(0xFF434600) +val onRecoveryLightMediumContrast = Color(0xFFFFFFFF) +val recoveryContainerLightMediumContrast = Color(0xFF757A00) +val onRecoveryContainerLightMediumContrast = Color(0xFFFFFFFF) + +val warningLightHighContrast = Color(0xFF2C2100) +val onWarningLightHighContrast = Color(0xFFFFFFFF) +val warningContainerLightHighContrast = Color(0xFF534100) +val onWarningContainerLightHighContrast = Color(0xFFFFFFFF) +val healthyLightHighContrast = Color(0xFF002906) +val onHealthyLightHighContrast = Color(0xFFFFFFFF) +val healthyContainerLightHighContrast = Color(0xFF004F12) +val onHealthyContainerLightHighContrast = Color(0xFFFFFFFF) +val replicaLightHighContrast = Color(0xFF002536) +val onReplicaLightHighContrast = Color(0xFFFFFFFF) +val replicaContainerLightHighContrast = Color(0xFF004864) +val onReplicaContainerLightHighContrast = Color(0xFFFFFFFF) +val recoveryLightHighContrast = Color(0xFF222400) +val onRecoveryLightHighContrast = Color(0xFFFFFFFF) +val recoveryContainerLightHighContrast = Color(0xFF434600) +val onRecoveryContainerLightHighContrast = Color(0xFFFFFFFF) + +val warningDark = Color(0xFFFFF8EF) +val onWarningDark = Color(0xFF3D2F00) +val warningContainerDark = Color(0xFFFAC800) +val onWarningContainerDark = Color(0xFF4A3900) +val healthyDark = Color(0xFF85DA82) +val onHealthyDark = Color(0xFF00390A) +val healthyContainerDark = Color(0xFF338437) +val onHealthyContainerDark = Color(0xFFFFFFFF) +val replicaDark = Color(0xFF7CD0FF) +val onReplicaDark = Color(0xFF00344A) +val replicaContainerDark = Color(0xFF007199) +val onReplicaContainerDark = Color(0xFFFFFFFF) +val recoveryDark = Color(0xFFFDFFB7) +val onRecoveryDark = Color(0xFF313300) +val recoveryContainerDark = Color(0xFFD1D800) +val onRecoveryContainerDark = Color(0xFF3D3F00) + +val warningDarkMediumContrast = Color(0xFFFFF8EF) +val onWarningDarkMediumContrast = Color(0xFF3D2F00) +val warningContainerDarkMediumContrast = Color(0xFFFAC800) +val onWarningContainerDarkMediumContrast = Color(0xFF221900) +val healthyDarkMediumContrast = Color(0xFF8ADE85) +val onHealthyDarkMediumContrast = Color(0xFF001B03) +val healthyContainerDarkMediumContrast = Color(0xFF50A251) +val onHealthyContainerDarkMediumContrast = Color(0xFF000000) +val replicaDarkMediumContrast = Color(0xFF89D4FF) +val onReplicaDarkMediumContrast = Color(0xFF001925) +val replicaContainerDarkMediumContrast = Color(0xFF3C9AC7) +val onReplicaContainerDarkMediumContrast = Color(0xFF000000) +val recoveryDarkMediumContrast = Color(0xFFFDFFB7) +val onRecoveryDarkMediumContrast = Color(0xFF313300) +val recoveryContainerDarkMediumContrast = Color(0xFFD1D800) +val onRecoveryContainerDarkMediumContrast = Color(0xFF1B1D00) + +val warningDarkHighContrast = Color(0xFFFFFAF6) +val onWarningDarkHighContrast = Color(0xFF000000) +val warningContainerDarkHighContrast = Color(0xFFFAC800) +val onWarningContainerDarkHighContrast = Color(0xFF000000) +val healthyDarkHighContrast = Color(0xFFF1FFEA) +val onHealthyDarkHighContrast = Color(0xFF000000) +val healthyContainerDarkHighContrast = Color(0xFF8ADE85) +val onHealthyContainerDarkHighContrast = Color(0xFF000000) +val replicaDarkHighContrast = Color(0xFFF8FBFF) +val onReplicaDarkHighContrast = Color(0xFF000000) +val replicaContainerDarkHighContrast = Color(0xFF89D4FF) +val onReplicaContainerDarkHighContrast = Color(0xFF000000) +val recoveryDarkHighContrast = Color(0xFFFDFFBC) +val onRecoveryDarkHighContrast = Color(0xFF000000) +val recoveryContainerDarkHighContrast = Color(0xFFD1D800) +val onRecoveryContainerDarkHighContrast = Color(0xFF000000) diff --git a/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/ui/theme/Theme.kt b/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/ui/theme/Theme.kt index d16f8ee73cd..a4c1c52f594 100644 --- a/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/ui/theme/Theme.kt +++ b/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/ui/theme/Theme.kt @@ -22,13 +22,404 @@ import androidx.compose.material3.MaterialTheme import androidx.compose.material3.darkColorScheme import androidx.compose.material3.lightColorScheme import androidx.compose.runtime.Composable +import androidx.compose.runtime.Immutable -private val LightColors = lightColorScheme( - // TODO Override light theme colors here +@Immutable +data class ExtendedColorScheme( + val warning: ColorFamily, + val healthy: ColorFamily, + val replica: ColorFamily, + val recovery: ColorFamily, ) -private val DarkColors = darkColorScheme( - // TODO Override dark theme colors here +private val lightScheme = lightColorScheme( + primary = primaryLight, + onPrimary = onPrimaryLight, + primaryContainer = primaryContainerLight, + onPrimaryContainer = onPrimaryContainerLight, + secondary = secondaryLight, + onSecondary = onSecondaryLight, + secondaryContainer = secondaryContainerLight, + onSecondaryContainer = onSecondaryContainerLight, + tertiary = tertiaryLight, + onTertiary = onTertiaryLight, + tertiaryContainer = tertiaryContainerLight, + onTertiaryContainer = onTertiaryContainerLight, + error = errorLight, + onError = onErrorLight, + errorContainer = errorContainerLight, + onErrorContainer = onErrorContainerLight, + background = backgroundLight, + onBackground = onBackgroundLight, + surface = surfaceLight, + onSurface = onSurfaceLight, + surfaceVariant = surfaceVariantLight, + onSurfaceVariant = onSurfaceVariantLight, + outline = outlineLight, + outlineVariant = outlineVariantLight, + scrim = scrimLight, + inverseSurface = inverseSurfaceLight, + inverseOnSurface = inverseOnSurfaceLight, + inversePrimary = inversePrimaryLight, + surfaceDim = surfaceDimLight, + surfaceBright = surfaceBrightLight, + surfaceContainerLowest = surfaceContainerLowestLight, + surfaceContainerLow = surfaceContainerLowLight, + surfaceContainer = surfaceContainerLight, + surfaceContainerHigh = surfaceContainerHighLight, + surfaceContainerHighest = surfaceContainerHighestLight, +) + +private val darkScheme = darkColorScheme( + primary = primaryDark, + onPrimary = onPrimaryDark, + primaryContainer = primaryContainerDark, + onPrimaryContainer = onPrimaryContainerDark, + secondary = secondaryDark, + onSecondary = onSecondaryDark, + secondaryContainer = secondaryContainerDark, + onSecondaryContainer = onSecondaryContainerDark, + tertiary = tertiaryDark, + onTertiary = onTertiaryDark, + tertiaryContainer = tertiaryContainerDark, + onTertiaryContainer = onTertiaryContainerDark, + error = errorDark, + onError = onErrorDark, + errorContainer = errorContainerDark, + onErrorContainer = onErrorContainerDark, + background = backgroundDark, + onBackground = onBackgroundDark, + surface = surfaceDark, + onSurface = onSurfaceDark, + surfaceVariant = surfaceVariantDark, + onSurfaceVariant = onSurfaceVariantDark, + outline = outlineDark, + outlineVariant = outlineVariantDark, + scrim = scrimDark, + inverseSurface = inverseSurfaceDark, + inverseOnSurface = inverseOnSurfaceDark, + inversePrimary = inversePrimaryDark, + surfaceDim = surfaceDimDark, + surfaceBright = surfaceBrightDark, + surfaceContainerLowest = surfaceContainerLowestDark, + surfaceContainerLow = surfaceContainerLowDark, + surfaceContainer = surfaceContainerDark, + surfaceContainerHigh = surfaceContainerHighDark, + surfaceContainerHighest = surfaceContainerHighestDark, +) + +private val mediumContrastLightColorScheme = lightColorScheme( + primary = primaryLightMediumContrast, + onPrimary = onPrimaryLightMediumContrast, + primaryContainer = primaryContainerLightMediumContrast, + onPrimaryContainer = onPrimaryContainerLightMediumContrast, + secondary = secondaryLightMediumContrast, + onSecondary = onSecondaryLightMediumContrast, + secondaryContainer = secondaryContainerLightMediumContrast, + onSecondaryContainer = onSecondaryContainerLightMediumContrast, + tertiary = tertiaryLightMediumContrast, + onTertiary = onTertiaryLightMediumContrast, + tertiaryContainer = tertiaryContainerLightMediumContrast, + onTertiaryContainer = onTertiaryContainerLightMediumContrast, + error = errorLightMediumContrast, + onError = onErrorLightMediumContrast, + errorContainer = errorContainerLightMediumContrast, + onErrorContainer = onErrorContainerLightMediumContrast, + background = backgroundLightMediumContrast, + onBackground = onBackgroundLightMediumContrast, + surface = surfaceLightMediumContrast, + onSurface = onSurfaceLightMediumContrast, + surfaceVariant = surfaceVariantLightMediumContrast, + onSurfaceVariant = onSurfaceVariantLightMediumContrast, + outline = outlineLightMediumContrast, + outlineVariant = outlineVariantLightMediumContrast, + scrim = scrimLightMediumContrast, + inverseSurface = inverseSurfaceLightMediumContrast, + inverseOnSurface = inverseOnSurfaceLightMediumContrast, + inversePrimary = inversePrimaryLightMediumContrast, + surfaceDim = surfaceDimLightMediumContrast, + surfaceBright = surfaceBrightLightMediumContrast, + surfaceContainerLowest = surfaceContainerLowestLightMediumContrast, + surfaceContainerLow = surfaceContainerLowLightMediumContrast, + surfaceContainer = surfaceContainerLightMediumContrast, + surfaceContainerHigh = surfaceContainerHighLightMediumContrast, + surfaceContainerHighest = surfaceContainerHighestLightMediumContrast, +) + +private val highContrastLightColorScheme = lightColorScheme( + primary = primaryLightHighContrast, + onPrimary = onPrimaryLightHighContrast, + primaryContainer = primaryContainerLightHighContrast, + onPrimaryContainer = onPrimaryContainerLightHighContrast, + secondary = secondaryLightHighContrast, + onSecondary = onSecondaryLightHighContrast, + secondaryContainer = secondaryContainerLightHighContrast, + onSecondaryContainer = onSecondaryContainerLightHighContrast, + tertiary = tertiaryLightHighContrast, + onTertiary = onTertiaryLightHighContrast, + tertiaryContainer = tertiaryContainerLightHighContrast, + onTertiaryContainer = onTertiaryContainerLightHighContrast, + error = errorLightHighContrast, + onError = onErrorLightHighContrast, + errorContainer = errorContainerLightHighContrast, + onErrorContainer = onErrorContainerLightHighContrast, + background = backgroundLightHighContrast, + onBackground = onBackgroundLightHighContrast, + surface = surfaceLightHighContrast, + onSurface = onSurfaceLightHighContrast, + surfaceVariant = surfaceVariantLightHighContrast, + onSurfaceVariant = onSurfaceVariantLightHighContrast, + outline = outlineLightHighContrast, + outlineVariant = outlineVariantLightHighContrast, + scrim = scrimLightHighContrast, + inverseSurface = inverseSurfaceLightHighContrast, + inverseOnSurface = inverseOnSurfaceLightHighContrast, + inversePrimary = inversePrimaryLightHighContrast, + surfaceDim = surfaceDimLightHighContrast, + surfaceBright = surfaceBrightLightHighContrast, + surfaceContainerLowest = surfaceContainerLowestLightHighContrast, + surfaceContainerLow = surfaceContainerLowLightHighContrast, + surfaceContainer = surfaceContainerLightHighContrast, + surfaceContainerHigh = surfaceContainerHighLightHighContrast, + surfaceContainerHighest = surfaceContainerHighestLightHighContrast, +) + +private val mediumContrastDarkColorScheme = darkColorScheme( + primary = primaryDarkMediumContrast, + onPrimary = onPrimaryDarkMediumContrast, + primaryContainer = primaryContainerDarkMediumContrast, + onPrimaryContainer = onPrimaryContainerDarkMediumContrast, + secondary = secondaryDarkMediumContrast, + onSecondary = onSecondaryDarkMediumContrast, + secondaryContainer = secondaryContainerDarkMediumContrast, + onSecondaryContainer = onSecondaryContainerDarkMediumContrast, + tertiary = tertiaryDarkMediumContrast, + onTertiary = onTertiaryDarkMediumContrast, + tertiaryContainer = tertiaryContainerDarkMediumContrast, + onTertiaryContainer = onTertiaryContainerDarkMediumContrast, + error = errorDarkMediumContrast, + onError = onErrorDarkMediumContrast, + errorContainer = errorContainerDarkMediumContrast, + onErrorContainer = onErrorContainerDarkMediumContrast, + background = backgroundDarkMediumContrast, + onBackground = onBackgroundDarkMediumContrast, + surface = surfaceDarkMediumContrast, + onSurface = onSurfaceDarkMediumContrast, + surfaceVariant = surfaceVariantDarkMediumContrast, + onSurfaceVariant = onSurfaceVariantDarkMediumContrast, + outline = outlineDarkMediumContrast, + outlineVariant = outlineVariantDarkMediumContrast, + scrim = scrimDarkMediumContrast, + inverseSurface = inverseSurfaceDarkMediumContrast, + inverseOnSurface = inverseOnSurfaceDarkMediumContrast, + inversePrimary = inversePrimaryDarkMediumContrast, + surfaceDim = surfaceDimDarkMediumContrast, + surfaceBright = surfaceBrightDarkMediumContrast, + surfaceContainerLowest = surfaceContainerLowestDarkMediumContrast, + surfaceContainerLow = surfaceContainerLowDarkMediumContrast, + surfaceContainer = surfaceContainerDarkMediumContrast, + surfaceContainerHigh = surfaceContainerHighDarkMediumContrast, + surfaceContainerHighest = surfaceContainerHighestDarkMediumContrast, +) + +private val highContrastDarkColorScheme = darkColorScheme( + primary = primaryDarkHighContrast, + onPrimary = onPrimaryDarkHighContrast, + primaryContainer = primaryContainerDarkHighContrast, + onPrimaryContainer = onPrimaryContainerDarkHighContrast, + secondary = secondaryDarkHighContrast, + onSecondary = onSecondaryDarkHighContrast, + secondaryContainer = secondaryContainerDarkHighContrast, + onSecondaryContainer = onSecondaryContainerDarkHighContrast, + tertiary = tertiaryDarkHighContrast, + onTertiary = onTertiaryDarkHighContrast, + tertiaryContainer = tertiaryContainerDarkHighContrast, + onTertiaryContainer = onTertiaryContainerDarkHighContrast, + error = errorDarkHighContrast, + onError = onErrorDarkHighContrast, + errorContainer = errorContainerDarkHighContrast, + onErrorContainer = onErrorContainerDarkHighContrast, + background = backgroundDarkHighContrast, + onBackground = onBackgroundDarkHighContrast, + surface = surfaceDarkHighContrast, + onSurface = onSurfaceDarkHighContrast, + surfaceVariant = surfaceVariantDarkHighContrast, + onSurfaceVariant = onSurfaceVariantDarkHighContrast, + outline = outlineDarkHighContrast, + outlineVariant = outlineVariantDarkHighContrast, + scrim = scrimDarkHighContrast, + inverseSurface = inverseSurfaceDarkHighContrast, + inverseOnSurface = inverseOnSurfaceDarkHighContrast, + inversePrimary = inversePrimaryDarkHighContrast, + surfaceDim = surfaceDimDarkHighContrast, + surfaceBright = surfaceBrightDarkHighContrast, + surfaceContainerLowest = surfaceContainerLowestDarkHighContrast, + surfaceContainerLow = surfaceContainerLowDarkHighContrast, + surfaceContainer = surfaceContainerDarkHighContrast, + surfaceContainerHigh = surfaceContainerHighDarkHighContrast, + surfaceContainerHighest = surfaceContainerHighestDarkHighContrast, +) + +val extendedLight = ExtendedColorScheme( + warning = ColorFamily( + color = warningLight, + onColor = onWarningLight, + colorContainer = warningContainerLight, + onColorContainer = onWarningContainerLight, + ), + healthy = ColorFamily( + color = healthyLight, + onColor = onHealthyLight, + colorContainer = healthyContainerLight, + onColorContainer = onHealthyContainerLight, + ), + replica = ColorFamily( + color = replicaLight, + onColor = onReplicaLight, + colorContainer = replicaContainerLight, + onColorContainer = onReplicaContainerLight, + ), + recovery = ColorFamily( + color = recoveryLight, + onColor = onRecoveryLight, + colorContainer = recoveryContainerLight, + onColorContainer = onRecoveryContainerLight, + ), +) + +val extendedDark = ExtendedColorScheme( + warning = ColorFamily( + color = warningDark, + onColor = onWarningDark, + colorContainer = warningContainerDark, + onColorContainer = onWarningContainerDark, + ), + healthy = ColorFamily( + color = healthyDark, + onColor = onHealthyDark, + colorContainer = healthyContainerDark, + onColorContainer = onHealthyContainerDark, + ), + replica = ColorFamily( + color = replicaDark, + onColor = onReplicaDark, + colorContainer = replicaContainerDark, + onColorContainer = onReplicaContainerDark, + ), + recovery = ColorFamily( + color = recoveryDark, + onColor = onRecoveryDark, + colorContainer = recoveryContainerDark, + onColorContainer = onRecoveryContainerDark, + ), +) + +val extendedLightMediumContrast = ExtendedColorScheme( + warning = ColorFamily( + color = warningLightMediumContrast, + onColor = onWarningLightMediumContrast, + colorContainer = warningContainerLightMediumContrast, + onColorContainer = onWarningContainerLightMediumContrast, + ), + healthy = ColorFamily( + color = healthyLightMediumContrast, + onColor = onHealthyLightMediumContrast, + colorContainer = healthyContainerLightMediumContrast, + onColorContainer = onHealthyContainerLightMediumContrast, + ), + replica = ColorFamily( + color = replicaLightMediumContrast, + onColor = onReplicaLightMediumContrast, + colorContainer = replicaContainerLightMediumContrast, + onColorContainer = onReplicaContainerLightMediumContrast, + ), + recovery = ColorFamily( + color = recoveryLightMediumContrast, + onColor = onRecoveryLightMediumContrast, + colorContainer = recoveryContainerLightMediumContrast, + onColorContainer = onRecoveryContainerLightMediumContrast, + ), +) + +val extendedLightHighContrast = ExtendedColorScheme( + warning = ColorFamily( + color = warningLightHighContrast, + onColor = onWarningLightHighContrast, + colorContainer = warningContainerLightHighContrast, + onColorContainer = onWarningContainerLightHighContrast, + ), + healthy = ColorFamily( + color = healthyLightHighContrast, + onColor = onHealthyLightHighContrast, + colorContainer = healthyContainerLightHighContrast, + onColorContainer = onHealthyContainerLightHighContrast, + ), + replica = ColorFamily( + color = replicaLightHighContrast, + onColor = onReplicaLightHighContrast, + colorContainer = replicaContainerLightHighContrast, + onColorContainer = onReplicaContainerLightHighContrast, + ), + recovery = ColorFamily( + color = recoveryLightHighContrast, + onColor = onRecoveryLightHighContrast, + colorContainer = recoveryContainerLightHighContrast, + onColorContainer = onRecoveryContainerLightHighContrast, + ), +) + +val extendedDarkMediumContrast = ExtendedColorScheme( + warning = ColorFamily( + color = warningDarkMediumContrast, + onColor = onWarningDarkMediumContrast, + colorContainer = warningContainerDarkMediumContrast, + onColorContainer = onWarningContainerDarkMediumContrast, + ), + healthy = ColorFamily( + color = healthyDarkMediumContrast, + onColor = onHealthyDarkMediumContrast, + colorContainer = healthyContainerDarkMediumContrast, + onColorContainer = onHealthyContainerDarkMediumContrast, + ), + replica = ColorFamily( + color = replicaDarkMediumContrast, + onColor = onReplicaDarkMediumContrast, + colorContainer = replicaContainerDarkMediumContrast, + onColorContainer = onReplicaContainerDarkMediumContrast, + ), + recovery = ColorFamily( + color = recoveryDarkMediumContrast, + onColor = onRecoveryDarkMediumContrast, + colorContainer = recoveryContainerDarkMediumContrast, + onColorContainer = onRecoveryContainerDarkMediumContrast, + ), +) + +val extendedDarkHighContrast = ExtendedColorScheme( + warning = ColorFamily( + color = warningDarkHighContrast, + onColor = onWarningDarkHighContrast, + colorContainer = warningContainerDarkHighContrast, + onColorContainer = onWarningContainerDarkHighContrast, + ), + healthy = ColorFamily( + color = healthyDarkHighContrast, + onColor = onHealthyDarkHighContrast, + colorContainer = healthyContainerDarkHighContrast, + onColorContainer = onHealthyContainerDarkHighContrast, + ), + replica = ColorFamily( + color = replicaDarkHighContrast, + onColor = onReplicaDarkHighContrast, + colorContainer = replicaContainerDarkHighContrast, + onColorContainer = onReplicaContainerDarkHighContrast, + ), + recovery = ColorFamily( + color = recoveryDarkHighContrast, + onColor = onRecoveryDarkHighContrast, + colorContainer = recoveryContainerDarkHighContrast, + onColorContainer = onRecoveryContainerDarkHighContrast, + ), ) @Composable @@ -36,13 +427,15 @@ fun SolrTheme( useDarkTheme: Boolean = isSystemInDarkTheme(), content: @Composable () -> Unit ) { - val colors = if (useDarkTheme) DarkColors - else LightColors + val colorScheme = when { + useDarkTheme -> darkScheme + else -> lightScheme + } MaterialTheme( - colorScheme = colors, + colorScheme = colorScheme, shapes = SolrShapes, typography = SolrCodeTypography, - content = content + content = content, ) -} \ No newline at end of file +} From 8febc99d62ee5e00f68fc7b9527ecf7bb7d20130 Mon Sep 17 00:00:00 2001 From: Christos Malliaridis Date: Fri, 5 Jul 2024 13:40:25 +0200 Subject: [PATCH 04/66] Add main navigation UI composables (without components) --- .../composeResources/values/strings.xml | 46 ++++ .../components/navigation/MainMenu.kt | 34 +++ .../apache/solr/composeui/ui/icons/Logos.kt | 23 ++ .../solr/composeui/ui/icons/SolrLogo.kt | 252 ++++++++++++++++++ .../composeui/ui/logging/LoggingContent.kt | 28 ++ .../solr/composeui/ui/navigation/Footer.kt | 119 +++++++++ .../ui/navigation/NavigationSideBar.kt | 164 ++++++++++++ .../solr/composeui/ui/root/RootContent.kt | 34 ++- .../composeui/preview/PreviewContainer.kt | 41 +++ .../navigation/PreviewNavigationSideBar.kt | 29 ++ 10 files changed, 768 insertions(+), 2 deletions(-) create mode 100644 solr/compose-ui/src/commonMain/composeResources/values/strings.xml create mode 100644 solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/components/navigation/MainMenu.kt create mode 100644 solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/ui/icons/Logos.kt create mode 100644 solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/ui/icons/SolrLogo.kt create mode 100644 solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/ui/logging/LoggingContent.kt create mode 100644 solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/ui/navigation/Footer.kt create mode 100644 solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/ui/navigation/NavigationSideBar.kt create mode 100644 solr/compose-ui/src/desktopMain/kotlin/org/apache/solr/composeui/preview/PreviewContainer.kt create mode 100644 solr/compose-ui/src/desktopMain/kotlin/org/apache/solr/composeui/preview/navigation/PreviewNavigationSideBar.kt diff --git a/solr/compose-ui/src/commonMain/composeResources/values/strings.xml b/solr/compose-ui/src/commonMain/composeResources/values/strings.xml new file mode 100644 index 00000000000..1f686e87cf9 --- /dev/null +++ b/solr/compose-ui/src/commonMain/composeResources/values/strings.xml @@ -0,0 +1,46 @@ + + + + + + Solr Logo + + + Cluster + Collections + Configsets + Dashboard + Environment + Logging + Metrics + Queries & Operations + Security + Thread Dump + + + Community + Documentation + IRC + Issue Tracker + Logout + Slack + Solr Query Syntax + Support + + + diff --git a/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/components/navigation/MainMenu.kt b/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/components/navigation/MainMenu.kt new file mode 100644 index 00000000000..03cbcbb9a21 --- /dev/null +++ b/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/components/navigation/MainMenu.kt @@ -0,0 +1,34 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.solr.composeui.components.navigation + +/** + * An enum class that holds all the menu items of the main navigation. + */ +enum class MainMenu { + Dashboard, + Metrics, + Cluster, + Security, + Configsets, + Collections, + QueriesAndOperations, + Environment, + Logging, + ThreadDump, +} diff --git a/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/ui/icons/Logos.kt b/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/ui/icons/Logos.kt new file mode 100644 index 00000000000..85575bacb63 --- /dev/null +++ b/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/ui/icons/Logos.kt @@ -0,0 +1,23 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.solr.composeui.ui.icons + +/** + * A wrapper object used by logos for scoped referencing to avoid naming conflicts. + */ +object Logos diff --git a/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/ui/icons/SolrLogo.kt b/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/ui/icons/SolrLogo.kt new file mode 100644 index 00000000000..f23efceab5c --- /dev/null +++ b/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/ui/icons/SolrLogo.kt @@ -0,0 +1,252 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.solr.composeui.ui.icons + +import androidx.compose.foundation.layout.Box +import androidx.compose.material.icons.materialPath +import androidx.compose.material3.Icon +import androidx.compose.material3.MaterialTheme +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.vector.ImageVector +import androidx.compose.ui.graphics.vector.rememberVectorPainter +import androidx.compose.ui.unit.dp +import org.apache.solr.compose_ui.generated.resources.Res +import org.apache.solr.compose_ui.generated.resources.cd_solr_logo +import org.jetbrains.compose.resources.stringResource + +@Composable +fun SolrLogo( + modifier: Modifier = Modifier, +) { + val solrPainter = rememberVectorPainter( + ImageVector.Builder( + name = "Logos.SolrLogo", + defaultWidth = 128.dp, + defaultHeight = 64.dp, + viewportWidth = 128f, + viewportHeight = 64f, + autoMirror = false, + ).apply { + materialPath { + moveTo(25.7013f, 44.178f) + curveTo(24.2211f, 43.4114f, 22.5512f, 42.8706f, 20.7359f, 42.5702f) + curveTo(18.9503f, 42.277f, 17.1375f, 42.1305f, 15.342f, 42.1305f) + curveTo(13.874f, 42.1305f, 12.3913f, 42.0055f, 10.9283f, 41.7628f) + curveTo(9.50715f, 41.5248f, 8.21901f, 41.0899f, 7.09835f, 40.4674f) + curveTo(6.00724f, 39.8618f, 5.10578f, 39.0159f, 4.41615f, 37.9489f) + curveTo(3.73636f, 36.8987f, 3.394f, 35.5072f, 3.394f, 33.8274f) + curveTo(3.42602f, 32.3446f, 3.77823f, 31.0782f, 4.44324f, 30.0568f) + curveTo(5.1181f, 29.021f, 5.99739f, 28.1799f, 7.05894f, 27.5551f) + curveTo(8.14758f, 26.9158f, 9.40371f, 26.4448f, 10.7928f, 26.1564f) + curveTo(13.1573f, 25.6662f, 15.6548f, 25.5748f, 18.1991f, 25.9209f) + curveTo(19.1941f, 26.0579f, 20.1744f, 26.3006f, 21.1202f, 26.6395f) + curveTo(22.0463f, 26.9759f, 22.9182f, 27.4349f, 23.7088f, 28.0045f) + curveTo(24.4871f, 28.5668f, 25.1767f, 29.2734f, 25.7555f, 30.1025f) + lineTo(26.0782f, 30.5663f) + lineTo(28.4673f, 29.5858f) + lineTo(27.9599f, 28.8888f) + curveTo(27.3097f, 27.9925f, 26.5905f, 27.185f, 25.8196f, 26.4905f) + curveTo(25.0339f, 25.7815f, 24.1102f, 25.1783f, 23.0733f, 24.7025f) + curveTo(22.0487f, 24.2315f, 20.8788f, 23.8686f, 19.5906f, 23.6234f) + curveTo(18.3173f, 23.3831f, 16.8321f, 23.2606f, 15.177f, 23.2606f) + curveTo(13.5883f, 23.2606f, 11.948f, 23.4384f, 10.3027f, 23.7893f) + curveTo(8.63279f, 24.1449f, 7.08357f, 24.7361f, 5.69937f, 25.5412f) + curveTo(4.28561f, 26.3655f, 3.12061f, 27.4637f, 2.23394f, 28.8071f) + curveTo(1.33741f, 30.1721f, 0.879288f, 31.8568f, 0.879288f, 33.813f) + curveTo(0.879288f, 35.8677f, 1.30292f, 37.6172f, 2.13542f, 39.0111f) + curveTo(2.96544f, 40.3977f, 4.07625f, 41.52f, 5.43829f, 42.3467f) + curveTo(6.77323f, 43.159f, 8.32984f, 43.743f, 10.0663f, 44.0818f) + curveTo(11.7608f, 44.4135f, 13.5366f, 44.5817f, 15.342f, 44.5817f) + curveTo(16.7779f, 44.5817f, 18.2976f, 44.6875f, 19.8591f, 44.8989f) + curveTo(21.3788f, 45.1032f, 22.795f, 45.5166f, 24.0634f, 46.127f) + curveTo(25.2999f, 46.723f, 26.3319f, 47.5521f, 27.1274f, 48.5902f) + curveTo(27.8959f, 49.5972f, 28.285f, 50.955f, 28.285f, 52.6276f) + curveTo(28.285f, 54.1296f, 27.9082f, 55.4105f, 27.1693f, 56.4391f) + curveTo(26.4058f, 57.4989f, 25.4132f, 58.3737f, 24.2186f, 59.0393f) + curveTo(22.9994f, 59.7194f, 21.6202f, 60.2217f, 20.1153f, 60.5269f) + curveTo(18.5857f, 60.8393f, 17.0735f, 60.9979f, 15.6178f, 60.9979f) + curveTo(13.177f, 60.9979f, 10.7633f, 60.5437f, 8.4456f, 59.6449f) + curveTo(6.14024f, 58.751f, 4.0935f, 57.41f, 2.36694f, 55.658f) + lineTo(1.90389f, 55.187f) + lineTo(0f, 56.7972f) + lineTo(0.534469f, 57.3186f) + curveTo(2.23886f, 58.9817f, 4.35457f, 60.4308f, 6.82495f, 61.6252f) + curveTo(9.32243f, 62.8364f, 12.2829f, 63.4492f, 15.6178f, 63.4492f) + curveTo(17.204f, 63.4492f, 18.8887f, 63.2738f, 20.6226f, 62.9229f) + curveTo(22.3812f, 62.5696f, 24.0339f, 61.964f, 25.5289f, 61.1205f) + curveTo(27.0486f, 60.265f, 28.3121f, 59.1475f, 29.2875f, 57.7945f) + curveTo(30.2899f, 56.4054f, 30.7973f, 54.6679f, 30.7973f, 52.6276f) + curveTo(30.7973f, 50.5609f, 30.3219f, 48.8089f, 29.381f, 47.4247f) + curveTo(28.455f, 46.0573f, 27.2161f, 44.9662f, 25.7013f, 44.178f) + close() + + moveTo(48.1663f, 61.2936f) + curveTo(46.4422f, 61.2936f, 44.8684f, 60.9503f, 43.4842f, 60.271f) + curveTo(42.0802f, 59.5845f, 40.8414f, 58.65f, 39.802f, 57.4915f) + curveTo(38.7552f, 56.3283f, 37.9252f, 54.9672f, 37.3316f, 53.4463f) + curveTo(36.7355f, 51.9184f, 36.3957f, 50.3165f, 36.3267f, 48.7146f) + curveTo(36.3267f, 47.2319f, 36.6124f, 45.7183f, 37.169f, 44.2117f) + curveTo(37.7281f, 42.71f, 38.5409f, 41.3417f, 39.5877f, 40.1427f) + curveTo(40.6295f, 38.9485f, 41.898f, 37.9616f, 43.361f, 37.2036f) + curveTo(44.7969f, 36.4575f, 46.4127f, 36.0808f, 48.1663f, 36.0808f) + curveTo(49.814f, 36.0808f, 51.3707f, 36.4336f, 52.7918f, 37.1297f) + curveTo(54.2351f, 37.8353f, 55.5011f, 38.7816f, 56.5626f, 39.9401f) + curveTo(57.6242f, 41.1057f, 58.4739f, 42.4669f, 59.0848f, 43.9877f) + curveTo(59.6956f, 45.5061f, 60.0034f, 47.0984f, 60.0034f, 48.7146f) + curveTo(60.0034f, 50.1949f, 59.7202f, 51.7086f, 59.1611f, 53.2151f) + curveTo(58.602f, 54.7193f, 57.7892f, 56.0875f, 56.7449f, 57.2842f) + curveTo(55.7031f, 58.476f, 54.4371f, 59.4557f, 52.9765f, 60.1947f) + curveTo(51.5406f, 60.9241f, 49.9224f, 61.2936f, 48.1663f, 61.2936f) + close() + moveTo(58.6192f, 38.486f) + curveTo(57.368f, 37.0725f, 55.8484f, 35.902f, 54.1021f, 35.0105f) + curveTo(52.3312f, 34.1071f, 50.3337f, 33.6494f, 48.1663f, 33.6494f) + curveTo(46.191f, 33.6494f, 44.3043f, 34.057f, 42.5581f, 34.8651f) + curveTo(40.8241f, 35.6661f, 39.2921f, 36.7721f, 38.004f, 38.1499f) + curveTo(36.7183f, 39.5229f, 35.6888f, 41.1391f, 34.9425f, 42.9555f) + curveTo(34.1937f, 44.7719f, 33.8144f, 46.7099f, 33.8144f, 48.7146f) + curveTo(33.8144f, 50.6073f, 34.1642f, 52.4619f, 34.8563f, 54.2234f) + curveTo(35.5435f, 55.9826f, 36.5262f, 57.5797f, 37.7725f, 58.9718f) + curveTo(39.0237f, 60.3711f, 40.5458f, 61.5129f, 42.2945f, 62.3687f) + curveTo(44.058f, 63.2316f, 46.0309f, 63.6892f, 48.154f, 63.725f) + horizontalLineTo(48.1786f) + curveTo(50.1884f, 63.6892f, 52.0899f, 63.2506f, 53.8336f, 62.4283f) + curveTo(55.5627f, 61.6106f, 57.0947f, 60.495f, 58.3853f, 59.1172f) + curveTo(59.6685f, 57.7442f, 60.6882f, 56.1447f, 61.4172f, 54.3665f) + curveTo(62.1463f, 52.581f, 62.5157f, 50.6788f, 62.5157f, 48.7146f) + curveTo(62.5157f, 46.934f, 62.1758f, 45.1199f, 61.5083f, 43.3226f) + curveTo(60.8384f, 41.5253f, 59.8655f, 39.8972f, 58.6192f, 38.486f) + close() + + moveTo(75.5252f, 60.5855f) + curveTo(75.1041f, 60.6889f, 74.7321f, 60.7658f, 74.4218f, 60.8163f) + curveTo(74.0942f, 60.8716f, 73.742f, 60.9245f, 73.3603f, 60.9774f) + curveTo(73.008f, 61.0255f, 72.6608f, 61.052f, 72.3258f, 61.052f) + curveTo(71.4835f, 61.052f, 70.8628f, 60.7779f, 70.4293f, 60.2176f) + curveTo(69.949f, 59.5997f, 69.715f, 58.9842f, 69.715f, 58.3398f) + verticalLineTo(22.4329f) + horizontalLineTo(67.2028f) + verticalLineTo(58.3398f) + curveTo(67.2028f, 59.6863f, 67.6387f, 60.8789f, 68.4983f, 61.8815f) + curveTo(69.3899f, 62.9226f, 70.6584f, 63.4491f, 72.2716f, 63.4491f) + curveTo(72.7765f, 63.4491f, 73.279f, 63.4203f, 73.7642f, 63.365f) + curveTo(74.2322f, 63.3097f, 74.6509f, 63.2544f, 75.0277f, 63.1991f) + curveTo(75.4119f, 63.1438f, 75.8577f, 63.0572f, 76.3528f, 62.9466f) + lineTo(77.205f, 62.7543f) + lineTo(76.0868f, 60.4485f) + lineTo(75.5252f, 60.5855f) + close() + + moveTo(86.3673f, 36.1095f) + curveTo(85.0619f, 36.9976f, 83.9068f, 38.1263f, 82.9191f, 39.4764f) + verticalLineTo(34.0903f) + horizontalLineTo(80.4069f) + verticalLineTo(63.1733f) + horizontalLineTo(82.9191f) + verticalLineTo(45.0672f) + curveTo(83.2664f, 43.8814f, 83.7467f, 42.7671f, 84.3452f, 41.7599f) + curveTo(84.9487f, 40.7431f, 85.6974f, 39.8478f, 86.5742f, 39.1001f) + curveTo(87.4511f, 38.3525f, 88.4707f, 37.7477f, 89.6086f, 37.2976f) + curveTo(90.7416f, 36.8476f, 92.0224f, 36.5857f, 93.4115f, 36.519f) + lineTo(94.079f, 36.4857f) + verticalLineTo(34.0903f) + horizontalLineTo(93.377f) + curveTo(90.6973f, 34.0903f, 88.3402f, 34.7689f, 86.3673f, 36.1095f) + close() + } + }.build(), + ) + + val sunPainter = rememberVectorPainter( + ImageVector.Builder( + name = "Logos.SolrLogo.Sun", + defaultWidth = 128.dp, + defaultHeight = 64.dp, + viewportWidth = 128f, + viewportHeight = 64f, + autoMirror = false, + ).apply { + materialPath { + moveTo(122.265f, 6.69195f) + lineTo(101.458f, 28.1865f) + lineTo(127.608f, 16.659f) + curveTo(126.834f, 12.844f, 124.94f, 9.41495f, 122.265f, 6.69195f) + close() + + moveTo(106.827f, 0f) + curveTo(103.946f, 0f, 101.199f, 0.555789f, 98.6946f, 1.55857f) + lineTo(95.9016f, 24.1496f) + lineTo(109.854f, 0.21049f) + curveTo(108.864f, 0.073317f, 107.857f, 0f, 106.827f, 0f) + close() + + moveTo(127.817f, 18.4183f) + lineTo(103.037f, 31.2849f) + lineTo(126.285f, 28.7253f) + curveTo(127.388f, 26.3462f, 127.999f, 23.7272f, 127.999f, 20.9733f) + curveTo(127.999f, 20.1072f, 127.933f, 19.2547f, 127.817f, 18.4183f) + close() + + moveTo(118.682f, 37.7183f) + curveTo(121.45f, 36.0998f, 123.748f, 33.9305f, 125.371f, 31.3933f) + lineTo(103.581f, 35.1279f) + lineTo(118.682f, 37.7183f) + close() + + moveTo(111.13f, 0.438413f) + lineTo(99f, 25.7284f) + lineTo(121.499f, 5.70775f) + curveTo(118.679f, 3.09678f, 115.11f, 1.22976f, 111.13f, 0.438413f) + close() + + moveTo(108.598f, 41.265f) + curveTo(110.943f, 41.1329f, 113.177f, 40.7452f, 115.243f, 40.1369f) + lineTo(103.037f, 39.1542f) + lineTo(108.598f, 41.265f) + close() + + moveTo(87.5299f, 12.4677f) + curveTo(86.5767f, 14.4097f, 85.9585f, 16.5197f, 85.7442f, 18.7363f) + lineTo(89.0323f, 24.1496f) + lineTo(87.5299f, 12.4677f) + close() + + moveTo(96.8597f, 2.49255f) + curveTo(93.8721f, 4.01874f, 91.3155f, 6.20574f, 89.3993f, 8.85365f) + lineTo(92.4682f, 23.6053f) + lineTo(96.8597f, 2.49255f) + close() + } + }.build(), + ) + + Box(modifier) { + Icon( + painter = solrPainter, + tint = MaterialTheme.colorScheme.onBackground, + contentDescription = stringResource(Res.string.cd_solr_logo), + ) + + Icon( + painter = sunPainter, + tint = MaterialTheme.colorScheme.primaryContainer, + contentDescription = stringResource(Res.string.cd_solr_logo), + ) + } +} diff --git a/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/ui/logging/LoggingContent.kt b/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/ui/logging/LoggingContent.kt new file mode 100644 index 00000000000..a6abd6ea38a --- /dev/null +++ b/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/ui/logging/LoggingContent.kt @@ -0,0 +1,28 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.solr.composeui.ui.logging + +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier + +@Composable +fun LoggingContent( + modifier: Modifier = Modifier, +) { + // TODO Add logging content here +} diff --git a/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/ui/navigation/Footer.kt b/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/ui/navigation/Footer.kt new file mode 100644 index 00000000000..ccb2e85e6d1 --- /dev/null +++ b/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/ui/navigation/Footer.kt @@ -0,0 +1,119 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.solr.composeui.ui.navigation + +import androidx.compose.foundation.border +import androidx.compose.foundation.clickable +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.padding +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.automirrored.rounded.MenuBook +import androidx.compose.material.icons.rounded.BugReport +import androidx.compose.material.icons.rounded.Code +import androidx.compose.material.icons.rounded.Dashboard +import androidx.compose.material.icons.rounded.Groups +import androidx.compose.material.icons.rounded.ImageNotSupported +import androidx.compose.material.icons.rounded.Support +import androidx.compose.material3.HorizontalDivider +import androidx.compose.material3.Icon +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.vector.ImageVector +import androidx.compose.ui.unit.dp +import org.apache.solr.compose_ui.generated.resources.Res +import org.apache.solr.compose_ui.generated.resources.community +import org.apache.solr.compose_ui.generated.resources.documentation +import org.apache.solr.compose_ui.generated.resources.irc +import org.apache.solr.compose_ui.generated.resources.issue_tracker +import org.apache.solr.compose_ui.generated.resources.slack +import org.apache.solr.compose_ui.generated.resources.solr_query_syntax +import org.apache.solr.compose_ui.generated.resources.support +import org.jetbrains.compose.resources.StringResource +import org.jetbrains.compose.resources.stringResource + +/** + * The basic footer shown in all pages. + */ +@Composable +fun Footer( + modifier: Modifier = Modifier, +) = Column(modifier = modifier) { + HorizontalDivider() + Row( + modifier = Modifier.fillMaxWidth(), + horizontalArrangement = Arrangement.Center, + ) { + FooterAction( + imageVector = Icons.AutoMirrored.Rounded.MenuBook, + stringRes = Res.string.documentation, + ) + + FooterAction( + imageVector = Icons.Rounded.Code, + stringRes = Res.string.solr_query_syntax, + ) + + FooterAction( + imageVector = Icons.Rounded.BugReport, + stringRes = Res.string.issue_tracker, + ) + + FooterAction( + imageVector = Icons.Rounded.Groups, + stringRes = Res.string.community, + ) + + FooterAction( + imageVector = Icons.Rounded.ImageNotSupported, // TODO Add Slack Logo + stringRes = Res.string.slack, + ) + + FooterAction( + imageVector = Icons.Rounded.Dashboard, + stringRes = Res.string.irc, + ) + + FooterAction( + imageVector = Icons.Rounded.Support, + stringRes = Res.string.support, + ) + } +} + +@Composable +private fun FooterAction( + imageVector: ImageVector, + stringRes: StringResource, + onClick: () -> Unit = {}, +) = Row( + modifier = Modifier.clickable(onClick = onClick) + .padding(horizontal = 16.dp, vertical = 12.dp), + horizontalArrangement = Arrangement.spacedBy(8.dp), + verticalAlignment = Alignment.CenterVertically, +) { + Icon( + imageVector = imageVector, + contentDescription = null, + ) + Text(stringResource(stringRes)) +} diff --git a/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/ui/navigation/NavigationSideBar.kt b/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/ui/navigation/NavigationSideBar.kt new file mode 100644 index 00000000000..5e966c36acd --- /dev/null +++ b/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/ui/navigation/NavigationSideBar.kt @@ -0,0 +1,164 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.solr.composeui.ui.navigation + +import androidx.compose.foundation.background +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.fillMaxHeight +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.padding +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.automirrored.rounded.Logout +import androidx.compose.material.icons.automirrored.rounded.TextSnippet +import androidx.compose.material.icons.automirrored.rounded.ViewList +import androidx.compose.material.icons.rounded.Analytics +import androidx.compose.material.icons.rounded.Apps +import androidx.compose.material.icons.rounded.Dashboard +import androidx.compose.material.icons.rounded.DocumentScanner +import androidx.compose.material.icons.rounded.Folder +import androidx.compose.material.icons.rounded.Hub +import androidx.compose.material.icons.rounded.Memory +import androidx.compose.material.icons.rounded.Security +import androidx.compose.material3.Icon +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Tab +import androidx.compose.material3.Text +import androidx.compose.material3.VerticalDivider +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.graphics.vector.ImageVector +import androidx.compose.ui.unit.dp +import org.apache.solr.compose_ui.generated.resources.Res +import org.apache.solr.compose_ui.generated.resources.logout +import org.apache.solr.compose_ui.generated.resources.nav_cluster +import org.apache.solr.compose_ui.generated.resources.nav_collections +import org.apache.solr.compose_ui.generated.resources.nav_configsets +import org.apache.solr.compose_ui.generated.resources.nav_dashboard +import org.apache.solr.compose_ui.generated.resources.nav_environment +import org.apache.solr.compose_ui.generated.resources.nav_logging +import org.apache.solr.compose_ui.generated.resources.nav_metrics +import org.apache.solr.compose_ui.generated.resources.nav_queries_and_operations +import org.apache.solr.compose_ui.generated.resources.nav_security +import org.apache.solr.compose_ui.generated.resources.nav_thread_dump +import org.apache.solr.composeui.components.navigation.MainMenu +import org.apache.solr.composeui.ui.icons.SolrLogo +import org.jetbrains.compose.resources.stringResource + +@Composable +fun NavigationSideBar( + onNavigate: (MainMenu) -> Unit, + selectedItem: MainMenu? = null, + modifier: Modifier = Modifier, +) = Row(modifier = modifier) { + Column(Modifier.fillMaxHeight()) { + SolrLogo( + modifier = Modifier.fillMaxWidth() + .padding(horizontal = 16.dp, vertical = 8.dp), + ) + Column(modifier = Modifier.weight(1f)) { + MainMenu.entries.forEach { item -> + MenuElement( + text = stringResource(getMainMenuText(item)), + imageVector = getMenuIcon(item), + modifier = Modifier.fillMaxWidth(), + selected = item == selectedItem, + enabled = item == MainMenu.Logging, + onClick = { onNavigate(item) }, + ) + } + } + + // TODO Add condition for displaying logout button if user identity / auth present + MenuElement( + text = stringResource(Res.string.logout), + imageVector = Icons.AutoMirrored.Rounded.Logout, + modifier = Modifier.fillMaxWidth(), + onClick = {}, // TODO Call logout on auth component + ) + } + VerticalDivider() +} + +@Composable +private fun MenuElement( + text: String, + imageVector: ImageVector, + modifier: Modifier = Modifier, + selected: Boolean = false, + enabled: Boolean = true, + onClick: () -> Unit, +) { + val alpha = if (enabled) 1f else 0.38f + Tab( + modifier = modifier.background( + if (selected) MaterialTheme.colorScheme.primaryContainer.copy(alpha = alpha) + else Color.Unspecified, + ), + selected = selected, + enabled = enabled, + selectedContentColor = MaterialTheme.colorScheme.onPrimaryContainer.copy(alpha = alpha), + unselectedContentColor = MaterialTheme.colorScheme.onSurface.copy(alpha = alpha), + onClick = onClick, + ) { + Row( + modifier = Modifier.fillMaxWidth() + .padding(horizontal = 16.dp, vertical = 12.dp), + horizontalArrangement = Arrangement.spacedBy(8.dp), + verticalAlignment = Alignment.CenterVertically, + ) { + Icon( + imageVector = imageVector, + contentDescription = null, + ) + Text( + style = MaterialTheme.typography.labelLarge, + text = text, + ) + } + } +} + +private fun getMainMenuText(item: MainMenu) = when (item) { + MainMenu.Dashboard -> Res.string.nav_dashboard + MainMenu.Metrics -> Res.string.nav_metrics + MainMenu.Cluster -> Res.string.nav_cluster + MainMenu.Security -> Res.string.nav_security + MainMenu.Configsets -> Res.string.nav_configsets + MainMenu.Collections -> Res.string.nav_collections + MainMenu.QueriesAndOperations -> Res.string.nav_queries_and_operations + MainMenu.Environment -> Res.string.nav_environment + MainMenu.Logging -> Res.string.nav_logging + MainMenu.ThreadDump -> Res.string.nav_thread_dump +} + +private fun getMenuIcon(item: MainMenu) = when (item) { + MainMenu.Dashboard -> Icons.Rounded.Dashboard + MainMenu.Metrics -> Icons.Rounded.Analytics + MainMenu.Cluster -> Icons.Rounded.Hub + MainMenu.Security -> Icons.Rounded.Security + MainMenu.Configsets -> Icons.Rounded.Folder // TODO Update to FolderData + MainMenu.Collections -> Icons.Rounded.Apps + MainMenu.QueriesAndOperations -> Icons.Rounded.DocumentScanner // TODO Update to OtherAdmission + MainMenu.Environment -> Icons.Rounded.Memory + MainMenu.Logging -> Icons.AutoMirrored.Rounded.TextSnippet + MainMenu.ThreadDump -> Icons.AutoMirrored.Rounded.ViewList +} diff --git a/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/ui/root/RootContent.kt b/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/ui/root/RootContent.kt index 2d720f294ab..ce2b58f6c82 100644 --- a/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/ui/root/RootContent.kt +++ b/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/ui/root/RootContent.kt @@ -17,9 +17,23 @@ package org.apache.solr.composeui.ui.root -import androidx.compose.material3.Text +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.fillMaxHeight +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.width import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.setValue +import androidx.compose.ui.Modifier +import androidx.compose.ui.unit.dp +import org.apache.solr.composeui.components.navigation.MainMenu import org.apache.solr.composeui.components.root.RootComponent +import org.apache.solr.composeui.ui.navigation.Footer +import org.apache.solr.composeui.ui.navigation.NavigationSideBar /** * The root composable of the Compose application. This function is used as the shared entry @@ -30,6 +44,22 @@ import org.apache.solr.composeui.components.root.RootComponent @Composable fun RootContent( component: RootComponent, + modifier: Modifier = Modifier, ) { - Text("Hello World!") + // TODO Move selected to component / state store + var selected by remember { mutableStateOf(MainMenu.Logging) } + + Column(modifier = modifier.fillMaxSize()) { + Row(modifier = Modifier.weight(1f)) { + NavigationSideBar( + modifier = Modifier.fillMaxHeight() + .width(224.dp), + selectedItem = selected, + onNavigate = { selected = it }, // TODO Add proper onNavigate handler + ) + + // TODO Add page-specific content here + } + Footer(modifier = Modifier.fillMaxWidth()) + } } diff --git a/solr/compose-ui/src/desktopMain/kotlin/org/apache/solr/composeui/preview/PreviewContainer.kt b/solr/compose-ui/src/desktopMain/kotlin/org/apache/solr/composeui/preview/PreviewContainer.kt new file mode 100644 index 00000000000..36266ec2871 --- /dev/null +++ b/solr/compose-ui/src/desktopMain/kotlin/org/apache/solr/composeui/preview/PreviewContainer.kt @@ -0,0 +1,41 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.solr.composeui.preview + +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.padding +import androidx.compose.material3.Surface +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.unit.dp +import org.apache.solr.composeui.ui.theme.SolrTheme + +/** + * This preview container can be used for applying the basic app theme on existing components. + */ +@Composable +fun PreviewContainer(content: @Composable () -> Unit) { + SolrTheme(useDarkTheme = false) { + Surface(modifier = Modifier.fillMaxSize()) { + Surface( + modifier = Modifier.padding(16.dp), + content = content, + ) + } + } +} diff --git a/solr/compose-ui/src/desktopMain/kotlin/org/apache/solr/composeui/preview/navigation/PreviewNavigationSideBar.kt b/solr/compose-ui/src/desktopMain/kotlin/org/apache/solr/composeui/preview/navigation/PreviewNavigationSideBar.kt new file mode 100644 index 00000000000..24084f0379a --- /dev/null +++ b/solr/compose-ui/src/desktopMain/kotlin/org/apache/solr/composeui/preview/navigation/PreviewNavigationSideBar.kt @@ -0,0 +1,29 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.solr.composeui.preview.navigation + +import androidx.compose.desktop.ui.tooling.preview.Preview +import androidx.compose.runtime.Composable +import org.apache.solr.composeui.preview.PreviewContainer +import org.apache.solr.composeui.ui.navigation.NavigationSideBar + +@Preview +@Composable +fun PreviewNavigationSideBar() = PreviewContainer { + NavigationSideBar(onNavigate = {}) +} From 104f70acdee6cb3353ddd44ec0c426849e1813b3 Mon Sep 17 00:00:00 2001 From: Christos Malliaridis Date: Sat, 6 Jul 2024 01:36:05 +0200 Subject: [PATCH 05/66] Add advanced example with query parameter navigation for Web --- solr/compose-ui/build.gradle.kts | 1 + .../environment/EnvironmentComponent.kt | 20 ++ .../DefaultEnvironmentComponent.kt | 27 +++ .../components/logging/LoggingComponent.kt | 20 ++ .../integration/DefaultLoggingComponent.kt} | 10 +- .../components/main/MainComponent.kt | 91 ++++++++ .../main/MainNavigationComponent.kt | 31 +++ .../main/integration/DefaultMainComponent.kt | 200 ++++++++++++++++++ .../components/main/integration/Mappers.kt | 29 +++ .../navigation/NavigationComponent.kt | 31 +++ .../components/root/RootComponent.kt | 23 +- .../root/integration/SimpleRootComponent.kt | 84 ++++++++ .../ui/environment/EnvironmentContent.kt | 32 +++ .../composeui/ui/logging/LoggingContent.kt | 4 + .../solr/composeui/ui/main/MainContent.kt | 77 +++++++ .../{components => ui}/navigation/MainMenu.kt | 6 +- .../ui/navigation/NavigationSideBar.kt | 20 +- .../solr/composeui/ui/root/RootContent.kt | 33 ++- .../kotlin/org/apache/solr/composeui/Main.kt | 4 +- .../kotlin/org/apache/solr/composeui/Main.kt | 10 +- 20 files changed, 718 insertions(+), 35 deletions(-) create mode 100644 solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/components/environment/EnvironmentComponent.kt create mode 100644 solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/components/environment/integration/DefaultEnvironmentComponent.kt create mode 100644 solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/components/logging/LoggingComponent.kt rename solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/components/{root/integration/DefaultRootComponent.kt => logging/integration/DefaultLoggingComponent.kt} (81%) create mode 100644 solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/components/main/MainComponent.kt create mode 100644 solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/components/main/MainNavigationComponent.kt create mode 100644 solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/components/main/integration/DefaultMainComponent.kt create mode 100644 solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/components/main/integration/Mappers.kt create mode 100644 solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/components/navigation/NavigationComponent.kt create mode 100644 solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/components/root/integration/SimpleRootComponent.kt create mode 100644 solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/ui/environment/EnvironmentContent.kt create mode 100644 solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/ui/main/MainContent.kt rename solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/{components => ui}/navigation/MainMenu.kt (78%) diff --git a/solr/compose-ui/build.gradle.kts b/solr/compose-ui/build.gradle.kts index 5203ef37423..0722d887574 100644 --- a/solr/compose-ui/build.gradle.kts +++ b/solr/compose-ui/build.gradle.kts @@ -32,6 +32,7 @@ repositories { plugins { alias(libs.plugins.kotlinMultiplatform) + alias(libs.plugins.kotlinSerialization) alias(libs.plugins.jetbrainsCompose) alias(libs.plugins.compose.compiler) } diff --git a/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/components/environment/EnvironmentComponent.kt b/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/components/environment/EnvironmentComponent.kt new file mode 100644 index 00000000000..dc96009cf5c --- /dev/null +++ b/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/components/environment/EnvironmentComponent.kt @@ -0,0 +1,20 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.solr.composeui.components.environment + +interface EnvironmentComponent \ No newline at end of file diff --git a/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/components/environment/integration/DefaultEnvironmentComponent.kt b/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/components/environment/integration/DefaultEnvironmentComponent.kt new file mode 100644 index 00000000000..c9e5fe8feb3 --- /dev/null +++ b/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/components/environment/integration/DefaultEnvironmentComponent.kt @@ -0,0 +1,27 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.solr.composeui.components.environment.integration + +import com.arkivanov.mvikotlin.core.store.StoreFactory +import org.apache.solr.composeui.components.environment.EnvironmentComponent +import org.apache.solr.composeui.utils.AppComponentContext + +class DefaultEnvironmentComponent( + componentContext: AppComponentContext, + storeFactory: StoreFactory, +) : EnvironmentComponent, AppComponentContext by componentContext diff --git a/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/components/logging/LoggingComponent.kt b/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/components/logging/LoggingComponent.kt new file mode 100644 index 00000000000..b1073b58aa8 --- /dev/null +++ b/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/components/logging/LoggingComponent.kt @@ -0,0 +1,20 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.solr.composeui.components.logging + +interface LoggingComponent diff --git a/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/components/root/integration/DefaultRootComponent.kt b/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/components/logging/integration/DefaultLoggingComponent.kt similarity index 81% rename from solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/components/root/integration/DefaultRootComponent.kt rename to solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/components/logging/integration/DefaultLoggingComponent.kt index c177bff7d30..572d228e7bb 100644 --- a/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/components/root/integration/DefaultRootComponent.kt +++ b/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/components/logging/integration/DefaultLoggingComponent.kt @@ -15,15 +15,13 @@ * limitations under the License. */ -package org.apache.solr.composeui.components.root.integration +package org.apache.solr.composeui.components.logging.integration import com.arkivanov.mvikotlin.core.store.StoreFactory -import org.apache.solr.composeui.components.root.RootComponent +import org.apache.solr.composeui.components.logging.LoggingComponent import org.apache.solr.composeui.utils.AppComponentContext -class DefaultRootComponent( +class DefaultLoggingComponent( componentContext: AppComponentContext, storeFactory: StoreFactory, -) : RootComponent, AppComponentContext by componentContext { - -} +) : LoggingComponent, AppComponentContext by componentContext diff --git a/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/components/main/MainComponent.kt b/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/components/main/MainComponent.kt new file mode 100644 index 00000000000..ee0e54065df --- /dev/null +++ b/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/components/main/MainComponent.kt @@ -0,0 +1,91 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.solr.composeui.components.main + +import com.arkivanov.decompose.router.stack.ChildStack +import com.arkivanov.decompose.value.Value +import kotlinx.coroutines.flow.StateFlow +import org.apache.solr.composeui.components.environment.EnvironmentComponent +import org.apache.solr.composeui.components.logging.LoggingComponent +import org.apache.solr.composeui.components.navigation.NavigationComponent +import org.apache.solr.composeui.ui.navigation.MainMenu + +/** + * Main component of the application that is used as base for users with access. + * + * Note that this component can be accessed if the user is either authenticated or if the Solr + * instance accessed does not have any authentication enabled. + */ +interface MainComponent : NavigationComponent { + + /** + * Child stack that holds the navigation state. + */ + val childStack: Value> + + /** + * Handles navigation requests from a navigation menu. + * + * @param menuItem The destination to navigate to. + */ + fun onNavigate(menuItem: MainMenu) + + /** + * Child interface that defines all available children of the [MainComponent]. + */ + sealed interface Child { + + // TODO Uncomment once DashboardComponent available + // data class Dashboard(val component: DashboardComponent): Child + + // TODO Uncomment once MetricsComponent available + // data class Metrics(val component: MetricsComponent): Child + + // TODO Uncomment once ClusterComponent available + // data class Cluster(val component: ClusterComponent): Child + + // TODO Uncomment once SecurityComponent available + // data class Security(val component: SecurityComponent): Child + + // TODO Uncomment once ConfigsetsComponent available + // data class Configsets(val component: ConfigsetsComponent): Child + + // TODO Uncomment once MetricsComponent available + // data class Collections(val component: CollectionsComponent): Child + + // TODO Uncomment once QueriesAndOperationsComponent available + // data class QueriesAndOperations(val component: QueriesAndOperationsComponent): Child + + /** + * Child that leads to the environment section. + * + * @property component Component that holds the state of this child. + */ + data class Environment(val component: EnvironmentComponent) : Child + + /** + * Child that leads to the logging section. + * + * @property component Component that holds the state of this child. + */ + data class Logging(val component: LoggingComponent) : Child + + // TODO Uncomment once ThreadDump available + // data class ThreadDump(val component: ThreadDumpComponent): Child + } +} \ No newline at end of file diff --git a/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/components/main/MainNavigationComponent.kt b/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/components/main/MainNavigationComponent.kt new file mode 100644 index 00000000000..1415a540f37 --- /dev/null +++ b/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/components/main/MainNavigationComponent.kt @@ -0,0 +1,31 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.solr.composeui.components.main + +import org.apache.solr.composeui.components.navigation.NavigationComponent + +/** + * The abstracted navigation part of the [AbstractMainComponent]. + * + * This navigation is limited to the destinations of defined by [Child] and [Configuration]. + * + * @see Configuration + */ +interface MainNavigationComponent : NavigationComponent { + +} diff --git a/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/components/main/integration/DefaultMainComponent.kt b/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/components/main/integration/DefaultMainComponent.kt new file mode 100644 index 00000000000..dc0da8a9647 --- /dev/null +++ b/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/components/main/integration/DefaultMainComponent.kt @@ -0,0 +1,200 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.solr.composeui.components.main.integration + +import com.arkivanov.decompose.router.stack.ChildStack +import com.arkivanov.decompose.router.stack.StackNavigation +import com.arkivanov.decompose.router.stack.bringToFront +import com.arkivanov.decompose.router.stack.childStack +import com.arkivanov.decompose.value.Value +import com.arkivanov.mvikotlin.core.store.StoreFactory +import kotlinx.serialization.Serializable +import org.apache.solr.composeui.components.environment.EnvironmentComponent +import org.apache.solr.composeui.components.environment.integration.DefaultEnvironmentComponent +import org.apache.solr.composeui.components.logging.LoggingComponent +import org.apache.solr.composeui.components.logging.integration.DefaultLoggingComponent +import org.apache.solr.composeui.components.main.MainComponent +import org.apache.solr.composeui.components.main.MainComponent.Child +import org.apache.solr.composeui.ui.navigation.MainMenu +import org.apache.solr.composeui.utils.AppComponentContext + +class DefaultMainComponent internal constructor( + componentContext: AppComponentContext, + storeFactory: StoreFactory, + destination: String? = null, + private val environmentComponent: (AppComponentContext) -> EnvironmentComponent, + private val loggingComponent: (AppComponentContext) -> LoggingComponent, +) : MainComponent, AppComponentContext by componentContext { + + private val navigation = StackNavigation() + private val stack = childStack( + source = navigation, + serializer = Configuration.serializer(), + initialStack = { calculateInitialStack(destination) }, + handleBackButton = true, + childFactory = ::createChild + ) + override val childStack: Value> = stack + + constructor( + componentContext: AppComponentContext, + storeFactory: StoreFactory, + destination: String? = null, + ) : this( + componentContext = componentContext, + storeFactory = storeFactory, + destination = destination, + environmentComponent = { childContext -> + DefaultEnvironmentComponent( + componentContext = childContext, + storeFactory = storeFactory, + ) + }, + loggingComponent = { childContext -> + DefaultLoggingComponent( + componentContext = childContext, + storeFactory = storeFactory, + ) + }, + ) + + override fun onNavigate(menuItem: MainMenu) = + navigation.bringToFront(menuItem.toConfiguration()) + + override fun onNavigateBack() { + TODO("Not yet implemented") + } + + /** + * Calculates the initial stack based on the destination provided. + */ + private fun calculateInitialStack(destination: String?): List = listOf( + when(destination) { + "environment" -> Configuration.Environment + "logging" -> Configuration.Logging + else -> Configuration.Environment + } + ) + + private fun createChild( + configuration: Configuration, + componentContext: AppComponentContext, + ): Child = when (configuration) { + // TODO Uncomment once Dashboard available + // Configuration.Dashboard -> + // NavigationComponent.Child.Dashboard(dashboardComponent(componentContext)) + + // TODO Uncomment once Metrics available + // Configuration.Metrics -> + // NavigationComponent.Child.Metrics(metricsComponent(componentContext)) + + // TODO Uncomment once Cluster available + // Configuration.Cluster -> + // NavigationComponent.Child.Cluster(clusterComponent(componentContext)) + + // TODO Uncomment once Security available + // Configuration.Security -> + // NavigationComponent.Child.Security(securityComponent(componentContext)) + + // TODO Uncomment once Configsets available + // Configuration.Configsets -> + // NavigationComponent.Child.Configsets(configsetsComponent(componentContext)) + + // TODO Uncomment once Collections available + // Configuration.Collections -> + // NavigationComponent.Child.Collections(collectionsComponent(componentContext)) + + // TODO Uncomment once QueriesAndOperations available + // Configuration.QueriesAndOperations -> + // NavigationComponent.Child.QueriesAndOperations(queriesAndOperationsComponent(componentContext)) + + Configuration.Environment -> Child.Environment(environmentComponent(componentContext)) + + Configuration.Logging -> Child.Logging(loggingComponent(componentContext)) + + // TODO Uncomment once ThreadDump available + // Configuration.ThreadDump -> + // NavigationComponent.Child.ThreadDump(threadDumpComponent(componentContext)) + + // TODO Remove else case once all destinations are available + else -> throw NotImplementedError("Navigation to $configuration not implemented yet.") + } + + /** + * Configuration that provides information for navigating to supported destinations. + * + * This configuration is used by both UI and business logic and therefore publicly available. + * Note that configurations are usually private to the implementation and not available in the + * interface level (therefore neither in the UI). Providing this class in the interface + * simplifies additional mappings that would otherwise be necessary. Leaking the configuration + * with the component's interface prevents the implementations from storing sensible / + * component-internal information in the configurations. Therefore, if any implementation in the + * future needs to store information in the configuration, this interface should be replaced + * with an enum and mapped accordingly per implementation. + * + * Use this practice only if really necessary. + * + * Changes to this interface have impact on both UI and business logic. + */ + @Serializable + private sealed interface Configuration { + + @Serializable + data object Dashboard : Configuration + + @Serializable + data object Metrics : Configuration + + @Serializable + data object Cluster : Configuration + + @Serializable + data object Security : Configuration + + @Serializable + data object Configsets : Configuration + + @Serializable + data object Collections : Configuration + + @Serializable + data object QueriesAndOperations : Configuration + + @Serializable + data object Environment : Configuration + + @Serializable + data object Logging : Configuration + + @Serializable + data object ThreadDump : Configuration + } + + private fun MainMenu.toConfiguration(): Configuration = when(this) { + MainMenu.Dashboard -> Configuration.Dashboard + MainMenu.Metrics -> Configuration.Metrics + MainMenu.Cluster -> Configuration.Cluster + MainMenu.Security -> Configuration.Security + MainMenu.Configsets -> Configuration.Configsets + MainMenu.Collections -> Configuration.Collections + MainMenu.QueriesAndOperations -> Configuration.QueriesAndOperations + MainMenu.Environment -> Configuration.Environment + MainMenu.Logging -> Configuration.Logging + MainMenu.ThreadDump -> Configuration.ThreadDump + } +} diff --git a/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/components/main/integration/Mappers.kt b/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/components/main/integration/Mappers.kt new file mode 100644 index 00000000000..125353cdd06 --- /dev/null +++ b/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/components/main/integration/Mappers.kt @@ -0,0 +1,29 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.solr.composeui.components.main.integration + +import org.apache.solr.composeui.components.main.MainComponent +import org.apache.solr.composeui.ui.navigation.MainMenu + + +val MainComponent.Child.asMainMenu: MainMenu + get() = when (this) { + // TODO Add additional mappings once more children are supported + is MainComponent.Child.Environment -> MainMenu.Environment + is MainComponent.Child.Logging -> MainMenu.Logging + } diff --git a/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/components/navigation/NavigationComponent.kt b/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/components/navigation/NavigationComponent.kt new file mode 100644 index 00000000000..e00173fd960 --- /dev/null +++ b/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/components/navigation/NavigationComponent.kt @@ -0,0 +1,31 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.solr.composeui.components.navigation + +/** + * Interface that provides the basic functionality for any navigation component. Navigation + * components can use this interface as base and extend it. + */ +interface NavigationComponent { + + /** + * This method is called when the user navigates back. It is used to perform any necessary + * actions or updates. + */ + fun onNavigateBack() +} diff --git a/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/components/root/RootComponent.kt b/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/components/root/RootComponent.kt index 676e3672443..6628f93b7d6 100644 --- a/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/components/root/RootComponent.kt +++ b/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/components/root/RootComponent.kt @@ -17,4 +17,25 @@ package org.apache.solr.composeui.components.root -interface RootComponent \ No newline at end of file +import com.arkivanov.decompose.router.stack.ChildStack +import com.arkivanov.decompose.value.Value +import org.apache.solr.composeui.components.main.MainComponent + +/** + * Root component used by each target as an entry point to the application. + * + * This component checks the information available at start time and redirects the user accordingly. + * Implementations may check user session, access level, destination and more. + */ +interface RootComponent { + + val childStack: Value> + + sealed interface Child { + + data class Main(val component: MainComponent): Child + + // TODO Add child once authentication is checked + // data class Unauthenticated(val component: UnauthenticatedComponent): Child + } +} diff --git a/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/components/root/integration/SimpleRootComponent.kt b/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/components/root/integration/SimpleRootComponent.kt new file mode 100644 index 00000000000..577ae2abbbd --- /dev/null +++ b/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/components/root/integration/SimpleRootComponent.kt @@ -0,0 +1,84 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.solr.composeui.components.root.integration + +import com.arkivanov.decompose.router.stack.ChildStack +import com.arkivanov.decompose.router.stack.StackNavigation +import com.arkivanov.decompose.router.stack.childStack +import com.arkivanov.decompose.value.Value +import com.arkivanov.mvikotlin.core.store.StoreFactory +import kotlinx.serialization.Serializable +import org.apache.solr.composeui.components.main.MainComponent +import org.apache.solr.composeui.components.main.integration.DefaultMainComponent +import org.apache.solr.composeui.components.root.RootComponent +import org.apache.solr.composeui.utils.AppComponentContext + +/** + * A simple root component implementation that does not check the user's access level and redirects + * to the requested destination. + * + * This component is used only temporary and will be replaced in the future with an implementation + * that checks the access level of the user before redirecting. + */ +class SimpleRootComponent( + componentContext: AppComponentContext, + storeFactory: StoreFactory, + private val mainComponent: (AppComponentContext) -> MainComponent, +) : RootComponent, AppComponentContext by componentContext { + + private val navigation = StackNavigation() + private val stack = childStack( + source = navigation, + serializer = Configuration.serializer(), + initialStack = { listOf(Configuration.Main) }, + handleBackButton = true, + childFactory = ::createChild + ) + + override val childStack: Value> = stack + + constructor( + componentContext: AppComponentContext, + storeFactory: StoreFactory, + destination: String? = null, + ) : this( + componentContext = componentContext, + storeFactory = storeFactory, + mainComponent = { childContext -> + DefaultMainComponent( + componentContext = childContext, + storeFactory = storeFactory, + destination = destination, + ) + }, + ) + + private fun createChild( + configuration: Configuration, + componentContext: AppComponentContext, + ): RootComponent.Child = when (configuration) { + Configuration.Main -> RootComponent.Child.Main(mainComponent(componentContext)) + } + + @Serializable + private sealed interface Configuration { + + @Serializable + data object Main : Configuration + } +} diff --git a/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/ui/environment/EnvironmentContent.kt b/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/ui/environment/EnvironmentContent.kt new file mode 100644 index 00000000000..1df34042b4f --- /dev/null +++ b/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/ui/environment/EnvironmentContent.kt @@ -0,0 +1,32 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.solr.composeui.ui.environment + +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import org.apache.solr.composeui.components.environment.EnvironmentComponent + +@Composable +fun EnvironmentContent( + component: EnvironmentComponent, + modifier: Modifier = Modifier, +) { + Text("Environment section") + // TODO Add logging content here +} diff --git a/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/ui/logging/LoggingContent.kt b/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/ui/logging/LoggingContent.kt index a6abd6ea38a..0706ff8674f 100644 --- a/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/ui/logging/LoggingContent.kt +++ b/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/ui/logging/LoggingContent.kt @@ -17,12 +17,16 @@ package org.apache.solr.composeui.ui.logging +import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier +import org.apache.solr.composeui.components.logging.LoggingComponent @Composable fun LoggingContent( + component: LoggingComponent, modifier: Modifier = Modifier, ) { + Text("Logging section") // TODO Add logging content here } diff --git a/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/ui/main/MainContent.kt b/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/ui/main/MainContent.kt new file mode 100644 index 00000000000..1799cdc6874 --- /dev/null +++ b/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/ui/main/MainContent.kt @@ -0,0 +1,77 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.solr.composeui.ui.main + +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.fillMaxHeight +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.width +import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.setValue +import androidx.compose.ui.Modifier +import androidx.compose.ui.unit.dp +import com.arkivanov.decompose.extensions.compose.stack.Children +import com.arkivanov.decompose.extensions.compose.subscribeAsState +import org.apache.solr.composeui.components.main.MainComponent +import org.apache.solr.composeui.ui.navigation.MainMenu +import org.apache.solr.composeui.components.main.MainNavigationComponent +import org.apache.solr.composeui.components.main.integration.asMainMenu +import org.apache.solr.composeui.ui.environment.EnvironmentContent +import org.apache.solr.composeui.ui.logging.LoggingContent +import org.apache.solr.composeui.ui.navigation.NavigationSideBar + +/** + * The composable used for users that have already authenticated. + * + * @param component Component that manages the state of the composable. + */ +@Composable +fun MainContent( + component: MainComponent, + modifier: Modifier = Modifier, +) { + val childStack by component.childStack.subscribeAsState() + + Row(modifier = modifier) { + NavigationSideBar( + modifier = Modifier.fillMaxHeight() + .width(224.dp), + selectedItem = childStack.active.instance.asMainMenu, + onNavigate = component::onNavigate, + ) + + Children( + stack = component.childStack, + modifier = Modifier.weight(1f), + ) { + when(val child = it.instance) { + is MainComponent.Child.Environment -> EnvironmentContent( + component = child.component, + modifier = Modifier.fillMaxSize(), + ) + is MainComponent.Child.Logging -> LoggingContent( + component = child.component, + modifier = Modifier.fillMaxSize(), + ) + } + } + } +} diff --git a/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/components/navigation/MainMenu.kt b/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/ui/navigation/MainMenu.kt similarity index 78% rename from solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/components/navigation/MainMenu.kt rename to solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/ui/navigation/MainMenu.kt index 03cbcbb9a21..704790a23fa 100644 --- a/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/components/navigation/MainMenu.kt +++ b/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/ui/navigation/MainMenu.kt @@ -15,10 +15,14 @@ * limitations under the License. */ -package org.apache.solr.composeui.components.navigation +package org.apache.solr.composeui.ui.navigation /** * An enum class that holds all the menu items of the main navigation. + * + * This enum is used as abstraction layer between UI and business logic. This is important because + * many UI-related elements, like icons and string resources, will depend on this enum and not a + * specific class of the business logic. */ enum class MainMenu { Dashboard, diff --git a/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/ui/navigation/NavigationSideBar.kt b/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/ui/navigation/NavigationSideBar.kt index 5e966c36acd..f04ff163300 100644 --- a/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/ui/navigation/NavigationSideBar.kt +++ b/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/ui/navigation/NavigationSideBar.kt @@ -59,10 +59,13 @@ import org.apache.solr.compose_ui.generated.resources.nav_metrics import org.apache.solr.compose_ui.generated.resources.nav_queries_and_operations import org.apache.solr.compose_ui.generated.resources.nav_security import org.apache.solr.compose_ui.generated.resources.nav_thread_dump -import org.apache.solr.composeui.components.navigation.MainMenu import org.apache.solr.composeui.ui.icons.SolrLogo import org.jetbrains.compose.resources.stringResource +/** + * The application's main navigation / sidebar. It is used for navigation between the different + * sections. + */ @Composable fun NavigationSideBar( onNavigate: (MainMenu) -> Unit, @@ -81,7 +84,7 @@ fun NavigationSideBar( imageVector = getMenuIcon(item), modifier = Modifier.fillMaxWidth(), selected = item == selectedItem, - enabled = item == MainMenu.Logging, + enabled = isSectionAvailable(item), onClick = { onNavigate(item) }, ) } @@ -162,3 +165,16 @@ private fun getMenuIcon(item: MainMenu) = when (item) { MainMenu.Logging -> Icons.AutoMirrored.Rounded.TextSnippet MainMenu.ThreadDump -> Icons.AutoMirrored.Rounded.ViewList } + +/** + * Temporary function for disabling sections in the navigation that have not been implemented yet. + * + * @param item The menu item to check for availability. + * @return Returns `true` iff the user can navigate to the section. + * TODO Remove once all sections are added + */ +private fun isSectionAvailable(item: MainMenu): Boolean = when (item) { + MainMenu.Environment -> true + MainMenu.Logging -> true + else -> false +} diff --git a/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/ui/root/RootContent.kt b/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/ui/root/RootContent.kt index ce2b58f6c82..1fc6c7ff5d6 100644 --- a/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/ui/root/RootContent.kt +++ b/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/ui/root/RootContent.kt @@ -18,22 +18,14 @@ package org.apache.solr.composeui.ui.root import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.Row -import androidx.compose.foundation.layout.fillMaxHeight import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.layout.width import androidx.compose.runtime.Composable -import androidx.compose.runtime.getValue -import androidx.compose.runtime.mutableStateOf -import androidx.compose.runtime.remember -import androidx.compose.runtime.setValue import androidx.compose.ui.Modifier -import androidx.compose.ui.unit.dp -import org.apache.solr.composeui.components.navigation.MainMenu +import com.arkivanov.decompose.extensions.compose.stack.Children import org.apache.solr.composeui.components.root.RootComponent +import org.apache.solr.composeui.ui.main.MainContent import org.apache.solr.composeui.ui.navigation.Footer -import org.apache.solr.composeui.ui.navigation.NavigationSideBar /** * The root composable of the Compose application. This function is used as the shared entry @@ -46,19 +38,18 @@ fun RootContent( component: RootComponent, modifier: Modifier = Modifier, ) { - // TODO Move selected to component / state store - var selected by remember { mutableStateOf(MainMenu.Logging) } - Column(modifier = modifier.fillMaxSize()) { - Row(modifier = Modifier.weight(1f)) { - NavigationSideBar( - modifier = Modifier.fillMaxHeight() - .width(224.dp), - selectedItem = selected, - onNavigate = { selected = it }, // TODO Add proper onNavigate handler - ) - // TODO Add page-specific content here + Children( + stack = component.childStack, + modifier = Modifier.weight(1f), + ) { + when(val child = it.instance) { + is RootComponent.Child.Main -> MainContent( + component = child.component, + modifier = Modifier.fillMaxSize(), + ) + } } Footer(modifier = Modifier.fillMaxWidth()) } diff --git a/solr/compose-ui/src/desktopMain/kotlin/org/apache/solr/composeui/Main.kt b/solr/compose-ui/src/desktopMain/kotlin/org/apache/solr/composeui/Main.kt index 2a71fe35d57..2a3e2497b31 100644 --- a/solr/compose-ui/src/desktopMain/kotlin/org/apache/solr/composeui/Main.kt +++ b/solr/compose-ui/src/desktopMain/kotlin/org/apache/solr/composeui/Main.kt @@ -32,7 +32,7 @@ import com.arkivanov.mvikotlin.main.store.DefaultStoreFactory import java.awt.Dimension import kotlinx.coroutines.Dispatchers import org.apache.solr.composeui.components.root.RootComponent -import org.apache.solr.composeui.components.root.integration.DefaultRootComponent +import org.apache.solr.composeui.components.root.integration.SimpleRootComponent import org.apache.solr.composeui.ui.root.RootContent import org.apache.solr.composeui.ui.theme.SolrTheme import org.apache.solr.composeui.utils.DefaultAppComponentContext @@ -56,7 +56,7 @@ fun main() { val root: RootComponent = runOnUiThread { setMainThreadId(Thread.currentThread().id) - DefaultRootComponent( + SimpleRootComponent( componentContext = componentContext, storeFactory = storeFactory, ) diff --git a/solr/compose-ui/src/wasmJsMain/kotlin/org/apache/solr/composeui/Main.kt b/solr/compose-ui/src/wasmJsMain/kotlin/org/apache/solr/composeui/Main.kt index 54e3a1f3011..c0d9d6326ac 100644 --- a/solr/compose-ui/src/wasmJsMain/kotlin/org/apache/solr/composeui/Main.kt +++ b/solr/compose-ui/src/wasmJsMain/kotlin/org/apache/solr/composeui/Main.kt @@ -27,10 +27,12 @@ import androidx.compose.ui.window.ComposeViewport import com.arkivanov.decompose.DefaultComponentContext import com.arkivanov.essenty.lifecycle.LifecycleRegistry import com.arkivanov.mvikotlin.main.store.DefaultStoreFactory +import io.ktor.http.Url import kotlinx.browser.document +import kotlinx.browser.window import kotlinx.coroutines.Dispatchers import org.apache.solr.composeui.components.root.RootComponent -import org.apache.solr.composeui.components.root.integration.DefaultRootComponent +import org.apache.solr.composeui.components.root.integration.SimpleRootComponent import org.apache.solr.composeui.ui.root.RootContent import org.apache.solr.composeui.ui.theme.SolrTheme import org.apache.solr.composeui.utils.DefaultAppComponentContext @@ -50,9 +52,13 @@ fun main() { ioContext = Dispatchers.Default, ) - val component: RootComponent = DefaultRootComponent( + val url = Url(window.location.href) + val destination = url.parameters["dest"] + + val component: RootComponent = SimpleRootComponent( componentContext = componentContext, storeFactory = DefaultStoreFactory(), + destination = destination, ) ComposeViewport(document.body!!) { From 0db70c602765bd3d707f9c02591a155c18539611 Mon Sep 17 00:00:00 2001 From: Christos Malliaridis Date: Wed, 10 Jul 2024 16:28:31 +0300 Subject: [PATCH 06/66] Add example implementation for environment section --- gradle/libs.versions.toml | 9 +- solr/compose-ui/build.gradle.kts | 8 ++ .../font/firacode-variable.ttf | Bin 0 -> 259308 bytes .../font/raleway-variable.ttf | Bin 0 -> 311856 bytes .../environment/EnvironmentComponent.kt | 26 ++++- .../data/JavaPropertiesResponse.kt | 10 ++ .../environment/data/JavaProperty.kt | 3 + .../environment/data/JavaRuntimeInfo.kt | 10 ++ .../components/environment/data/Jmx.kt | 11 ++ .../components/environment/data/JvmData.kt | 15 +++ .../components/environment/data/JvmMemory.kt | 12 ++ .../environment/data/JvmMemoryRaw.kt | 14 +++ .../environment/data/SecurityConfig.kt | 8 ++ .../components/environment/data/SystemData.kt | 19 +++ .../environment/data/SystemInformation.kt | 25 ++++ .../components/environment/data/SystemMode.kt | 13 +++ .../components/environment/data/Versions.kt | 16 +++ .../DefaultEnvironmentComponent.kt | 24 +++- .../integration/HttpEnvironmentStoreClient.kt | 41 +++++++ .../environment/integration/Mappers.kt | 19 +++ .../environment/store/EnvironmentStore.kt | 32 +++++ .../store/EnvironmentStoreProvider.kt | 109 ++++++++++++++++++ .../main/integration/DefaultMainComponent.kt | 3 + .../root/integration/SimpleRootComponent.kt | 3 + .../solr/composeui/ui/components/SolrCard.kt | 30 +++++ .../environment/CommandLineArgumentsCard.kt | 53 +++++++++ .../ui/environment/EnvironmentContent.kt | 76 +++++++++++- .../ui/environment/JavaPropertiesCard.kt | 73 ++++++++++++ .../composeui/ui/environment/VersionsCard.kt | 74 ++++++++++++ .../solr/composeui/ui/main/MainContent.kt | 17 +-- .../apache/solr/composeui/ui/theme/Fonts.kt | 17 +-- .../apache/solr/composeui/ui/theme/Theme.kt | 2 +- .../solr/composeui/ui/theme/Typography.kt | 41 +++++++ .../solr/composeui/utils/CoroutineScopeExt.kt | 57 +++++++++ .../solr/composeui/utils/HttpClientUtils.kt | 24 ++++ .../kotlin/org/apache/solr/composeui/Main.kt | 15 ++- .../kotlin/org/apache/solr/composeui/Main.kt | 13 ++- solr/licenses/firacode-OFL.txt | 93 +++++++++++++++ 38 files changed, 989 insertions(+), 26 deletions(-) create mode 100644 solr/compose-ui/src/commonMain/composeResources/font/firacode-variable.ttf create mode 100644 solr/compose-ui/src/commonMain/composeResources/font/raleway-variable.ttf create mode 100644 solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/components/environment/data/JavaPropertiesResponse.kt create mode 100644 solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/components/environment/data/JavaProperty.kt create mode 100644 solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/components/environment/data/JavaRuntimeInfo.kt create mode 100644 solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/components/environment/data/Jmx.kt create mode 100644 solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/components/environment/data/JvmData.kt create mode 100644 solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/components/environment/data/JvmMemory.kt create mode 100644 solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/components/environment/data/JvmMemoryRaw.kt create mode 100644 solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/components/environment/data/SecurityConfig.kt create mode 100644 solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/components/environment/data/SystemData.kt create mode 100644 solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/components/environment/data/SystemInformation.kt create mode 100644 solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/components/environment/data/SystemMode.kt create mode 100644 solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/components/environment/data/Versions.kt create mode 100644 solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/components/environment/integration/HttpEnvironmentStoreClient.kt create mode 100644 solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/components/environment/integration/Mappers.kt create mode 100644 solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/components/environment/store/EnvironmentStore.kt create mode 100644 solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/components/environment/store/EnvironmentStoreProvider.kt create mode 100644 solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/ui/components/SolrCard.kt create mode 100644 solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/ui/environment/CommandLineArgumentsCard.kt create mode 100644 solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/ui/environment/JavaPropertiesCard.kt create mode 100644 solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/ui/environment/VersionsCard.kt create mode 100644 solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/ui/theme/Typography.kt create mode 100644 solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/utils/CoroutineScopeExt.kt create mode 100644 solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/utils/HttpClientUtils.kt create mode 100644 solr/licenses/firacode-OFL.txt diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 72f85e74f0f..e2bfeac65b8 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -32,7 +32,9 @@ openapiGenerator = { id = "org.openapi.generator", version.ref = "openapi" } swagger3Core = { id = "io.swagger.core.v3.swagger-gradle-plugin", version.ref = "swagger3" } [libraries] - +# TODO Remove dependency once https://github.com/JetBrains/compose-multiplatform/issues/2404 is resolved +# Track also releases in https://developer.android.com/jetpack/androidx/releases/compose-material3 +chrisbanes-material3-windowSizeClass = { group = "dev.chrisbanes.material3", name = "material3-window-size-class-multiplatform", version = "0.5.0" } decompose-decompose = { group = "com.arkivanov.decompose", name = "decompose", version.ref = "decompose" } decompose-extensions-compose = { group = "com.arkivanov.decompose", name = "extensions-compose", version.ref = "decompose" } essenty-lifecycle = { group = "com.arkivanov.essenty", name = "lifecycle", version.ref = "essenty" } @@ -45,9 +47,14 @@ kotlin-test = { group = "org.jetbrains.kotlin", name = "kotlin-test", version.re kotlinx-datetime = { group = "org.jetbrains.kotlinx", name = "kotlinx-datetime", version.ref = "kotlinx-datetime" } kotlinx-serialization-core = { group = "org.jetbrains.kotlinx", name = "kotlinx-serialization-core", version.ref = "kotlinx-serialization" } kotlinx-serialization-json = { group = "org.jetbrains.kotlinx", name = "kotlinx-serialization-json", version.ref = "kotlinx-serialization" } +kotlinx-coroutines-core = { group = "org.jetbrains.kotlinx", name = "kotlinx-coroutines-core", version.ref = "kotlinx-coroutines" } +kotlinx-coroutines-js = { group = "org.jetbrains.kotlinx", name = "kotlinx-coroutines-js", version.ref = "kotlinx-coroutines" } +kotlinx-coroutines-swing = { group = "org.jetbrains.kotlinx", name = "kotlinx-coroutines-swing", version.ref = "kotlinx-coroutines" } ktor-client-core = { group = "io.ktor", name = "ktor-client-core", version.ref = "ktor" } ktor-client-cio = { group = "io.ktor", name = "ktor-client-cio", version.ref = "ktor" } ktor-client-js = { group = "io.ktor", name = "ktor-client-js", version.ref = "ktor" } +ktor-client-contentNegotiation = { group = "io.ktor", name = "ktor-client-content-negotiation", version.ref = "ktor" } +ktor-client-serialization-json = { group = "io.ktor", name = "ktor-serialization-kotlinx-json", version.ref = "ktor" } mvikotlin-extensions-coroutines = { group = "com.arkivanov.mvikotlin", name = "mvikotlin-extensions-coroutines", version.ref = "mvikotlin" } mvikotlin-logging = { group = "com.arkivanov.mvikotlin", name = "mvikotlin-logging", version.ref = "mvikotlin" } mvikotlin-main = { group = "com.arkivanov.mvikotlin", name = "mvikotlin-main", version.ref = "mvikotlin" } diff --git a/solr/compose-ui/build.gradle.kts b/solr/compose-ui/build.gradle.kts index 0722d887574..cbd3a7538d8 100644 --- a/solr/compose-ui/build.gradle.kts +++ b/solr/compose-ui/build.gradle.kts @@ -71,15 +71,21 @@ kotlin { implementation(compose.components.uiToolingPreview) implementation(compose.materialIconsExtended) + implementation(libs.kotlinx.coroutines.core) implementation(libs.kotlinx.datetime) implementation(libs.decompose.decompose) implementation(libs.essenty.lifecycle) implementation(libs.decompose.extensions.compose) + implementation(libs.mvikotlin.extensions.coroutines) implementation(libs.mvikotlin.mvikotlin) implementation(libs.mvikotlin.main) implementation(libs.mvikotlin.logging) + implementation(libs.chrisbanes.material3.windowSizeClass) + implementation(libs.ktor.client.core) + implementation(libs.ktor.client.contentNegotiation) + implementation(libs.ktor.client.serialization.json) implementation(libs.oshai.logging) implementation(libs.slf4j.api) @@ -96,12 +102,14 @@ kotlin { dependencies { implementation(compose.desktop.currentOs) implementation(libs.ktor.client.cio) + implementation(libs.kotlinx.coroutines.swing) } } val wasmJsMain by getting { dependencies { implementation(libs.ktor.client.js) + implementation(libs.kotlinx.coroutines.js) } } } diff --git a/solr/compose-ui/src/commonMain/composeResources/font/firacode-variable.ttf b/solr/compose-ui/src/commonMain/composeResources/font/firacode-variable.ttf new file mode 100644 index 0000000000000000000000000000000000000000..5655ed51458712ec48319bb13356fa691a9d0334 GIT binary patch literal 259308 zcmc$n2Ut{B+pgEzZ76~u9m@b^>|L?M*fn;s zCb1-H#MoOjQDciT=Xv*wVsD`V0(kyW?qo6+lN;5lZc9TnGc(42L@A}3 zz(1|ygmuVU6aEIxVnQlREHnFO_%q;7h>5KmJHBO~>L@=9{ zqv_bWcu8?{~V_LB@O^GFIeB z?>% znO7KVzB;vEm(=dsR7PmA51o!rP#~%We1V|9JgWblhSXz?VH;tz^gHdLh&PV z+cB91B&Bvwqmce-{rXT;diQR+U(}{wJ#j@2y?s;y+=c>7QFib$sGTX#l<5eaE>v2} zDo6t{a*lTPh?JOejY*FS@mGIJ%;Zfq)Q@dY4<>N3ScJ{&(&W1dj4jH$h_Zau4oG4` zxzt7%r{X{l|g zYpHJuw?tSPSsGiKT3T4*E$u8FEnO_#E&VM6E$Nn_Y$lt{7P9;7S02fuc?@sEyRs%I z8>ME996fpZS92F+uiLbB$L>8xkL8}d@Y9v6H}Bkg_~`MIXMenS`TDJ_**g|+F6dgw z&E3n#w{Vf7#f*ODz*42lmaAN)T8-LuBbvsxZr?GfYj@F5eNu3}14U3t0k|aXhW0zA zh?~JpUplh(M0;v*M@&QHDFI5c(zupo9dS)$b8wx@KeNxif6< z!ZG=|J9o#`lY3$ae0eRn>+nci8}dfDHsP&tZOc30n#dDzP2wrIrt&mg2l9cqrt@@M zhwzcOj^?PB&*Q6bUBlPnx}I;xbtgv~_!)i&*L(avt`GSmTz}`k~M9ETyb@iFmO^ysU)tYrE0i_N)2$0kn%AbN zTvsV*iSmQ;1FnB4f8hE`dBwQqs-b)>NJIHrNe$&|p;{=eHMN?!*4FCaT34%wYXc3| z&>CtjaE;Moa81yXaP5jsk83F!tfBSQ`r&#-yMpTt?J1MB=h}0|F;?!_JiHCwaQhle zxCR&ka1Am9VHEIVNc?M(nG7;j`fx@tZw@c+>XpFb+CpP_`vPNO}w@>+?iG44pz4dR@Y0b+ZDU^ zBdgm7tL&<9qh|%!_f|K5p9Z_hyS`xb3a}&AGz#21t!@?Ntg*T^>?BL9ZUf4hZFSqd z?<2QoCfq%A8={THSiIHk2zO1Z8~tLwR<{#ej76{>tREIheb$F{W?iso>cQ0;?!U*x zAU+xC|2ahyr09$k1CZ|T`CB434Y4Vx@6)l}kh3>p`>~d2MKW9|?`r$F_7Cg&u;kXL zr3dTAx}&a-Yiazq7}L9+Q~ETP%0gKP{`F@`XhjeB)8GyUJ7*LrQONn``jKI&5<>x3)SJqUhkhY4X+ zZ(Y_xcc;N7Cf%O@xAw8ww7=D=X}XpAvtDd4TA7Sm>+4qPhj3vfnuq<+ce*B`HC-6> zGhDY5SuPdnx*$LGTg(sYcU=~#r)!GXUV1O62hEYD5Bz=f@&>+}4JO>L$XqB5V6R)sHegpg%+9ixT;UOXFdxgm;Pd$^zLj6Yt+ALCB-N3kr8p@;>Lm@7 zMoN>VS<+Hzhx9~xE8EF#axuAz949Bp>GA@3mApmXD<7B7$$9d9`MJUsesorV}wVgUuoue*OH>x|;!|GY}vKFY7(`slL+Dh$=!O2j~ zP~Xth(AKcfu-dTIu+NZdIB!?TF3_%yU9?@CU4q>xyD4_F?UveYu-jpG$nK2YCA(X8 zzu7DHX8W@C)$HrrH?>c;A7ekwey;s;`yBft_TSlGvA<*g)IQ(A-of3$=#b#h%VD6y zNQcP|vmBNbTD_*U?g-X@U3xvkROlaH+tp0>2gb z(@Ar3bt>Xi+-a!Oa_0ihUe0Fc5a&?m4$c#uzjEH?{GIa^=R3|%oZl9-E9h3RO~Iss zeG3jPxT@fxf@cdpDEQpP)up^kEtiHau`UTNlU)wF+;Ms0TE?}iYdzP#u0vf{xo&aY z>w4VvoNJ!zeb+w<)hHBEs70X_g)X@jbZg+&&uy4nrrQj+^KRGN9=JWn$*O>RTlWn2 zP40W#kGr3Df8il{IC*$`__1NIC!{d<0bx*~!pr@~A zpl3PH2+tOt?L51A_V*m_Il*&==OWMjp0~XUc~!u_HeLx{%e{W}_Vcdq-N<{O_i*oN z-gCV-dq47i?!$cw_*C*4;xpH0xlfMIQ{RHVzP`15!+o3h#`$*lP4!Lp&G237yTSK? z@6*CQg)0?qQaH8n#KKz&=M}LlQm062k@O-Pid-*pzsMg&-WClknpAXh(S5}ni&ZT) zsMy?Mxy9ZXYZ#{*XBrn84;jyzd`*>115K+;TTDOsF+YF5dVZb##`qodyJoIz9&OGx zuQDGq|L*VYALT#Df1ZDCfNwxxK-qw50cinC0?r0J3G@qW9oQ)_IdDK=M&ORXLxE=k zF9o><6$vUHR3WHW(7>RPL6d`K1uY3$A9O6}hvN3d8x(I@d{FU2CA1P%OAIctrNpih zzm=>~GNt75l0TMmFIA*eK&hxwvr1hlZCAQ->7>#-%h;8vT&7l;@nsH`IaemH%!{(+ z%2q2|ziiX81IunJd!g(vWgiBY3vL|TI(TsK;@};@-v*xxz7l*h_(iZK#33Xpq*ut4 zkToF(LvCZM3M$vU+^}+6%H1mWYk6b&7UkQP?_9oj`Ly!u%3rMDQo*}IRE4n>R#iAt zkyi|>IKJYvinA*2u6VSPQ>DO4T`SG5w6s!grAL+BD_5%=U-|ROvnyY$5>%y6mC03> zS2cHScQv)jCw0RBcDK%he6lt5_7MdBlBy@e~wHk$Mgw=?ukzM0TP3M};Yfh-S zyXMncm1^~>wYb);+O=y()NWckt@gKd)H=a+dexaz=U!Naunu8e!&1Tqh7AwluNP9UM!m>-G4(pu z>s4=1y;1e1)XT2-ZN205rTW$Cx2Zp<{@nVf>%V9qH*jtc(V%IAkqss^*wx@zgYyl3 zY4B@xMT8Zxfyro)SJdd`$SX@VVj3!*jxSg&zt3KKyF<{qW}z zQiOAaZ$wZ;g^1b_(Gjg8Iz^;J42c*QF+E~o#F~h05eFhpM_h`y9q}Y0Khh!6GtwLx z92puJ5!o`bLuAj$fsvykr$o+U7klsM}FbqVgL$H1up}ZW!D!v|&WUi4A{fm>(S- zJt6v7^z%j)8^turXtb`;)<)+VmuOtBamU7AG(OoxZc?sEnC&bfn(kCwQtt5*@9+2H#an|*}Px#BQ1Pev}uvu z;(5!8Er+#S+j2|GT`do`d=L{DQ!b`POhinJn07JUV*14li^+`nGG<}S>X@xD`(jST zT#mUH^CDJ_b&K_j4T-H4+bFheZ0FcMu|s0V#%9INi(L`BDRy`4(b(@}e~!Hy`!qH` z&OXjP&KOrJu1Z{ZTx?uYT)()HaanPT;x@$Xi8~p0Iqr7c?{RNh8Cn%;RkT%!Rux;- zZq=|=Y^#o~dbZl!>Q(DDt&>`(v>x1gOzUZ_=eAznI;Zun)<;@@*ZNB9JFTCze%r>b zja!>yZA!MO)TU0G=r(a}mbdw%ZM(MJ+V*QZtZio7FWW9`ySnYxw)@)VwmskWm$tvP zwZuEe7mY6yUn4#`zHNN>_(AdG;-|*Xj9(kS?KAdS=x3ci8~54Xb`I^L+x2X>tli#r z58Ib--=zJh_Q%>^>JZW)xx)&a896&ZRnc?fi8Y-!9QzmUg+@wO-eaUEg+V z)@@(+!rilb`1TmsV|tH`JudW=dsgq+rstrZTY5h3`LdTsuj;)bdJXS2x!1g28+x7U zZQt9qx6dd3mFQiycgNn{d-v@)-< zB;QPanEWjHjrf;hpW>O~pAwQ%HKjpH!x-}9i2KebwldUef|5^>N}?I%D!9s9`2|0 zbL-c!--LcM`>pJk-@kJIdi|UApV@y)|BGqgGUbDGx)_2_aWtnG#!#Q zWYv(&G-Aq#uSe`1adgD>5x-{GWw>Qj$Y_?)HDgM~ z@{IKvdooUET+FzZ@#o0Ek!?p#9=UJilTn_d>W}I(>dR5jENhwX3UGRPGh~t))^Z;HhpZy*x6&h9(#HmA6I8wlX2a~jUG33 z+?;XC#ItKTP{&+T&?&vmCR0vVyWIW!1}Sp4B0%ch-=s z%&eJN%d$3S?a%ry>sHqDFAQIJd{O#~n$!Ew`01-hGYifPpZWRB)iW>7QfF0~6+J6q z*2GyyXREX8&(4^gJ11aHhdE>Bte%rQ=fPY)*K2Osx%K9@oZD;eq`7nEuAIAj?ss#4 znfqj(G|z2bnR#{QwVc;wUi!ST^S+$7cHZH6m*zd5?=nANe(m{fFm1=opFjWW`DfztfY3kB1mo8qq zd+Co$Z!dkl%yC(egzu+H-aF)jijgT@$sY=bA}t zwyZh7CVy@5wXN44T33Eu=DN%4UDmf=KXU!P^*7f)+hDh$$cEw@s%)6G;l@V3vCGCi zIgU9sa(d=0&)Jf5Y?HL9@TNMO25maF>B^>GH<#L+w0Y3xahvCE-mv+==Df{Mw-~k* z-V(C4?$+j8J8wb64LBDSS|Q|+7BZ#sT6 z@|(BYL$=r6-g0~5_5s^xZr`+h|MoN6uWtW!2jAhbqvVcCJEC^9+|h1FuN_15f9H1w z>|DHa+s=bKFYfBGtN*THyC&|MyX)Is*LS_y-Ff%;-Cys%vir9^j(dXl#O%r3b9~RA zdu#2D+}m<*`@NZaAMfkBZ}Pqa`%dn=yYI=qxBCtIz4!a?ue(2GfBLuDx9z`Oc%bZo zMh99SNI1~rK)(Y^4(vH_^uWD?4hM|~OCD@+u-U<02L~RUba2tZEeDStynLwiq4-0y z51l&n^sxDGyThXne{=Zy;rt^3M}m)3KT`illOt`8BppdUl73{=k;zA99a(bZz>$+j z%N?D0tiZ93$3`C8bnNPJm*d{YO~*?ek2oH4Jn?wy@$};v$EO`%cznh2oySide{lTi z@jr9rT-V$pxq-RmavSBwj+}vMspPewA2t3i^#Gn&nPpmz0=ET(# zw@*Ai@$#hMq~}TF$%-c98evfq8GydC6*T`*MRg-K@zz25k2Am6l)P4{|S~N?B5cG zw6OEvXo|3UpI`~XK7_`S`cHkOHd5Sze~0B6<^*7u!Qp>k4#H=GE?^DF`Ij6)y4jzA z>M9GMT>H<^ocb^gJA-^S?!iq^d71w}e``FYL0x)Ua@$w|_rJuF|53h==g2>e_j%-7 z_X%um_%}Kk`AdI-(Fnu3_!}RuFB)5_hx$tGr1%rUwz@sZezc!ZpAh~c1$qJGB28N; z?J+k1_70AA*dUvJxIeIBNYfg8ydJ46A{c~Q<9i9!*B#AaT1QbJEV09Z(+XQ%8^hXg+QRMF6#{zLlcTufRcI z>zl1F)Lx1|4CaGSK<#S=Z2hsVU+N3lm-=Jt6Q!lSk)SqH`4m>os7JQ_RQb{WthKy6C}uAnNI3tT`lpgr9Wi~+&G6Hq=6 zKx0B}IcBwO6}Ztx8cz%A)$cWwpT>yxBicKjAil+W^nT?a+y<2~41BmIPQZWL3iYRx zHGYLvDJ_k`7r?d_>cTx5><2Vo`dC3)?glsYnbK4HSAnH~$^f?gMqd{+FQ`330l8@$ zs9fqxEEoYQ1Da3EtV->gU`2vr4e9q>%1dS0`qCb5nv36pQ{XJ94L%39{)~s4pgL*( z&^|(ax&o+Q-c~Z9WV?r;8z7tf0w^uDeStvV>&e#CM#5(ANpMph!WKtL?XcOD6y?$Q z>9)&;l3l57bdT@?K7i&ADYb*r*aKQyT>#A?niFJqDxc;e=Dy_*DD{02Kp!lyljRZI zZ2|2k%K_Q%C)7`Q;MUgxtr6Rtr#18|XaK^k;VYrNgj?Td$PV$K9-uZh1w{a*L7B8) zSWuS*V`ljgU>;e{BaX_ZJk%x{cUzs9JDk=6m0Jhg0Vvg)-U!91`9gaT`vEzQUJPkAgak@u>SlYbO^2Vf7225tlD8|J8GBEoTB%!iHh=KzdN zKIU+KCB#h!WNY;AzotEoG#7y#^5%oR0RDXRKff))VGFXOZ9mr2euX&nH9sAoE&02V zhQ=CmQjfX|Jx%7O9U7L+d0UBId6fj_4W^kV*K;b*8DD@GvcVM4M>l2{##mo z-kw6*ZeS*$IZES)^7Xkn8F~Pu0Q8MD1U~?px6a@M_{r*T1HA=k+(&`W0F5D)VT0mr zP#F|YYlrHkI;rkb;4C1!9kwc^#kg=6=swT{j0fw%VnFN32*v_x6XiQ&Ra(y#K_@_U z{cl5k`A<+k|F^K&`G2Zp=l=xRmavWC|5Rz*|CiucU&OoeX?!)5Me`;JkYerV z_bj@P(474o(0;uMkJG_#OT%}- zeb>q@l(!2|*f#>QjSkw(-+m(8+U_^|m7JG8O3s@YfVup34s;!W4c`8tZ?L(i_b47bxd#L4nQQmWSwb?noB$$izG|!{JZ{Q0s9i)S$pcA0HJ&}&q zH|DiIhcW&VY^Fam(EX6Wy`EJ^d=MBS(9gGvt?}ps-47&tYhH{$mGKS}@(i;=by>^P z_aoSW%GS#xB|p_kd)jN{aS;0MJdOFph&uq|N@?`_HO)8)j=Ee zJ+mtGCqV6>x{m*~t$P1ILpWguCD0Cxoz6k{sht=Xy?rhsFULI4^X*4CLFH09TUts_ zG_oq$ZXvL>fozC4z3r3W#=6#Rz@YyC?NO{Fs3G)k{)s4$(olaXO{f*jVcp#gzZpH# zK7s!ZKkA_K**h%-|JTBA3)A<+`^Zz{A6WFM@b~5ZQ$PM~xYS0;QG7+4$o;8&e+j2K zVY40C_dlTL`w#K|l$Y}TEidLSFY>-Va!Yms{hosP`Jqyr&Htg>7DmduzfWTer?eDq z!xsLjv>(P%KH|f4|J1*a!>KRC$Kn4kep}l}sZAfY%NF-xd+GD=kJEjeht?8>QNDjl z|KG~6)%_R6ny~Byv^LNVDxa{Wp?Ym$AI4K%wlx1%DbJ_!QJC~Wogb#5@DJn2tv`o0 zwJNQLt^b9Zi2nfY2|wL8aR1Yxb#)dj0qy{Mi~ii=1NQ)s1aR-y??XMIB|!#2I>`+D z;64D3SixSyqO727%g@4AtQ^8#0*bF?h1zd(Th-DD^;4N`{|-mp1bcuoFTjoaJdF$O z3zh_&5AF)3&*kWOTi+*XY-yZvkFgv=9&7!2UaFJ)fK%U5?mPV9wsFns9t&Ln^1;u5 z+E38FPhfoX`^qrr5Zw3C*0;Za8)zH)^%8da<3}aub#a8PLOksACK_iCl=tWD_veJS zN8v_UFLo2Qw07j!6XSDSPXa(>a7!EQ4<}inSbZAYH4RDU) zus_cLD_}n-=mQW8$Zmr{e^3bGW72J(`|h3+kPimcoLD^hoKB>)^qISrEQih97(bjlOq8 zU$T*tQt?eXb8=$8UaUxRujF3%?h=ekF?tFrpHPbIW*68D)TQBD3iQne`c_dY!&f@+ zd%gvj?Dde@IpZ4_QkvGEId~O99>)yIE8}Y+kMYGF7knWq9z~r7k1Dl@dYBX zhW?$c!l!*^GpVoxDHW<6 z=EvxDQGNds?@K6$$o1Z-ljEK3{V`eItiY*>;q`*sQ;8lZy&{#`Uu~T{I+<^PH%!0Zt3;f>)EH!<8FFg z^2+tv@3jr-K4#q~!j^c=_QG!XF;tcf%;%O~nALwF?IXV}z9+)1cr&jAqVQ(qZ|)WG zDJZV+60b1AtBO|{n_E|k`v5QVU;Tx#s|!Rp>hjj>a`sZZKEU&}=Wn0nw&xYkk9c3E zDBBBngpb4C`~TXWzqapvK3f@o8xM@5t)J9Bibt-NWIxaEVK4MS>=9zlcpmWFY{O@i zm-k=RIOde+D$j+s`Djzm83+e9|KF76B-VuIM5F_@c+U*c7Mq{iWpmq<<}kTEt#g{( zv=7+g^)@2xz5l)26W?gIg?qL`84;k0XOJxq^~Kh1&mx|MY~i|E+iY8Jq8u-8YBOOg z_pb_jQCszR>)uQID)vcFJA?y0{u4IT!_h~ZjdZ2DFdh`=@zUe2$5oGW=b=`pGTx8zn8bZPcYP#F6 z+1#{;2)CH4w)NvNoW|ZG&6bYF-sZL`%~x`Jbhge}+7B>qY0t2w5#@PDdBndDv&HFo zn^V1B-X0OCttQGU1B!SQ(!69BKz#&mGu+#R&B#qqd)(K7CDd+8Bkbco8*#9|Sm*ESx9yYf z>-$uH#oi>+*y7)pVe6mXR(%c89DP5>Xr9u&EU#*!#(M*;qFuQ zJ%!E($ZJESqd1iJw>&flVUIEHLu~0`6>s-cgjunLe@flsebU{dK_w6X+=1eg?)D5^ z{nRb_0a8CKOSlUqAiO!i zo>r&|2m+q((-qPRw{(329)c_2q_DYdKO=SB?LO6Yo$C_U>CjQ2ALs;Hf_gMgHe9Q@ z?gr~zgI%XXM}dBz6KDzQfdE%uu@xI&Ydn2hWjmsgI zoi1x!eO}zF!axBaxoQQUfVv1k47RARWYlXzwVRC+~3%bFKo)fZbp-SOR8) zOpp#@K{PNshw1wYJ^x^Ta`tw1rq%S`?W{OGbGq+zlja5X=+3l{Gv;&&V4ruwKJSEg zZ#ZEucUlEzgQrcl1$0fJ2US6Rt#rxl4E%gw#gu3IA{&>R1d1}uKW2}j)m0OaJAD$)5A1ei}bc@D5sEKzLyqY=qWWv%xbjmoD_i;hoCB0u;e!g9H>Vhe zS5Pps9@C3TWAuKP+PZ(37GfXD)*B%-DrntIPi`VBx z9X+Oy=I@xT&zK76DSh_BShOBo#EddTn?w z5ev}cee@RMa}HKt_m|c}><;K9N0OhX=;;FxUqkm_(E`*XdK(a9w@OdhNYA+-f4G)y zhxb)TD-~bn;P4W8jCxEJHN|1Of#zE$#n<7g1Kw95Re@`n!#UL8iB~8Agf&xq4PzYk z!_^I+J0<90gB4#pI|o=yibjV=>0!kYR?LCs`0x2yhWirUTOmEp&vHnUvYBj|r>0m( z-H?G&Er--zm}lG2V;}P8_f@-KX5*D1qIH&7HC68giq_L_vHCgF^z`5B>DM8BLGnxO z@iLgkNGx0O^_t9Z+ffXQR+CXOb`opOw-hfGLCzu+|Msa~QYZL}k>9fTT}^s^%Skmw zY9rGdJgVs>;pH#Pg;M7C*K?MDzo?$G)w`U9b^rQzerG-XNwo_fMJv(roZ2AM9#Vi} zSQEWu1%8G6mMlGZuyNtJz8SZ+_=@(9`Q9hBeE@erI{0*H7zJw9HrcQ~4fx`aM)W%SC(? z`7Mjyl_zYbz4Pn)vn5DRKNtC3DZSpmZ4AHN%u=Xih8N&4cZ!kjU|pu^{n7obKl&^B zR}S%<`Re)Skj=4Aapp#TOHaN0P{vre9^d3${i^O?^3Koo^v982lv)aYe8Q-wx=FUh z9*h#n&mGVwhp|CP_6^2;ISm>yG3?V#>evH$Uv z@RPk5tD8Y-^7TB2;IFRx8>t;+7nSayNeC+j;6fUAH5<9t!7p;_>qeIK+~W|c?-%@) z;T!8%*ULa4bH-JcYU!yG;1ALLRn-pCI+gb2hH5A24Z>w99APOc-rytkMrx*3fNLmP zT|zAZS2I{j*rF|BH>>VwOK;>8ZSmDhJxH}EuMw)xX2}cwOyxdu|B3}TlWO7DRd2i| zit1~M8Fo^4b;fT3Ojiyd_B7Hddf05mm%mmvAYGgM;i!8ZxoFnmokp_M1sbcT!+k~R zs*FQ$yzW1Tm;<`YOFf7=Li1YR{iUvmS*6EZMcH?imMEtkX6s8@zfwEQx~QtyEl5%ylvPd9;Oc=i?s~c&dd=x@>$`+R^HjtH z=rORazUOj@EWxE5g=SG3z4Ur;B~uIJ&4|*rv~BVxpTaslO($nyFwE$xIqUAm6aXT3{l%Ane2Acje_ z{-?f+(eHE8XuXUL2=&)fl6A?B7#}@m2Ha)zn990;4E#a5eh`z2FV+@58Iz@a{gm+KmU(tKE22dbJx5rB}Q0aC)^H!tiQ0 z-k4tPhPT_{)o#2!z1j`&c(ohvNUwI|-RRYBd^o+@jZdamyYZ=fC*Q;8@_qaiUq~-_ zLnvPG#*feo-uN;8lw0@-Ns<))BfZ*)ozvfYpJSKO;YIv zZ;}Boc>6;tB)!1D1JWxgUph!Hdy|gS%ig41dfA)Ym|pfKH&yVOH@O+T=1p!+uX&SO zD0t1A+>&1NCdbfg-sD)k<}FB$qgT7ht>`6fa%*}$o7{$8%qF*`7qiLn^kOzSkzULu zcVcd^^;WRVs^p$w_1nU1N^!&(kOn$qtl~ke9?n@)yx#5t+<4l;RhC-gN^w{dw62hr zSCr~42p#zWl+poZ50v%^ApZg_E6}YI3^$OkK|=)cBPi~SjNZeV1tp8)|J&v3(3%3} z5VV#+`4(DRpkN1Pbp-MqXqZ5wcGb1Qp=6`_fb7)3iaRviiZ_&Yy+}ZIin2m|ZD@u1 z7j1>?(8x+PD2)|CZEpgaf-pe4EkWfrw}Kr8Z#ZLk*PM8piqAk1lmg|)lG~8oj?+x zJ-xG)InXXv7C@?a@RI=xJp)w3n5A(B4)KK$AfVI0pJyISWm-as^8L z?+31e{#I^4)2!Tw4zNOf9|*`!uR%H(Op6ddLj+udelAc{=um-H5lS`%xSKOJT%a6> zW(#o2U~I8Kz71U>z{@Wg-W{f+%z!Qv=$}6H*L(8@wr3Gf0-##Re7 ztQowOQHOg$*9w&K&~*YO7fN;qN@3^*0iNp_+bA$V^zp!$Xq0!8KsgHC47Om-kbA2@ zdjP8Fz<3J_6k-;NH+(0;K|!<^hn;LH7vc@1T1H@_8uD z40vAOP-+w52&kWgE1)??7y*qj;RDE~CqNN! z(h9ZzlocAU)8GssJJWn6JOK5FhydSPX$<|rN)(j(PecRiGtmNEu+j)hb_WXC<3}sa zpg&pZ1-)dY8}u@`0(yX-tqg|JnjvCAo|SvhYgQ&ff3Y$idfmzdD6KJK8n|g?BJ`G( zsnFY2vY>aY%!JbT5ws4dK4Kxb4;}zoLl3Rcoch%Y&BsUJG1v-zvoaU@yOlH0CsxRI zPpy#MpIIS$|6zsfMC*zmyT1@9`=Kwbkd0qip)y`uq5A&>ZvfT#R)8lEyx7|2xfr7L9oeC+zQ`#*V1=PpST@{PhXkEd zcu@iEi=4^@be5stStDrg8 zw?cci{=145keYRR6uv>(Dj=I>&K}1GMk*cmbW^ zxE0!K>D~PVo!fYO0qw7NCAbcq?|4T6?ZG@jK<7W6D4>0scM{M!jwcCdujS+ibk5^l z1hgOXt^zs(@@@j!uX%R?oy&L+0qvK(r-06JyqAFXS^8XvptB*TI6(V1PZ7{rk6WQV zm{Ylc&W60Nfc9_RPe5lx-d{lbH%}AL8BqV--2uq^7Vd!pI_vR4R%B?pfX;n9$+5y-X(0l(C$GC3be;iH{g!&-=IODINVR5*z@Ena6g0A z6W}+0nH(-KAdigsMd+XDVvfl`dJ4rHBk2EjWXv%_qH@vz=9Pwi(`Ueh)B%clMM#*R z@(?Ryp_n`JFoZvcVvZ2XDCh_QK2>7!7=gh9N_l|63p!39#X!dkl#$R(FcD?OLMIEP z*3hY78p7K^vjh^^8FNlvjPM%JrC>GOjiGD6TDaq(>%a!M$%Y#R5{+GsfIg{}HvyVA zXP~(PiN@lDKzay0DZu}9Gx?N2qH#PekZ8OpKajB3$Y;TKaAPjX--B~-cY&S<7Xapy zd{KZuHNa%dRYK|r#XKdXSI|oWDFKSPN=UDvn5%@82&FLt(x1?)0;v-;PawU4V$Bfr z89RMuK}c_*WEYwjG?!@}0I55a#+$%AmT8QEMs>arNIjr0tzdr3)K;`h>ItQGP@VRG z>VOTT-k2X)M+(QjV1`Npx{uN4ECiiz6eJ?({z=cP1l?EZ8I_*z>HevpT*U$IFsP$| z?wR;hS%=Oeij#oOFN(8(&I(FF0p0Tz7vP3+e4*~Z18x)46ZpU#0HruUXB~RxRQ%yC z1Esh?xT`?1HVHasC|IKeoj(++yCmG9P|A;X(V0S_{D96GN?8G&5tLvMg7AjWa-bsI zYoL_?+D?D7hd!TDP!Hb#k3%B`{1}w%g?e}{G#X$W zIOej_SimvIl_mmy4%!qnLz8GeQ4{s>BNT570OP$2w42fi_5U z9@-Yf!+jR|nSf&rDD4D%7qq>AZ-;ge@WW876M~q_Y@p!1ZHEa2Cn zDFQlMDSZU|1~gSbXDp?!fZv4n6VRDU=`Y~7plJd+e<=e5{5Eu;fX-pcAOXJvO&8F) zOc^ZTccBvnbf%}zbO^o!I$6M%L8l0$O3z)%;J-na23IUxxm6Zbi47y4{ zXHR9dfd2tqBcOArvR1&KL)QuDOscFGaO}JI-$5NZpDJWufZu#zN{)ces>&t-e+Atv zpmVFTMS$O&V#-zlone))1^iFwHUXVwm2U)e)>F0%=v=GN`~Y<3Q+5jIoU71U1#|{f zb_?i?tLza-47yi9XI^EWK;qE-;9KOS`F=nk$^7+y)2LlLazvT z2J~lv92=uvtPl3J=NJXJ91$-*>l|U*6eJ$YApnnP^BlL}cXF=Zz zBoj1Wz`uZ61d<n4<)r1;xB1q~cJ_MS{d5Hm4{+%2)+bL;{l`!P#OckmqN+zK&l8OTLbzW zK_&YF{uD|!1@wHck{tm(`>JF+z*j)YUO=h>B^v?05=wRf^t`K*EdXByrTzn{8kG7B z_-ZKi6G+t=emO=!&rtolU>ms-6gD*ug1Zqk9Snw> z>K_6=hr0_DHZl%_8+nWw0AnI!jv6z;G}J}$Szs2zL!q+)`YOS1%mynFjQWWQ>84`V3^uW8-$P17)J!#+_gn+=HOhe;`r4 zdjtk5f3JX^;0DU?4!sF(!TlNZwm|L%y(5r&L+^rnD4%S6A3T72 zJM^JIqH+5bJi_N8*msPN1%?19)*2xXhCUU@>Ck5ac?k5mfIgQoz7WWxp)bKJ)P=cX zd=1{fO}2k4Fa$yK1qNTnOa@?wdlK@Ru!ad`JhYHNfo)B00P{$JeN3JL8T~MM3Fvv) z!~SQ-Yp*O|Yp6{njuCOxSA)8Fn(EeS{1fo5~3k*xpnf zgd%T6Xaj+a@i#>a=rascsz5#rO#`r>jQM05BA|1P3GI&Pt|90y=A(CJX5Kz%&I+ML8V0PC(B|ri}u6elqP4(DRUKr+}WB zOnU_M%;YBtWYq14HWBo>m>CfI>-3U7SP$nZ;pV@D}Jj5bk6Y00b5Xx z8}zC`YY)ZxCA4~Gy zHdhwVGq<^lfSw7=Q386#GA9V=xy_s?pyy$8CxNm9+F3x)YUVBidWJKP63`jnJX%0! zdGi=B7VX&y9S6q4jWIN5f(dYc4V@^UX9Dvi0iFHLWJf^H5N51Ng3kWtWdh|Xl-dXA zEN@;RpwAf0D+TndY+fax=K%9+0X@^3*9hoY!Ms+WWJA{p=yL`0dI3ELn>PsPvj_7= z0X={FV~!D81*jy@Vxh7?3xg^GI?MX20<8-a^NY|rLoufbdJgmV7HA!yCINlM;O{4( z&mQ~(1av0$4-{y)m-z;l2W0ETGRb{4s|9GQDIrJ-_;64G>yK=ox|5mNA%3 zM@xcofHBj0LNQ(e3f$39j1i$VfocM+IMg7}LZNm7tt8Z5fIs=m0vrTd0@P8U^@A1= zXw9Kc0<8|zS)g@?VoxBnZcxkxLaPhK{y=Eq&_V(&66z+hGLEpT5YJ0Kx+u~6==Pog+URdX$r;MCGf|MSwJy?))i_LXnmoWtAy4A>L<|Z zLCpfKCe&Y`)qr9!2(1$|P@vU^1_`ue#t^Kd4uN942sIaqaU;~vp%^aQu)bF4eM?!r7#W)h`DJaH~P#;1uj)Zy|ig6@V^fwUWNT}aJodxPH zD8`Ubk3%trgxVkKDp2=9F^+_aeKio{NT|o47)L_IoC(Aj5*qab<4C9$D8`XcFF-Md zgqjA$I1(D!1LH`jZ=o1RLOln?coJ$l6yr%~)IW?Vq2@y|ri8j1it!{gvJ=LXP!B-O z0*&nLFHkQ*0|e?|CL$uO9(U?lac~;KeUuUqj4@RP=A7!5vT*9 zWd-ULXs|$i3Jnpcd!gk7>UL;(f%+U;L7?VAD+<)3&`JVz5VW#D{TW(Cpgx0E6=;}? zfz<@+pU~<8^#wFkpk9O45U4*uYYNl>&{_iZDzvsh{R3J@pwWB`6R5ADbp`4kXgz^O z^SZu3y$)?4P+vjA1?pvJgg|`)jTEQ{p-}=9!vY%$)R)j`f%*%ykwEK$k^fqEF)T%b;Ywh*Wzp)ElS=EGOeSb;hL8YfUkKwAma;n3CsbriIXK%D_? zD^S0L#tYO;=w||TEVP|K9RqDIP)9>MfR1RxIB0@EoeWI`oe(}0nj}y&pq)V%gnt3; zDo`guyMgWqp9bwAP$xor3e?%qUIKL%w6{Q=3QY#7SR)0XeFf?*D6M~>-h}oSs5hW# z0`(r0<`7VSgVK5c>aWm20`)F5U7((T4i>22Lx%{|Gtkck>JcdQ8L0Q6!vyN@P#OcE zo`lla0QEeS>;hDp`y&Btua<|>SOT>!lxzXiFeupzsCA%ZYoOMK()<7_tqHOVP-{ZT zra+}NlqFDU?$a1x%vG9qG!KAEYwjzs2=4mOY_JyYInZ@rJ=`hK4FWY8x>2BF3<5U` zREpmwP$_<=K&ANI0yPJ^U!ZP+(i#Bj7AV>ADBLvu#|3IfXs$r*4W;n_YD?&8ftmn4 zBT!pF&w?M2CKgJz1}e?*3*aK$v<`j(Sl?o95;<@C)2DXRiayBlT-2%`KpA zh0OxB+%TT-0yF)P#f-r7c5onk| zqqG<^Li2+r2sASk>xL9crXe#K7GoB-Ku|P%r#WB~5 zV@)U{pud6N(Pori{0X4GctO#Z;ug43erZ*pqCKTGU_iK$v0%(0LP2;i<{Y7*{pAV( zC%EkyyT*Ww&wNTkv%wO$%R+O&7P!%#eAGkG|IJ!D0rXMvz<-xl*P-8$;ZN~qK)|#p zrZ`W$+x?6D6yGiMS3;Hg%3w9bU3GUTHn!NpVo!|*V?m>bv8b`Q zF~nHaSjQM{Y+`I}Y-{|?*xuOD*v;6-ILtWSIL$cAxX8HDxY4*3f4TXL@dx8&<74A9 zW4_7GU}Xf9;-F#DQ|nM<3in4`>{%w5cr%p3jj zOyuu^zXa{)U&6n%f2RK=|MmW70)p^&pECnz1TG3(8@MrWbKthXoq@Xp_v0@?9}PT# zzXtt7;KjgOfe!+o2EGU?6l4mj8dNhVET~>kLQqmr*Pvd--HP`uzPR|k;!lfPN*jV} zlykZ!Ut4l*OTNXDg!el#*xba*u~3!`o4=8~Ve=iZ`4QOsM|`8q0XBD&gXGG(%~Rze z@)+2Bs{Dn#R9+)*l5^$Xr^J z$OSep7gYV7&ASBkgw0c7^Si}=EB>ss8XQ`#z%{IwYdNraCyPZHich5yV0k9x(=~q_ zR*1h+S@9+x;;zX*%O~Z1@^>=!MEc1;0oLTN#%d}Cup_*61tTf$@yN%xTm5nXzx3~T zquWjQ8@+E9xY7Bh8{BR;l5RTP`0PgfjkY)1z!i%x2+X_w?8chwmK&FEV9nFd4cyzr z&&{DX(K7nEvG-=qjn_9O-B@uW?nWH^#lejmdAOdxKK}Z!Ti9Q&_rKovmh<&qw;ZmI zxIXeab|%F3xPjGKH!cb7rTW<3~}JnSNQ8}g7h z?@ivTyq9^;@_x^IoVSeP^Tz1cy>NBA#`2!#-ORg@cP%e3??B%EynWYF^W3h?`+3@x zS&aRRJ&3U%-WD$zG$klQorKRqu(|M5Fj>MrEuWUp;rb(`f}WGF%8!IwT;<#HGa2Ke z*pZ*E3U+>_Hb8Hb&Gfk&b}sB}^z{7Se(0(C{g2j0OVD6rZL&5~+o_>9aOY~5w5#va z=wWD~c13qxv&GQ;;IBX0Ne%Z;N=f;(yWoug*Vp7SFoR@3pAE1x?al_+-cXG&v@>)t ztYHjq1;LNqPP)GTvD<8iQ-Iwz3b#A^KKxTIJ&p7#E-{Fu@j=I{=}d5L^hRWv6*Zc zTgVo(CF~ovnQdiXv$^=@(s}kB`+;4;-;3G*e>i&+_^gWSfB4Sax$}eoNk~FS!WKdV zjDUHbCr>sI$SNWtB5p{5kOUG4NzB5grHD$cbuU$_6j5=lQl->Vv=kAk3sq~awQ4O= z_XVwWK}3ANXXf1Jc@psb{Xb1U^V~aU&YW{*J!j6`JJ)%|`P})``ONvRkj_7ag5JE^ zah)rj1m_wj*;(hLIyXCM&Uz=s`MHzf-0BQ)HeiOo%gJ_bbA~u~I>Vg1oq^6KOmX)+ zdCq;#Naq1(g!3yW-}$w3qO-+`IFCAE=l9N7=QmEFv%?8G4?Cls?M|_?6S{eq^SCq4 zdBQoxdD0p0>~SVId!32SpPUNk8K=tmvs3BpbDnjoo#&is&flHWoEM!loR^&$&TGzj zFdr^(4mjsKZ#ow`Z#i?Ecby+N?>Muax1D7|okr(BPOEds zX?DJFTAZ((PUl-^rEr~#VIKsX)uNa4Baz_rac*#?JO6OzI`26R&Ov=Z@7Lezuk_J? z)ZgjD`fdG=eoud-Kh_8J2l_4jZ~dWuSHCZ3%m2zB$j|jZ^&4`I{KCCLeu+1!52-b> zEYLqNK%T8Gl{4iz@?3eoyg+^+XUPlYr}97YGx?tUSiUbmk_Y97@)KDvzr$PC4RV28 z=n7ZjJ?y!78+)ESENkUA5+^mtI{B?^bOZWz+2kh3MRKv*%T1Kca*1paxnelpDIX## zMFrk4ufdz=lSH|gEKU-mL`00oTgL;%ATe0vh+!g6oFGPsks@Cd;m!0?QGz$q$B7Ae zU;PwOh4v;eDpJJMLL!2r8C8mr0;w~{`v&Fx~O!1aDN4zc074P6J`FHU?{Cna=@q4jZ7K*#@w)#-F$eFw&lR7DdE!&NQU4z?UwnqQ>OU6^;tR1re2MqxzY>k&kZ2NLi$&tF zSS-E~&EkkyBEH4D_eVvW#5)I4z-H`_uIR*D^Ig&tOQjaeWI!y(`|~SgFDb=JnJ6xn zy~QQ6kNBbND^|%Q@gtcmR?8G|Dc-MNBU8m?GEH1A)5R6CzgR0X#E<0waiz=@KapAD zDw!>QDhEPq3=-GK!QxsuL|i9_itA;LxIqpRH_BY`GdWzWlX>Fj@&s{{93gJT8~f|! zDDextvww@s7q`lj#0EK9{8Ek)8|7GWn><-;k_F;+85DQOkhoKZMLpjCZ^a1!cgrGi zk1Q7V$`Wy(EOnMT-#H!55vR*J>Rci`SYhdIzI&2e2wUuQyxV^PPKIc37r0&SQa8gL z;AXj*ZnoRs9WGbMm2#O}E-wybxtHS&{!xM9Zi!p$mXhTxuaZBN>*UYnO@V=d!GWRf z8SV^upS)k*Bkv6i3Jk%U{*7*vyU1PaUg*wt7rM=`!5@{|VHN%+Ff5RZGXPe&%V7sD z!#M*F%dK*cd{XYksQ}q(s2ZdOt0C@3ux3tH1?nU!&`N7N_kGxf3hT>V!aR_oPo)FE|``buq5x2ea}Mzu}P)RVlyx@7+MwQ7@2Pk7Tz!GA z(~I0c&(I@vnLbgU4c*_ar|XHjQ7_cxx>}#AYjl;a)h&9eo}f?D&3c+XQ=g?5 z=!r*ZbCc$y=^_dq;8RO@g-@3hz~Kg--O2csq2!+oh%V4{xdWy7yn4 zaMilwyt!VpH^ZCfo#oB)&i5|xYQ6bh zowvYS=rwvxUcJ}g{nmTL`<=JVJKMY8`<3^A_n?>S4fh6kncgsOsF$OL(P|gE-28pF z0s0#zqm9LW14X#cbDoCo{S&m+gTjRdu7lRRUU<-`BcP+cbLw%TNC0~EeUShyHOgtg zsUp2$i##LxIM0f{A_;mn-#H|bar#I<=Omm!lIDyS>CQgU9~$&I*eK773^71tI%7nZ zGgf3fC$kj!npzOK>ix`PZ%1t(1}1_jKb5= zMIs*>_Z#Sy(PE5KjPp%S76l>*8|x(zf_2g8yez_^5IP6C1zNrg+NG5A3v~T>=R+~x zc~qR@oFXPT??B&>j;esps)ELE64kJ0nw>?Yy`ZO;U>!Lb`oG3Gippyxy#x#H186w` z8>kIh4ILl06OGC z=L~3&A2`#XKju1TLVMIgbJW4Ao9>*2IkW+~W1(n-WjMoGA(~(%Tmoxhkyz~9E}ESm z!iG89IS6~}9O#i2(dwLw6~Wui5pj`dhxK)y=)j3CU1BM$lT~7wv)Z{7*2QwM0_VD1 zEG~iFGE4jrUWp%x)v#S=J0FQlogHG0^8<02^RBpDTp`wqAB!u+PsCN?r#SWH8l3rZ zow#1y0E=`Z*3~}~>%`B+P2y&;9w)@yf)ipkh+pC?nA^lAal5!f+$lDTyTsk%9-JI= zUsR88fd(aAPMX@+=i8xScR)u!h7)CW;zXHU;&HKCJR$Z#XOpIX3c8*&{XXb<()Og& zUxbc-iFN!dM)$u4-TqJL^?yO9zX^T*Z|L&3p~v5a4yTi8K7_9R7<&2>=;;4IKmQl{ z`3vagub`K|hEDzl`uJPu;_q;TionS=IA;;((rBDYlK|bDD0|C3vad{%$r6XI;*^>+ znJ)Xw3^@S)g)Es3&(0t@SPqdxWsV#sbLDWECr^+g zLozH2WkeR4^KVLV3d=Y-UY;T+$cb{2ESD9sQdY@oStC!CljUi0iacFTm1oFl@=Q5h zo+W3A~G{Y`CIvj z{GHLmq>mqye~>%nALTCjIL`lh!fIi7%ASJX<{9~{+$aAmpOeqa7vx{$i}J7XCHXh` zvi!SzMgBv+DqoYY%YVu@<)21?l^b6dx|^3o#;+-%i)=-bgSSItZ`3uC%dP)Q;dCdhC9tY)1B^~<<4-=c4xZh zxaT^zy63s)8_S7on;*Dy+_~;Nx7MBS*17e@npzmOewy7SZj0OMwz(I%?QVzLX)LW} zuzgm*`nlM>#QmYW3O>ly?xi@}>oWMou5j17KQ<>XUFH51Ub1W8C%X>*$s61o-JiMZ z+@HHQxi`D(-Cwx3xVO3+++VsI-P_zv@L%2mZ`x+}F86Nt9`{~&Gw*kQ(#%xFS~ztUvdB8zUsc_z78+b8}7fb8h?{k%Ql{?|$HZ=zipWjCJ}a@bCS{{mlI@ydqz?U%Fqphup8-!|pfk5%*j7sQaCAj2-7H zr97;s16X^eW6hg^b!R44!r54B4#GOUmr7Kg zTB$C^O8QB&+J6M={`;^p-wFQ(PM}hks2{3T>PKp|x>T)Em#NFu6>6>evARP7We=L&p5@g-R0FRQ=9X8#B5=GTnf{D%6M z+OOWkdf?xRZ1Q*1yRe$yH+J+#u*?s_LjM#t`)9DwKZm9NC9Ly9IIHY1JVc+s^RXS? zjO*aV7z+Q!I(U8VfnR7d{6sgZZ`2X>tvaf{b2fMm{3gF}?(&4Q-jkl|DbK^|A^CVU^Jv>y5rg-_xgJo#v;t3wFcH4gS{bS8^S`&g{_$9o#2h|M&f+M z6TN)zByY4g#vALM>=k%HFXV;2LNDSKdBt7{?A0<@spDa-PJq=q3D#?cSLs!G)n1Kv zsyEp?&70z#?oIX1U_16K*sf=LGre=XbG`G7{W{CL(3|c30H-<5g;iT?tl4^4u?yIu zUF0o>#k<7Vzin6tv||m>3447hZ20Bg3al6|Ha7PvSmdi=ov(o=KTSyi$8k1uuj?SJ%QE2ld$Ulgq6zE zSkXKS+y2j3#XOHy&0k>g{}n5izhU+AcdRV_fz`@uSe^V6E0BL-E%GK-AOFT0;ccur z-o*;xeXI>W#2V;htcgCss^LFam;BfJ-1`D6nXj-q`5J4MZ?M++7VDqyw4;TV+SN*X zTI+yL(7kk`?(MHWbP7(vOVw#QUH8`+dVtQ?8(qZ@yBedGpC0NmxVf8j%pMsU$L_G=Xy$Y=4s<7&- z!MblUR(n&hHk^vp;WT|Fe4f4F!CMPo;8pPEU8bj#KTDtGtZ{bh8CW^a)aPIgdLCAy z7holNp`ML(@f@r(=jmEKU)Sk+-Jlofg;-fOnRREgUV>F+D^}GPVa?g0J9U>{s+Z~I zdWBx8FV>gnAL>>5M|!osRIkyO>C5#MdaeGkzEb~0U!{Kv|MWHbT78|qUf-Z^)IZbf z^v~h3zFDu=ztFenTlEJ0OTAIwrZ?%^^&R?7y;4)`J{Tsba|5iVuf2X(W-^1_ysD4cULGRRm)VuWKdbfT;@6k`{z4}l3Dg8A3;m^Xe z{b&80eqO(z|Ds>if7LJPzv-9t-}Ni{AMlpH29NhY^&9$M@b$e3kKe!H*Lxd&zIWm2 zdmmoD582=MiT+gohrZyYKi6Ntultogq`!tw@Ed&uKEk8=JNU;1JmhXb1-yU`1Of?x zUV+3w??9hG-#}6z86Mf!;nBPX-s4x`wS3L_Cp?X>!kfH5kP_$@NDZU~(%~)42n>Li zB@3q{4ul6~FnlOO137_Vf!x6GKwjX4z=*&|_+U;9bzPz;ZJX`n1HE-*fDN?<}@Vqj9BJW!#_=eIX3Z3vVvsjX{oZ3&dOE^KXSSR5#? zuC43pZ0KEC*VJCuwPZna!}7$+`qs|cy1IszPF+=33v684TWdRYwV|P_4KT4fiWaD5 zs@0Zi?^9#c0$nXl1;J1#@zf}~nmoU@z4zo8jy!FOKF!K^8dEyWQqre&HZ|8b^qvw! zwgkgPda99JPc_mov_ee<8$Hb?O^Zt^jJVY;3-y_XP2V#cyIL03ws$RQuI=g!oN1Z% zKC`2_wxiMJoxztl5|JW(wt@COyN5WTUI)1=&obE( zXGQBgsnS5kHn-L_PoH{vlC7a=^vv$5wwTdWOU;k!TH92$EO#w;rP>B7Yh6s7#JZ>e zy53ZYZZMg3gNY?JMAHKeOs;|Z(83rQ+qj`{;=(ApYNS5Y7{k#`hH$SYBj(H*r^}{A zfhMNe#J#D>RH|)`aB=TNvFw&bxVX<^e8;e%rMb4HzNt<(n-b~fxYi6;s%A)`TWn!l zYTH^nI@?>@8XI&=99m(K+kjSVwGH0dt-)KZRJ~i{x?8*D)E-A7Qmi{Hla3y8hJvN4 zle$@F9C}fhyIFTtZ3fs+A znrw+Hqs@|3XCQu8NwT#Rjkb1AwZ)63T55hYarxLKUCo_MZOtnZo5pt3Hh0c#Ze5nR zD0bT%y-ip)wxg}KuAyDGkL~Cv2qwq!j_qviSdh4EF8;?hH!ZBCN(vPe*ONS; z$X7d73xl>Y3k&#K>f;qMUc_Dt7+&D#FXHrKzM6TVpfFg<_*M2=QqJjoEvV#p1z-I* z;|Hr5&T@yCZ;1JZSniN7H{*v`-Vn7|@r%IT$kI@2#@`lU?2oavWy{&LP=Zu3X{`YvZWsBQ5 z9ZegH8|qfrmaSll6-=>$C8}Ub6_!%OZ@CJVtb!%0WXUSIM^ti8sN@!^maX$!iy+&B>un+g+j34Iq3iHS@{rl3SpXTdtB@xRP6t2uu)=db4c)ttYE^Ve|x8qQzC`D-|T4d<`n{53Xzgl&Nc+YXTen?J(3 zFv2=C!n!b0VDm=`IDgRckFX6A33C3RjwZ{dyfo49?`&;p?dZcCO(X#v%}p<2Xw#X#jWA6UNj!5&!$L+Pbl;v$ zW+XpunX=^&X3HVW7DJfzUYPY>nDt(m^Red8eC25<7!3^uBH`nHKPbu)7rrrYd7G^_|~34oatFR zB3M&mMkTHcw-zemoX_er#F>xPYlt%+UIEwG-Wja1dJ_R9CZNaoc2)`2Sc?u@OxNno zV2#zAxN?509}(yJ4|9I29|7n5w%-J6>}-WA*R!3)f;Cp};mYz^J%>2USIG1WnZC7y zf;G1P1Z%7v6|AxP5LeD;^*iD$hqb$a&*|14L!9|q%Q{$N^%|~RPOIM#XF05%L!A4W z)pwAG@$IaLIOAJOI9Ox#5Uz}8^%3Ge9+$72>6X`cwPq5UkNL%0NRyCP-_YDy8))Du zXeAO{O6)XKP!ml-i_H|&Y^ESPt}7~KOP5^U6lk^cklWtaYEvphUWb{CIx!h_@nqD7 ziKq?%QLmNek6uLAPA+ukPa6H=BQ}{ym`E~5eDw4lahrohGLb~X&EA@VTNEy=i6o$~ z=7wi1t0%&2VT6l|v&hBQ-qBFs+|^Rs2^SHj+Kv@V=C?KvzzV(dIPjruLTN>9)l&_i=u!@e${A ztN9V<{MIH!oaL~V8|ZPmwM{X1a=KkRBF^-z1&2A2`IU0H?J62@F1KAxBhKZvt7^o# z+;$C$xsmDEwGQIU$F6k{XSwX!262|lu4N!M$E_`mIhEtK-yzQOSzU}c%V+y1=2qr! z*DQ!Lf4gQuocY_e3i$DyZEbeUnVfDdOU$uM&#t`?XL@$chB)I#xL)j<1aQAU@|;-g z&&^yOYg>RHm&dNH5$Ez)ixzV+^S5gj#F@WcyCBZ|?HUGgrf=6WC?C(k#lDW=bUPj~ zmoq(U!(h&4es&FlIH%jS2;$7ou1OGQdUj0$dj2@D7Js<7JhiU21#@d{OUH`l=Gys9 zbseq8f@*bFuqt8|aVTg9J+4ORP|yw%T#Z7*)l@33oE|FdwX&hTbu9hZJMs)BMPbHK zn1D?Yd(*kB)w&Kl8(|Tf+g=M=yW07#X({7%G%dGy9hiGt>}^BS!p2UE*wVxVEhA!S zB%p~kRA46(TulSxYAO;})4;fzip14)99&IB;%X`oSJN?ZEwv@8Z)sg(iePT22y~NZ zi$J%w2=h@Ye~D|VQz>A-7pWjwLI({@i2JA!{AvS z=GO8sh=vE<*?M7PynvUS1?(IvsNj0B6BpdLTrYM)K%DEv4p_vwFIXce6tn{pS6i<^ zJ0KCa^%}GT5^-CvL2FbYUfv5G!^qp%$JD01@94b%CFJ`)rf3|o<*?49P(fjNa>MdE zm?ibC%UZ_P)pj)WyQr(7qqC{CB?{?N*NTPJSlV`LXzyLyf#0T%#bcZ6`nKV&wVplP zjAq^4DIE>4YD_*0=xf<9ZnDqBk4LFm?0%^6`7juo7Pk1*&6Wg5Qs&pzEsh5y#Q{1B ziqd1z&c>#?#pHS~O0eQ|)o~BEqp!d&7s3U0xq_>O7u%K&6ZG>Xc5K8n zEa)^9mTaQ!W@J$XCe6o|Nkc5zL}SS*6kpuX8Aa&FfEWr1Si^HAu3?kKQnb~R8c)N5 z(z;QxFrrgXP|kt}BZ&)|7Iw8a)MG2r)IqgfDuk-T<$b$a>QUcytw^5V+`DlFwvB9m z=)*)zS$j9MP;S0o620%m8PF&Aj@vOtmYXhhVOLXgbHkF>SOug-L9r?@XdT#Y1TNRJ zK{KEjT3l1mJP_X$6i>Cn%=M+iE=yK7P<%=Tr_^Fo%WlV+Z5dP7rt;@vW6OZj{Cj>@h%QblA_0-WhpP?eL$=vw$gWH_%)wn?dg9r^JdG z4~Z*&x?jHd>={v@e`Bbo`LVeC8UDO8*S|5SL;YA39KA8={iEq{N?|=?yG2?QYNsYs z$XG|18=E$Ircl?hZs zdXy;56uWy(rCL~gHKkZktd26`0CQvDbPJA6;fZYG5S zF77_80V(NTp|&Ry+-Rp_>j(-JSC{sxZE5Yq0BNcKb}CEN_D0)zaBi+ibIymnPs*2e@%sIun~VY;IlHR98!nv-INI*7iPB5V(oz$o}-uXm}os z8ZyLtr3H59Clt26QCw}Sg{{vNaVuq*J3`p{Oi?Pky^z4&@4Pw42XYwT>S?M(7h zElXQWuKZAxh;1C0>Am1egpe@LET-Sd%1e5og2=ZP?H7^0=txa1O`R)@nU>_wy==c5 z6T#jG+M2syF4XllSKHtF@F+B$Kbn`vg2~I4UHsrS$f*WmAI0IplZ3(%D~<+g+uK{0 zb=jU7EG%?9BvY_|^du3R(vUo^0cF zmUWsUa3J4}K+2jTfS%iTUS5DN2T5Vnr2P=)QFxY~Rb z*1-pQc19|;4n@QZ4V_}^NJQMO?~1MC0db!DtP>q^+hL2XqY-gCi4@yS8N}^OSX@(+ zJRi@5EuKNkkaDUq!zaS)_Xw}wBPHQpR9O{x+HNsp*bW@w6?~+m*qd)t+v2dS11%J> zn<}_kz7cG?G%sL$4Acns;0O=62&Rel&bai_2-cUi_3gDSol{$vHMCDfyQX%7m=Z*h z&S^szBBXpDDGDiXsgIKI?@i_*--~LJk4wo=wUrk~_N3!cIu_OBiT&)WyVttN?+esy2eUpgW zE*r7F@KA)iXoS0Hgu7^jyJ*Dji-B!*ucnrz@tp0B5-3{T5wTvvP{eu(0k@quV!iZ; zb0@OidQh~3A!5C;p-6c(R;*Y6*0)0=*xt&E*$Atnh+VaZ_@NkF?RevdVnPwS2^Qjq zS`fG6FJd?S0Oz=M+=uufolwL&EOE8-M1=h?5%$YOtOGL?v5r+-xf1Q>7UEn~yXl2E z7nS`zk%%4F5%%{)?B*8uaTQp{De`f7>?Rk|nUCERL!9Ne4piXVc`CwwqKI|)0?v(Y zH_ec*yqB%o`K`;jW`l#5H8yoNoQ*!;-f&)1XXA`kGVbatTiaWpUl@z&u!f4T`irpo zi?F#6VRIwG^KXRpRfN@Mgy+`?&#w`lUn6!i5M8Dsr-wAraeo%iA3YJGlYx>Oo^y zV20WEVZ?^6kCEKj-c-A=t8FGOa7OSDt0?M2Z~{bCPo%P-uMcdeSvX*_HZK@pCgvDv zpOl5ig!17T20vPw?%-%G_+Z;CcHaWspS!EwM?rVyZfBps2u19^0=m7mlOlG12XXE; zY{N$Ez76oXyV*Tn#5o^ZhY`Ck0>0cW?A|{3@|?r&&IlXq{DcY8d4^znjGsgSocXbP zG{O!lexf84u}{Z>ALH45HOR&E?4CTz!}8dD62z_b7Gaw`V)w)`9dLcwy>rmvVQKeU zz>n$J{Vl|~Tz2mp_*}p2-i@&PH)8iKP#&w!`Pn|?=i$xf13v=@I4faxGDhsPXONre z+kGa;>&ICR-g1c8J$lH)(}CSb0zUJ%`)jB-E}wli5OJ2r?)3wo>(xHvfOPH`cK;4> zmecM_K|Y^8PgC~U0>BxMw>TnpZywVQ%WwDQQEr>Bh^Or$?vF*>kBjU+VyKAwcahzf zL)^Ao5%<3$p4N-FeT%rhinu&Q;nH3mOPXLr!q0+5#?olS?dWRJ3-E-0bAzHE57upc zgQ{!pn(s9>z&jAY-p>*^!_7D=4u(@_YCjg?w;Uovx9D-+19Z&=z?*HCFoRD(@cOxlV%ZjKm>)P>Eh^NnIT1It{qrIrfc!kG)sXsB=MTEe+g3}|M< z@=gY1S^z9YG+IXomV}%z_?QG^uX1WqLkm{V?JGFiw;{el(xLkr&TfE14v#JPB~8Za zYDrB)Lp^8dzp%ZvtF0%N=?CGGl7Wq_?M*9DUA4_KYv*@0*V2-eb9#-fT^$VuGsp@p z%rkPBXQ(ibNPapi6y}i>=8+R*n<&UOQrJGl6be^XCpTl~E>6zu7J8TrYryhjdS+5f z!!p8Vxq7#Bb?4a_!rNZBkrX2S!vZI^V3nX)h@psKuJL zqaf1Dtek19A#q7l3l`Jn)-IvxHZz)gZuHK0VAH^Gu5tSsTfur|eHeC!V$ePY$~zC3 zVvx-SlP5C{FxOw{v!m2v#sf|EctD!~5fL#QK^fRHH%c=f|S^ zI{o7z$AQL6onmm=V@R!#83*XbHOVAID>)+??S_?Xz_vRPIV)W}M@xs$jQD9LL-fbM z(oHnZT|<-x^#FEbJG5tFkIYsq<32VV1{i$nPL3B2yDR=yTDSIz17jSKI0NE9@f5P- z;IUhiB{vqwmP3?Jd~VC%dZgkz9DAi`&&YVENCG>OX}f?&vbnWYPq)#5X8U!V2b@M= zPhfw4SlR?=D%w^U&>b4}muLC#V>T)bonxRGJ@A=)RK%XU8~q5sn|}ZcLMVFwEh$^84N~wV3H6*o-l{gZ%{m+KtapAL?Iw z@E!0ya43AUnb*ClhWSwcdQ5XgY2 zv7S&na^o^^SIRP=IC!-6Q{#Y)Y$uo=l{_#;;g|}uv)wUZJ6W21oW=~|iq*3s?1a}H z-4?YcW)IB+?H!7rUMZe=9BoKyzR*&Po7W9=uo3lp^VkZBO-+=ixSO5?pd`bh#r+aq zN$(|H9b~%D-bzy3Js!>=+ovGRZ=Z$vJ;E@*#S`MU??U`mUWnhS3-JR>VcseW7Zmq0 zZ_3uSE}7rUy!=XcmNvit5#~46!u&=WTZ;wZg7RMG<=nU&X5EPtv+l#y_z4Qa{H92l z-&td;w*b~K%tCs}umfgvXDbY~=GqngEC|mUEo4Y9^A_<~ykTpeLP2)3rP0@ac-d}n zMBni>(L_@$duw0nHBU9gzj165ldWE$O(2VGc@c7=c}v+qd(pedHr*82-1fFFESvj2 zby&S%ztBYbc6*B$OGQ|?Cc%Go*w!z)~!B?ID|&n_kKa3yyh(I!eNtFfGRK)@9tDMyZ zc1eq?p@6Gdj^k?FCDptSiz}zw&Bp2iy9K7n&D5E)rEW!gvuwfqw^-t3_|6t*#LA|YM%l7*#flZOMNV}R%WF>0k?G~Ls&mBt z%JP{x;(^K;_+5T_`K%mKb;g-fb3_VG8pv^8pK<0HInKQ^f#Y=I#rzzc#q8j`czjI& zd?ijCRydC*8K(^Q!>LKfIrGV!u{89UJbnL%JbnI$JiY&iJc<89o?ib$o`nA)PvC#Z zqyL9I-v2`$g+4%iAtSCY{NFtxrxtUSJQovpr?{M^60wSwfnxarJmDi+=!^@|Xntu= ztXa%9zvr6Y>E?He`K>a)6U=Xk`3;c~Dn_^BB1T}L-Xez3$pa#j9vcv;&>2C|2frbq z@f&uI;kotHZB@`v+WCullP(Id1tO`LlEVDp<~ ze(@y?GZyeGX5wDrM9Z_x^>mzaN%6_zG{V8jm=vqRS(y~8G`|(*_iXc9j$es0#qgaC zP)s(zRLcTmi+*w1KYnqNJAQ4g;~N0D?{9twnqT^QfZ*{-XVkkm&y3EyA}Ef-!fy(G z7vkiz9GqZEXRMFKS)w7Fv|ff&%*t_==czc0^9-C)ehyB-oQ)HR=HqyR17Y%4AO^jp4lTf zNBmKo47Llkw+APM;|x@s5B?m^WPj0l3Fm^pg41;9boMuKj_2Dr!TST80saZj{r)e` z|Nh$f#`zX!wY$O-0nrENre@+i>_K7}PB9%Tf;g?T80V8xy`gO4oT>SzsmXgLUov_6 zp;Pa`fBmTyr{l^NXsLXt{DbmW@VmCWvplyvWzwceH&WWfqZ2=!cmV%%CQhGNF|lI8 zo(YdsJ~UzMgq(>7PFa7-RTC@5KQ?~j`0K}~k2^f>qj8hRm5m!cZgknAve{+R%BGd> zF1@#GTFH!(s*<9TqT#CB}FIHoKTpzJ@5Xa zjd^)_iNm)Kzk7JW@Z9m&=f04;Gq*W+My@mLonf;L^O?-$nTs-K4>&sD(*XwtG!K|HAR*&m#`26sCvWWk zS^t;tKd*mH`oZ+q(+;G)l(yG|jmi1RNlEV|y^yp$X;acwNu5b^k|rmW^*z}4g}&$a zozQ1z?*sNf;f;i+@a2OI30Ed`Cd^BiirACEJe#^The=kR|CPS$F{X<+GE zv8=O*uw4`3wH zXiPxQO>z{S??>la0ix)0D!IkRwck^gnwT2JGV-gZ^)f(k;-9|VFH zkY^+y>1`>AUkzdsSY1|<{2WfTDFW~qZ?p@}ZzBlhxVT3O&POvTKhZZwQ>bnuhzXor z=F<^lUcx!XvDjXGks%h_jyd0t*_vFb9|1(FTpc#$(9SBHcsT`UM(3d%rlrTMbp!>J zXA(m?9XavJF`WiB5io)Cqs5qcT<;SMBp(p8F$Ls2#lSKUFGJpG_$4TE;e1J)j0q`- zO1dK^js;G3G*y~&GkuxG=p#6BG8Q`sEftIH$N7}he_Uw1Avn3yNI&{HM^FH_GQ(p8 z;*YVUr9Riu_XCOmtP=c6I>9qWx$q&-JIub9I|=8cXE|4i z`|-VmYvuFq6=Dd|0>HWgY1!gF=L(z_{ha8JQ+R(N?#EYX62vx~(-;;z=yXK!DDgwU z>^B~L6Xy{AMgKMqmJiqyIEV1zI9LW?PvT_4ZE-NHhdkj)ZTh{XH|`+tc0*rK8JLHB z88b&S&OH3H{&gI57obae=9l*ax)>)U?$cXL4GzP%M-Je8=PPjz^*o$$U5N9u6L2>7 z8#wR#5u71@EzT-mfOFI*;EeZdd>Q3)d~anRPD|a4uga{#3GK6R{<`fc80m5*@fUd( zGVVq64VsZ0oD*+w#_a&4up0#BEzIo(+2F`=8wyhl>_lp_aiBczN=Jl`7}zML)dIYh z@Ov@5qC0>$3wSSe!xqPgFP(DFejFkg-{+qhm+K$pTl+* zWuO~cZ=ks(H@k!&*u^mf1|lWnYgAi7HPw5IvE&xLO4lu=CL{Z^I@F%xeI-rPWPnqJfGKpG5J%$ zr5@bt@ry!XMnw)vDV<_NkiLsW@iG%+X<2ZKl>pc%BfdMZ5GTM-#L4fKIPHBJ&UYX8 z|NK7@`Qrb}LFNDcuLP&#{htQ@@&Bhon(qHIAl?7@&oksS%yqfOs*_ls%|L1AbIs?V zKB%syVRlQ$YK?lsQ2YvYg{f2Y27K*-FdWQ)7B?3$)HNW3kxQb6F2uyyDxbsI$rL|Z zUchmhFDWnTmTW-!))8V7C7xy^li+A>|auEM)1iOm1snXCOTKAamZ}^-<(Qfe#(Lg{=8 zDECOuxjMfcxXW>-?bG_fI0~}??Z7Fw&*-f&DC{iHJ)(c#lZG?N@zheBkNX%-!8P-p z<%pi(sZPKj#re3uildWa=xmSD@!W&-JvAPOTnd$hQ@LAIt6GNBcX!~7-TO`572vG$ z8L9;5y}yJr4W*(A+PO&^y^_Y^ft+e znZl%(z$(hOvlz50)qG?!Al9PvAq9Y7Rz~6g#>od{zJV}K{&Yu{jNlomA5tXM1z`3oCpb?VD4GFXnN4pX27I6u#1LP(0P*7aUpq!ik3stUoZt@I>@9%(N%I zV_@l=dmT8eJMqOBUg31;%GJQz*$r<2@D`kSe+=*BTYxtMcsF&!n*zKkC)#=3@C`$T z!Xn_IzEBUuS4h-SaRK-GGy_2`6()9rpq9d)b%Q{%@JHPsm`#eHX()g;jTxDnD^bTq zzJ=D$P|vV>n02wi3pYv$=z6AS@C3AMc$E!4y|G)xtAH%(hPM|Gk`KYh3#W>$fK2O# zx6u(NLH~_vH+Zz>72+z?#dyHx#KD$A;vB%H7#Ov*5TG481Q_ZLJS=P)U~d4H8wV=` z>}9}`;$S1t8_@$IFN{R(BX=^@%&-K~-jN+JE8a3tBM-jVBSP0ZGIagO=VG{_Dfs4& z2(1JzjROax1TtZih|nD1&KY?}40p`+u+&5dy?^A@ak#(;O#tqMktm%nL+~S<5iUZb zfIBY^w*>JiTyrF=z}JYxNI-d9P}u@B0=vx<>1KAIuMyx|1m^7S2XS8a@A#ZbD7xeA7DC52>`F&sP0KRL|?lu%LzOY92 zDN>0^BORaOalZ^=q=ROq=4OfgT9Nn$qEwCUw`?y=##%h;1%j_tgl(VJMiSI6wa6z_*Rk#(QFvwg!*!isD(y`gYGBHv76s1^bk_3C=b@7 zsLjD2;XcG134(+WctOSy%qs&B@G@&SlIRnpDr8^dIO-<>sn*~m_I~(oX&O#OPbA6+ zWR<`Mz_*?8bqB;<_W)@*Baw$MS51ZGlM9N5-wAmzo-yi>k@l!?$$QZeCs2R05TlRs zb{Wc4$t1;pNqXv&d0Ynu?sK$M_Bk@|>QS5z*l5|{1Nagttui$9-MRSURZ+|{5?qIL z1f+gP)CawQI7(?CN3CSRHjIz9;pmZsF&uMRaGnVi2WD_O(x>Csqz5MfVgu3)CAQbl zPW6D0&U@l`?G%KpV-A`;M~p00h`(+qI9PWWUIlMCa?CShp0T_NUUCG5F*_K`v_je) z=zVqWk?$*W!6wvTqv3Oy_zZj<@pGAif#iX60oor|E@MG6>a`HRetb6K_%m@)FctU+ zdFf2W)H~L)>CqYx@JTJ^QgJBV*LG#sqTZGXBO<-9wO=c>G$ zfMJ7`&(ybo_EBfMUmusp0vP(xETH*_L1a$H$90^}LwE)VM7qVeU4PzM| zG#|TPt8+j}y6?hfvi-Rk`#)2$8i{)PhJWdZ9NULJHT*DIa{NB@DRK+Q2`(o=GY#K| zv_0U0`0z&%9z%Sai9@R44>&SsbIxW?-v9_g&N{@S^_)FO{ONe5&PE$h0PaDeo{hH3 z`jT^g3g$Sb?{AEqO=)tYA@nW z5aP8QcI3KzlASQn_bKFG&RDS;{z6SAUijA1yT>cnpa&e0yWUWKpC}CgmE5&Vg&^QH z=t|gSow=Qs*P!KqAmrA^@e+gP;Y+&If<1cVAdDdjNO{-LPe8nkbH2m$M>%rPs6nFu zg#?432RZbpH}?xwY0ILrkH>4^en$+0Jp?*$5v2^&<1k;h5CrrFJ_bwbBCW>?dw!4)A9Z@~;cevpk*u-? znK2f%H_FKOPvYAj^GHSp%TEy0RtCmz20o!>OW7awZo=nrrL?_$u1jlMjB)qlB$BOo#kLiv5 z&qXebCZznsP)b6atPvkVyh7l$dgy9Ei5Kh|3Pal%E6PjF;c~rw{Bos#fL!f{^52P4 z`W=YRV=4pzuk^j(HEk&MAHu+lMPcX!#)|Snd(Go=*?F?ZC`*UUJJ8Pie>0Sd5clVO zf)KA+jvRRRz`L2(6hIIL-qe$q`T>{g!1t63^Y5VXrd)p|UTNSvD4(ei1iaD?Vnk1&bCtliy z#1|;d1h$LxMo$7lc9FFfd+^FTfb|jSE(c#-1*N=oh`+&92m*R}I~_T4-$-87}l~%dDjGFs{>RZX)gkAztu*r{$+nE0Q!7Hl$@Umf?kn z)cB&=@#-!QeIgIF0sNT&^L2=9_R7| z;2mBB-xbY_I5Kk^c0LTpOpN>C&A{4h;&R{y z^nEcL{V&sMQOYp|Io4#7wM;UiM^MOYCu%16?fWy9@tWh;`Eay;s?~Z=5~bX2i2GWP zAfT7~h9gr)rLxw`eGU+WR2nngd0k_9xgQ>%S1wACg>oU^6NVRbP1Y=?LJ;EBjxjPh zYclRhn)x*@joeJ?#1 zaGNUyGNh!EwxT?DBM;F+6mgmQNE);R2hIUaD%0Lb<@Qb8i*)n>1d}6U?~t{K?KFWP z?vT!mZ5dk-$M{9CSer6#L2SJVKHasTyEbjD!4PRnk!Azr0W8|D)lK>`#3a7{dEC`Y z-|6tj95#6#qB8Y8AMy7L1qb^drqq2$J96;LgL!7|I|x_^gZDC);gyP=I`>O;2KUoO zXn<~hjx?H6Up9QU5TCRX#P=`-14-Qq==Ffo2u5x8zrX)xKvn~Chk>9}X)UPb>r-j; z5{)@Fq^?HXFSSUkfv<-~%W*YP+GylKK>7njBlRJ~vpN5-4CE<5FzOJvu2V5jr5;M% zZsM|kYX3gS_nrwp24<<$mr*_=7qv2nm|WJnu2AIVBTGKP$f(TdiTdVJQ2xYvBi(%@ z3#}j$XRvhlAuf>Lv`Gr~2olQ@%Phx~bK$f`Nc3mmSo>$Ha^k20{B(|o{rxF;k~8WF zODTk1iMbz??(umJ{D^tpV|ZpVPw4xBFC~9wc%o#j!0J;o=Qf)Rknmnq+EBuh#oblpLg zg&;^v*^D*A>-aToKWHBy>wsnLUrN6m>5mN}`@DZ6k_HS(AZDGyPa325u&5wOkg056&ed#q=YueKT( zDK{Ak)1ga0=iCG#9*vH~ld}hKPdv~@6bAT`MBC3iKS||zTIU~^R}N&VGIFgWN=Z~U z8oeYbL2#FZG3?~v-|$Mp_@&_YV9@nTC6b=Q{@`&+l(YkR5J2HZ!(|oX_Y!S{8<@*Y z7^^oW-Nam=cavs$lt|JO z!$rX$7~+;h5fj@IZ& zalEcFJ6Ti*7&F-48E80r@DI)a?L6eMWr4ndJ-oo=yvlGNh5H#C9Ooy1(K9FMfcPGf zD{(JG8dJ!_HP8H;b~fIzROCs;Kk*lMjz3x>nai=a7K<&y8wFG&9=!Ndm;)-aW|%z^)*<+?DQ1Kt>xr4xaHeWy*wJ%QSz0BPUs<2r?6&b!JRcEAAtB zjyfufd#`xv__DY+g42!oCEPVemi3SaeUSoSml|0vcP|HI5p!5=WpU5Ne$~134>*+q zV+KLGRrrndP@(U38jjChUyl)gJ${MPDxx9KSM((|0QN)TE{aIkYG1crV!7*?cm{DM z{afxD&sQca#^q2F@4yB z_2{)EP@i?MBS&(f4|~uq2@?!#sgcX{;RN53T8b3me!hIFG7QW8>Fx@_dn2G#7q z(KzYsKIAuec82CI7uKGutmoFlO78sl{_9|^?=&Z(evrS@mkBr`5w*iGiD#2At`gTX zk4_^KjTQk8c6`z`FL8O|a^O(OGEKnfN?c%a2}nRC`53>{pU57d-O?laHsi5yX;(1X zqCG}`zx`PE9PIa!$=go!`=Otuzly7soM0IJ{m|R``8vMc@Z){MejBltdZ6Ep{cg1K z^}~FHAk%N@x7x@PCzJY4-(+Q?Jr|bAh0U5n5)*d6>EJf1AI1n`ZAKo-k2>mCz%Z(t zKUk?!-T^#=xwMf~>N|rKtp%)-)-gw{la9wR1?xCx6f`k$Y$1**m}iJ%%1(w6U7D9s z560dh+rVN|%1!1z%F#WnujP7&^>QtvbN zP6_jB?#@MT@bHEMU@q}si{qH_nj*pJlH@N<-bKVIc`GG~O#gz!j`@tDINp?{VHV=p-$*qgQA5+sQTtbz`r`8@!A(TOJ~r(^$e z6k5_y31A%?sK+mrv4JEAfOcTI4S>}f2|m&v0pj~*>o_l-W5)N}MG;;1>NP>@IN73 zW%AaN{JIQ*df!q5n`h)7p+_J#-*9srg1LPU>oQ#kT+EUP(~Nvl=jkDUoevnzTU-iV zg}SanJ?0sR&>`T2fD`g{xx3$Ri?%(yMl%4Rca!YwoPhTLuZ8?H(@b#koeao;vU?xk zDbFo(i^=^1z=XFF4`ke812ECNyke!R7SO_5U!jQC;(lSTAzAi|pm*gW9mNh)KsU1Xv&F%}a?cqcFk?`(#| z5J6AVzwYdT*Xb%)EcLL~im=i)B@-_}`@V!qB#$;MxQ*Okvk1KVFaYL($9b- zGcckl=Xrn$yg4ew1YGAC7%VJM--Ukx8`5$xFn5xRF(NQh5u$w@WpWXseHYHRBa;%cRG}cH@0m4IT*&J?DD4(fV<{98cRzgu6`+*j~7zFJSG$Z_YSp8(FP2 zy^3X}@gv+X4R#*xF;gMbBh{2209J%NMfmqi`+v*-A#xEl%%)i9qJ=qTW>dYH*Wph@wPFvO z2Qw>HJPG?vzNyi2pcNAK8QAHuawKdwv>oSkqzF*98sgBcpLr#yI&Y^wm7$7ZaLSPgjtidR>CB3+=di8Z&Lk0%1N zt^p;|s3I`KO@ zBx0%b>pZsyP}|2yrBPcHfL%#a3Dgzd;IjEEEEkR1N7x1^)zfBRTx)`f3$kifnZQy( z>q7J5*QDz?NV6ecs;TH>H1;&C&^f4)xcw=ky$g*@lZd1D87SnkOcPlqlw7AcIhF_c zBS4G-@gT3%;}*|*5BA!7_%*V4=rbJRWbyVwb4TmT+b&*a$=aQH-REX+6R2&%FJYfz zWSb6(SK9y>Y&T$x_r?RV9C5-M$CA`z%~kK!V}Fb5$-_(sEslQ!5#A)^LJ#mJ;Wu8s z>~8Y);dQ%4?{9Nv#_JCCIm-Syeu-}>$w%|C+HV73B_yAnv(!H3Q4A~`Ibg6;feGEE zw&Is0aN*Cq#;iXOgYEC)U2ps&4YbweCP;NT?&9QCZO}{96vtTTcuq#DS>|aO2k+|= z4U7U+V*_#&l6(sPfP|PPX?)^71l)(vKVp=#j|o!s!Cj2I6h~2mQeS5z=;1MR_hXd5 zYHBA)G~62zp5ojD0Uh@-=;ue^D=}Q$2LPdPcRUXXZ;f69UpSSrCl6=`x6SZ4+3-M5 zcIR+zf)Eercz3Eh755}X1qa^_H}-;nra(Ea|GvKHrh`V3n`AhRCOUEt!eJXgc?@7u zJ|Z6iv0L;w7GDqeBVrO3q6B4x`$0PT6wp~e1P>}g-yArKT z6QsN?SbUEN#Yyflwpsr}d|9rsKGk2l@IR)O55^L-~;zYI61Xr}sKVusm4%@EW@G-4S zlIzu|Pm-M86QUk}Sz8qEC{vW+fio1?uSyLN7qyXf}C= z8meR$QV%#k3S)1OQ^h=nA_eah(=Rw!=?ZYokF#BeAaw|6(;F2emB4Nb;nSO#0+vNg zR@94o3q~#K6>mY@ic;EAkgtO*r$nSEJc%Un>=4y`fhvl_nF1KuTME5Ly6?xOV7}*+ zy(Wd)i>&KJBQedbV}X&5;J{jdRG6QsEPiQi`_b;H09{Jojo{btAiSq>DdzRdU~6B2 zcI|D>fk_I`J6?3cQw1!V3(>FF;ar)&IB$u7{yHumReq6Jy{QHEaoZ0 zlN|Ubo|qG&JSRKD-2b?rsbrO+`l(cvrqWfOIzf$4BUP~~!NC?~>Km-|y?_n`0tta$ zfy6-XK%YS0KvEzX)<;I*guqD98-};*-h+owDNkuQ1`?o!2dY78unMY>3adi34?dAE z^;i0k{#qZ_-{>RyTYXf27jOb1&_9qD7!fBGPA$M&?6^+l^U3r!ym`Nc%Hy}KhR#7;T^843)E1^KHEF~bNC)7*9Ko-3)SDQ9({>O5rLlA> zd@3)PvFNw0FxIC(>p=HFic^6@BW4vs_Y{HrK7H&XeD@{O8e#g0wV=lu{th7M^X|hg zd!As!#;El&X^*;l46bmWkE5#b&L`!>oBmA6mQ#QCCa?tdMSTe*_Cu1vVXONaoXzrE zXt&?F+uh&0JJdKeUN6@x^vXEg>A-!|ea!s>-jw{KyUTst-R(Z%?omx@k-kUYt7-q< zuem(nKI!gt|KvX9KJ7l^KI`st|Li`e`l=*#09M3iNT{rY)H9q!ctUqNebnQy&ywQk z;4NVH9=w-%pL@UiEB68SL3fM$Yxf}~U<^^4&}~)$JpX;?#h5 zL>tao zN^}lm?mXzc1v_mkB+SQH`3BS7@!nn951+%o@qXF6*oFSs#alx?dVen2PHHDgYrK}~ zUpgP>nS?QBCB{)dr@xw{%5|q+rGKQa!=A?t=6$pW^n>Po@`v=pdMn;d+lKebA8{0& zuY%K7E{48XhI3n_=V1>epeCwIuy=W@{-wSXC)xBbu;L;phGV%}qW3U9JKgExBV zee~z>M*0hQCp|}4o086jsb-dab@n|5RVAZ`AAbO?tiFpl{Q6z~8t7@8CX$ zw|sZvo!(vgalPBT+y11Ju4>e2YN|Se&hJs@sCjBL9&TMpC;4cc%A)Vm_u)Oc?RZm8 zsfX28^sjrJUTDVy>L`5T%k|~@3jK3^kFh3i)<47hzWJ(FtuW`C^v2vX3Qx+Nq9&+H zdQ)C4(O2tDz)e?K`iHotsZ2b-D^)7?gj~#61Js3}AkpJe)OfWBbt2IJlF_$kVdtU= zJ?C5Zs9Nasb)UzZLl>w9wLmqh4n^+(E;VlfZp53q->3@JX3jd%?&t1doM&{Ns?*n? z_kN9&jb^I3xI3iIRR14$?*i9k`Tq~!J1`jB3~Aqr!|>71hA#84DP zQ53}kiXw`KIm#%@G7F6;9NwSP#RBpgko!jR45%%<1(`w^c`A7tIhDK`+PF=YlP8fA$+O_| zN2Je5he=JOlkoXNpyfK?p;q`@29*5`aMTI-`~lE;E%4XR@cDh9`mcf8THtdj@W5BV zdq2VF_kbg6fD?a&&j)}%z68E(hR-FyEnfhaLY^4txp#njs)1{dTP33({NI-Vejw~? zRK4loR>E?u8fuC`zkr-W8V2c#=RxYZqiS=|H36V)7z9tGKL|8}AF7LoD*9NWjQIbP za|cN8!pT%mk%LJ8kt~ntycb=_y7{jU${a~LaV*cnv28?Mv?;yZ>{s9M32(}&Q zqX|=kmcE3&Ou9_EjO`{pBt67l0WBSjy$V`79DALtA#1QV$v=a2_?8O^JV5(F?ySe& zww}jSOxXhR=N*t38th%*^g^t}dM4BX;Q1n~l=42vrT49Ij}Ji4-^I!(CRYMh4!YeB zs{;Mb!w$I)11<0HFIZQJw$l}P!!TL_`adA2AdCx$eKdFkVgMUX15e;8EC;*}t>6be z2h}b;*bSi4Si)qe#ZM(HA*>)|6E+dH6J8*^LfA)mhwv%k44e_uMYu{ZfJ4`x$R>^= z#=~l)5Yvdu;8f5J#C)QL_!6<4_!+T*_ybh_pCeu%ULhJt6jCTyWwS^rq%_j&r2W8+ z&7_lXV!%0&^F5>+Aelk|$t)r7B7Z{Gft)3~xVz9@rnn@yJm-=Mw*5-*4OF=_xEyym z;qt4?O*k#h0!O6b6kkdpC4@2@j;9k-6qHoT63PlnHpoGcYoJl9K)%<*IXq`6e^4$_ zu2K3a_g#sAvL?93xhh=~U6WlGxGr^F<(lKV#kI-xXIFz;fE&kcnA=D(N&hVDrZr%$KPqHm&aqrXId zo&Et`OK+#2r+4{aK9N32J}Ewne2RSz`F!p3tIt`V4xcWc8$Ne@9{3V{2l)>5o#i{% zH_!Jq-}ijK@jc<&%kX9h8Oe;zj2(}2)|b~gJx_6hcB_O0Mi!OMbQ3;rS45PWw~*q|kYUK{kypg%Y` z$A=TZ5puFP<(w0oYlFQ8#}6(Xd}#1jgRh6MLxzWp4v~grhO7zM7_v3w?T}L;y&<t-Z=cv5yTN8BVtA@9P!SG4@P`4 z;?Rf-0ylv`pcG^YiUbD)9|;Z$z7TW>E()#+ZiNmC<%J4Dg`u-U=Y=i~T^_nRbVKNt z&^@7VhJG9RSLof)ha;sUH;jCD^oyW7~4Fyb?lw74@5&nVWJ38jA)W*x@fj2RkT#JO0-e5P4t53712J?JE9Ln6{62Y zwW9Au$3-VZZK89c3!pCnqVNgf6T_#4Cxy=sUlP6|d~Nu~ z@ci(d;V*{28on>QIQ)a~Ps6_mKOEi|-V*+6__^>4;a9^A;rAj45!48J1S=vWVg&ql zt;mSj2t`CfL~=x0#IlGr5gQ}6Mm!(!YQ$R+2O`QNsv^FQ_&(xz#EFQuh~FbRBQ8hu zMcj!ni^*aSaf~=$ykC4e(jzh^a!KSXk>!y;L|%-%I*u@I(zt2kvc|nW?&!GQD6c4C z)WWE(QDsrOs6V5+qpnBYj=Db{PHP(PHQs-G@Oa+%@#ANXUqAkx@gI(_9N#v5q9JAxm%xL&BEuBqJr^l4yxsGEJhA%$1}`mPuAiHc0X%8p%tN*CqQU z?@7ufpGj&Y-%1)KKS{Kbvywk0mnAnOcVn?ww^;AkfY`yY!(&IsM#M(PPK=!zJ2Q4p z?84ZL*j2GPv0Gwy#(o>yFO^Ca(izg(()rSKX{L0Ibb~Zss*%1VeO|U$Fj+D=bMpI>Kc9R<5v-V|n5jrsq$<)CnTj=v4T>!awPKf| zLh+TN4T4g>Q^rkMHf6(^+Bu|=}l$fMRdNb+Mq)W3W z&fYe=VD?M1Kc4;B?90!Mdv4itZ#{QBIVgE*^7`bO*)!+sIp^o}&bdF=bMCOYin(cXm(N{0chlTsb35ifNTH^9rTC`=KXFY; z$xrzz<&Sxcc`@@+=e;S41ew%tURh!zoAb7#l1*;dlvEY*hKP|Yj zkg(8uA!}ji!Wj!w7Oq~Hzwo7nr3=4a_+uI=jh8k$EhcSiT5a0#v=eDp(rzyDTNJb? zY*E~z*^9O>`fSlxi+)&ic2UQou0>ZCk6yfI@tcd^S^WOupBJB6tY7@s;>(M#FYaG# zO2^Xi^bzSP>1pX1>2IXJm;O=u_vt<9<|X(N-zBUioF$`{gfAKY*fnR#`Xz5Jsa|qw zN$*n6r6ZOuTDo`X{-qU5k1zds>8YjqrGG8GoWc0};%1DqUo$e2GTz8|JL7PMA>;0{ zLCfYYTe$3nWxJQvF1zsm+I4T){}(RHGRtyECHY^!JeJe{m#*ODk;_$ZEn2>Q`SZ(* zmsc)7y1ae)^`~ABGs&4Ane@zgnZ=o3WIkLGyCQ!@*@_=mTwHN&#l4k+l~F5a!1emd zqLm-6{AHzar8$d~MbBbp1!sw}qOxMMCS^^7Yi3q*R%%vyR%X_ktPNRPvea44S*=dj z)vT*o_f}!6{8r__wRzQ!RWGdCz3PKiU#E!)^)+_BG=7Xw_x3xbsN@gS*KpNYuzjB-dp$0y6@MITA#PR zD(AVJ6*<{Cn{u}2ypZ#5&Zjw_=QQP<&FRXyl5>9pVT0EOzYQT9!Zt*1n7AQf!%G_u zZaBBWve9qj_>Idq?%Mdp#*-WW+-S*l$@R#k=Q4AHbBE-P$Q_*vdw&ubY0~bYqh-56kn&qvr+W4apmoC(e`SCFQNmTc5W%Z)e`i zd9UZao%eoTZC*p(k9nu^Za^|KZ8K~0@Xg}Q^3C%$Z`=IN<_|YFZvJEQmCZLc-`#?3 z@z~#VJFw=UVbV(Z$ixqn}!Tff-)CtN*S`?lWRhHvwgVmpxU5Po9=MyN=Y zVy}>@_T(fl^_vR|i<`iLnf9>ivTtjGTQd4oftSl-@tIf<*69s}& z=Mih|BT0rfMidr)qU}gaYi~Pzpm6u@W4g37?YFyCsu{6E@S-Bts7Z+`mFl_Vq?t2S zng9Xed|O*vet!Oj^od_t5-}?D3mYZw7{nJ}g%UaK< zs0opwKBlTFqw8Q{l!i|E^}RjtXZ!Z;o72ZqJUrdWJ6&L&?rs#@XsoeXHoL1!X34YU zk={E^pvr(Cc919!e|-l+6xhCj zoDNqCfe3#H5Dtsa5m&}XQzWhV7>@6Aez(Wz-GMY{9q?{iKe^nJj}=(z;cvcr2c-tX<+z~7 z_M~%vzK#`uHkIkh+LBtVP>L1ofWL%7d&^^C9sE0vAK0~Pmr8}>Mq_og(I}BfhEi_! zYuwD9x0`Dk8WIxJ9tjBz4LIKR<$LeFy-VY~yZ`g@#<3lR&OWEfXv$mMlw>nuOy@ z+`fBJ&=R$fH!>l^}igctE*F~G&`^YIUup=mN-jyz zI=CxvnvvUp{bAehoat~b^u%gB^zI8Mk5!iy6{6)oC z`!7b~;Cu!2=OvMh^1-hE+Su6m>vha$ltgCPXxT{o8k=foaN=a_u+*|q6GSzEP&XJJ z;DH=qZcYI81~9h)=K*IAbEcX92|6Dr#T>M}5XQS>xa&}0I~eo5bJj7pi^Sd0Tz*R% zx3e9SfeM;G3~K}m|KNVPhSAGRsVCCq$8W3MqENs~xYbyoZO+O;1lBO#Snl z%4g5RF@||ChG6dagtSg=_N>uidcAN|!s?cm)S2VCUa%~_3|>MUkN{k+GkFG3lc&f? zP5L0U{_!=W*f~oFk=CPF$Rlk|Lt^pQy3*k8+1(mQ|Kju5TP|l}LI| z?vq+pQADCKe73~CKV3c|jd#!YZ-bhH)tC^_-QCvE(17R`zwJb~z6l8(ZlLU=Mlll- z3JO}`_UKD-K(TOPpK082CX-1qo33?scBqod164H_+$S(aFq5RX!4#aYXyDv1fyV^WX`JgR>%hdV^TXJO{M{r&y7 z9#PD-($doFIR6pFAdOCvNK`q9*b*%Ht{utAd-j+H!7M>DyL{Z4oNTBEjjSPebX~pN zp(a#Ut6_@x!;Tt2F+3iR`m`N$<|&)3ad6vG=#QsTMF)_6tg6CXUHdx^s@3Yk^2XA# z`uh4my*ZIfGI=Ayqo%HlgOlgsa@jUllDb%>3FFYsuw!2I%*^cU?9?#Q^S&xTLnIgsBrKKk( zCWbR;F8$Ys1zN6D#aT9?i+1GBotF-@UJuF0$aw3mx2iQ>TrQh^*57wXpqmN)Scr0f zaL?ORHhucwz7r<`j#Tg8zyAc8Lb>b8wT%}C(MksG3BRKuqohqD*g@KbJZ%7pkZ((m6?S62fl^(S2ie${y3Oa>9w_`U}diSqBT zw}?O}GGL|eFo!I*t<(RWgt4`sI$)0+oNxQiamRvrV5CWw^$^#319-Iodrd=(2Qvet zzHK#!zylP9s)4Gg>6Kz{lbG$oKB;9rQa)It8uVrk`p=nC9P@f|B^|vE90Lb>aI4P4 zcBkYj)tD51mqgtz4d~=N!1QWtml`A4T1PsQoSt4%QWXbUm;|6mrNInpq5;Pd#DM`j zO>TXM6W$XQwEdo15=3 z71;w;&4FWWEAxMQXGcA9%;>x`PjB@_m?N{#)YsS7D;D$dhqrsVJP+f|3q5`JjK-bA zx;xw3+ke;pb<^11rSH3JctA3>KHI=!O}n$hc-L9hzp%CYR0mX@1TQBqP;DCzE>TCIu8B@nd(R>Yyh zUY*>b&Z86+{`xJd_Qi5{bePLP>A2Jry003rm6&XQ`_d3l?1 zNdW8&CIZPb0NVDWRU9ZPD$)4@0Qn8t&im@hD&EZ(!{-E$fOi>hXKVK5vc0rw4r;e<&_OaG#J$E{wyS}N{1 zQfi-HF0_a3iL)eG7FxEkifXGXt7<9iv7qF~bIjd80_^f`ag?hMJI$Eg)+-}%Vx?B z(4jB9@@kxA0}OhuTN8Q0gbBm?oA*xygfJJb4D2I~t5^(JK>VMV!HSrtK%XI**{PAd zzz|mQ>_|%I;mXR&n$t$Fae#?uCiD+VPv2K`UK66HDu8b@QfU;J-+eNLM1!UEcQG2f z^!4?31cHn8188!fH2dGYL;FY(rmo0=KT_<4(VI7KSem+M@$zICU*x2JF||lJMi2DG zDO4)egW7Zqu~ySbmK%E`{I zuGYA+C8J@V0vT%8@=suLwWr(Fe`ApG@LnLFpWW3}{q(mzt&}eQr#6t50EuF@Ngg5G z`6(1UUU~VhUFGFw4&Wn>`Am6v`56rn&&pDJXJwU^;;E@)XxCwNuhYh)+Gp=TY(yei z!7JZY4!?{ht8~C@O#@cu|Mo5uMmh>8daVqrJ9pt{z;9`3eSIArB_$mlroq6PgH7!) z>~_Yu%*@Pjj2i%|ZvfztLb6aQ!`KbK0(u>?+TSLXl)$vuSy?3|1Ew`#icWjx7&pq$ z-a#$485Xv1DU?j9-FS ztgF*_Qq$IfyK`F}1z9OzDC{DZl-PT*b3qSg{(H@={+5?9>QhExf0_=7v(|4Tp+{z= zAT6uA<|+O9nw5RV3hW;gSIe)uIyH0MBvq7+d-r{3V9o;e z)$DM?alvpK`?^V7zX$$3e7@7!6XU>9v(aky)55~SMu^3|?X6%zpKEOeA2!g2=c3iK zmoH!b$tRzDuA_<8Aan2)>=jJ_hePOTKV=}1>W`f6F>%1_^zZtz;X((VMVN>jA0K?S zPKFe?e*uV}-EVyF5I``mL?o3oKB_S;SG%%TuU@FI%>+rJNAnvX10AzM-h&`BJrcMv zih*4RL$|8=s#yrTC&F66YCfR>4Cn7j?Y|17(s!3iXR%95&rn6^0qR)?4spgm|Lten zTpeB}=eLpfWP~|DVjEj`qjhXrxuTaZ64upHw5?_VxMC#USQ}`j#y;f188}jAzgcQo z>=)hJN2laeuq!G$s3B9~l`!hHqZKwDaqiFgGpe+V?7Gp@({s67I4Xp4udkcUq4eLs z*LTy*biar2g9r1zq5p0_E(S#>#{U3%=+u+>VTHS^HIWD&8*lgZ1wF#Yzt#Qn_Y$(% z(FxJ)l9G$mFzZ5ID6xX#zcDe|agI_k4Q8&KoB)`&x;i~QE8UFXZ^jVPaoCvhHVt^z z91yt6*p1^t5i|+#R|(?O3Wn`FZfz|)dr9KJ79VeoB>*pgbBolcwr0h!t>1iFR+f;k zXU~DUs;_EbW4`%;6b(~J2_v0-7cgw6W-yyQT!iD@#^%c~?Yks|W33og29G&oSkxZ7 zx_a;4>S~@MZn8)^D~TB#z#KJErHYT&>98ceW(S^?RaS=MEG~GUeDF!Y1)Gt}2d;cK zkTh5^xUz}|(Dy()ap0XphR%ncL#e+4%fI1<>D-SkKc4RD?sJ3X^24jDKvbPIc<{#vM~xc64R%4(rKT-O zA21#VeGjB|+ucA<&cG)fcI$SuN(P1~Iyzc0Hw(P)nX_dgkw`cg_omaMMa15(CxV9> zU0dCX>)L^CPuIK=XW51>_rltqKp=atOuy5NWwCIx$>QSX=0>G6{k>gD7_y;m^kl3C zgFuO6eHZ^Yuh*YB-($3x?`mOgO`ujxW|oa#kVl3YA2-Z+9C2fFRn_X%Dmhpsv%*FU zW@(r>Le`w*;$k>p3>-7X#Yt&M)8yONLJDsOOC;a|t$Jn~!A!sb%>UF9=yt1K+JQm= zPMT?;N1)S=XGTK5zF=ZaV_pL4ME2KbUsWFhHLs!KJOx0Mi9*nuu02S|fv?3rT4#Ci z-+msr&(3e#zDcu>%=sJV&wemsk}7v^l@yZpN&Ao=2x#2l0YZoYPiQbns`NRW_OQ-9 zJdGNwQM+2bIpEOwXW8c5kMn1QDLk?&3X9UPeF-_qdyN`31v*W@k%Oqt)+P_0@k-8G zIJ~>1zV_Q=P3ns5{(Z2D)bl6KcO@r=)6p=~{-3TOniqJcNb;!aYN=%zsj5mM(Gc?U z)h_w__Cb)*HU`@Y{u_IYY^4%Nu(#urr}3ME!))I%pRzA#UEFm-l~9L;wO6%=6?h1B zq_Fnt_Aru82*xkUCiq8G&at6#Fq*b(Nf?R$`RAYb$b>C+D*KN(lq1ESz@d*fWgWva z@gDvJ-rKdyP9qawZp>#%-+vUmL=e0-oP=n|5xt%PpLzSDQrgTSI!-s5>3wG0U>29R zWieZM{q1~1JDa8x@LPF3fN%k-)(rTM?jT^GVf%mfRay+~jv|S{+>=Y9*=ER4INNqg ztJSt>!N$4NYq)LfxIp0Z4TeTa1eo{`ANi$GGnmElGA5{!lFXI|rn?ZiBvU=PTyFmb zc&D+6>BmY^dn7@K!i0|kBT61+?+fY69fRn@ghCnEbRd`B8RhE1`22~ zvA%n%3<^13By8^1_~YBn*!H}v1iB6fgDz_MmTjOS>gv=)_(x3u`^46^^LTB%>CoE) z?~rBg*Co#FZqTPicXhGZO(i@TtFReTHZ+93KD7rA#ei&ocxw2GJzr-Dyf>P{7zMV* z#BgS~EGjB$q(^Tn088`ru0!CYDrsoZ8}z3>E+{DY@MOn5BE9j*6%APW0X{UEyV-E< z@|C{JNMZE%t5N~eL{P7_0$G7l9_HHf^FfI4)HKlj9X1G(58hQ(;Eqs^7nP_~V2OR( zk^!;~89wCViJvp%D7 zVG0@cKK2T}Ttd<{9{>5LhCNmJCgc@Go`~0IvuK9vhP0H)fqh_FtL)>lQJ}+yLR`S$ z@z}6hVLYB*-v;RGFTLI{I5Q4=16|~C1{&?BI25F{tRn31)P!)1CKqb3AHBPq&J3oy zn2emdn(w=)LRC^-l1fPJ`o88VT!5@=yVIIHk!yIr5F+h(aox!-?Gb=XXn8e0I5PwY znq}ToaTEd%zuaOw`2zxB^W4x%LCg+vi%>d@uw)PN%C=hPO2RRq4Q#uO?r1jdM~}O( zyVA76(j8yJJF_a?P!-&i%+p$M)0HSeog>wt6FSzbs zKKU>j0C~ZJx;nJb1n^E-TSmS}dU`r#h)gDv2sy>Yy7cs(_75EL?t_yWR~$qkthCQg z54^b<;mbL^`=^`jD<*;Wy;D=$ZqR5n*L!^^^QJU4bu!otx!`bCTCX)&v7?m`@133i zSG8Ke)NA5-_jQiA1R94Iw9^F6$CkG4?hf!k0HTI4wq*&4#R3-%1qWxsBtCT~71!wi zT~6Zbtj-tPJSM^WL?+X$38Yk4(*iGQm*Y5%7M=lQmOh5oR}Zd+ z?`~>vF#QCXJv1*QjVWtFZUhHu}osc1D}PSMsm@d>9}_Px4uB60(v%j41H z6e3MPQR*z~gcWMW;$0WWG$s+m-G#Ql;QtSN z0%_z6T{!N|9fFI~!LE|@kVxH8@L_YdoX#6ev#&J5yp-D7?b{h$Z`;Kp{;g^Ib{dlp z`ZGeJR1<53Ld_0e9EWw^G=tR&`Vtm}8^jFsRFk{lp)MO=q(MtT+qb8InW@!sgM;KF z!$AIx9iKctQpg@LCV5pH{89itc7-4m#=*gNm#{5Ji;s*^Ci4<~S zf(Zl=a9d;}rLYhfM3*Hp8bw)YwiR}k0M4Hg-lDKWrSS`MwnHWiL9LZy@4GUqs(M(g zKwLv9D*;YBtVbEtGOY_31*4+vbFxVohgE3J3Fy2EL2K=wS35f|L*V>!XXjTCw)mnG zMGxJL`mXNo#x8EJmc*dny{h3rPAmAJ8Aw35Q@zOsr80zi3w%p=@WIM1lLr}jWYfT; zzI5uGy+@`s4;2ofwCYB-ycS_+e~Mgc*+PI|n-!khWa~1R6;Z%Q0o#~R3~8A;mIcJ} zcM9c}EtWNwMd(7+lik>e(9qC0%VKnSyjJx`Sn6!$uzBf9f$$(;U zaKGBU|0Z}a`^EXQ#g8HgF^FIcG>|ZDlA_ihJ7727(>%he%k*_U0rfH zTMp?vbgTlSSr%#tEiGy{7WLX^QD1>$}XOHJf@>1;d(^a;4py5a~80%io^L2gBG8#P4U{x{}EUP_<78<)YR zK6~bp$v;|d=qFQxW=@1K-iPR-<#M|yxB6XyJA7OzSFY})n{Hm~>(W+LR+7TOxK@lF zrO=G;=>aU{;vEER>1rzf0DO=K4|iYzbl66m4dV#bks#%d&~fQpbLaU#TD6da(%Fpti#i1!6?5-B2Mph=WwKxhfwX%! z0V4go+6ABi%u_C}F5A_akx^3828nSRD@7Bw?^2V&?Sk*JbG@^)LOkIvm#4!#9?!gL zusd;y4Gja5u&g{W3f?14nD9xl)Uu6w_VMH{YrmB315&(f)FVRgwKa-M)euClEKxU< zmI{T|;1bZ9#tjG0Xf=-5ngj?Q((52O3%;;9MBm^P=egMP4nnUv}bHq9V-|f#Z zN^E0^gZ9XDy4h_054H_cK%>b8|Jc?T)D{~&EDHOoc~rLCSLS6ejmyogs?w02E$OVI z;0y;ezg{mm%g1d0zeJFx0mh;6%S*s z{n*rWI}&0Ki7FfcGqWcn1f@KY`)g}E8C%n)7gG@ z_z|9i5xP`W<>qoa;~-Lb2z!H)n+po@%6utS?z;}eVe8?KU)P3TjIR zaDxJp&o{xNr9~!Nrox<62@zC@eH19~iV+`QP@r6$lbe+oY^?d|oc`CA;&=wi@>vfk za?ul}zuaN^|Lvl%@iOvI20fAIUWm3OHy35SYX)SuyP)j$@^Vyd5FhWL+2J58J)Ct1 z2ry!PO+NZ3dID*pWfrK)=PZdXHVNzOB>~?qvS|L9Hl>!Oq#wDIyYTPRO>iRMSSR0B z613yzxowV0r z*ekcpw#b|-4<3!yNwPS0`q}o9?HlJ9GpC^e9Qw~6?znJ|QhVaEIS?#xk)OHk+XmB* zFROF2#%nmVA(7G19blgws37?RJ-V50BJy+(%E}68Z|6Dk?#SSng6r=(jDe%D-JP@3 zDDs|A&3_&Hs)pj_-UEJ3Ys`wct5}E9dS7x)l7N*R69~Cv`7Q`|=jt?rdwTA9(lh3y zr>76X`vD$OD3pK@2E)>0vOz?L@AYZ@I&8;*-$`K<5SbcS-GDVbzbijK4vWpr+x6m6 zP4MGI4Ov;f?d{$Wnly%m8OsK6praT2O0*A*Ksde~I0oCD11H(;dhDyjhVgkUU;bP3 zK^Jh@B3F-9wvx63pnH^UG_bu{@D6rJhW&v3fFBYM@ixUp4rO|Ppq+?*1eb=eJ{`%Z z_ep2Z=H&rECNda04FO2?36?_Lz;UY(^n2c_d5}#ZL%tNBq@uI5J1_=7La-+Lt<5tb~pM&}`oh=^_^K>>P(I&Vsi^G8U4d1cKmt>WZk}f#(R(gPc~{qX0r!ZIA#<8Y6t*O#d46w zlqTHI9ERgz;PmgK({3pdriCnAKx9p3v%tV*VjyfHi4H=kQ zEDIr&2eKThBCJIco)C72$_Q(T1k(6_Yq7=9qQH1fuh)Y?&BOYCg*ZiREep~?*uw%% z-M1+;Pimh;qSq@@(-x=512t@;@lMav7NtivY2Id}?J5wGg*2x-uGQ6fnTlagtDr(RBz+HYe&j+3tIr$5 z<50!2blA=WhBwKij2Vgdp8@|$y z&+l;4b+&X|Cqmn5;Cqb2fgoO^{sGF#LM7B~Z8zYk9Iuu2mzFMH zKDI=GG_L}RC@T9i*v{soRc@_;=S9XY1Ifdk(u?>+o|3vSS;lN@_@+$TbfgBQih`u+ zI}iUJZoeh~n~fjFg`a51kCqM?M(yKZ76i7~0Qb1QG_?=c|CSDWWVu1kE8RB!70@r4 zMFy|+zp@Cu;K9bGrkos;DJQ3?3F7VG+xC~@~KwjVZ9*Kl{v=BmSfdh)! zG+up2?bU4b-U}!d52YR8cbpJo_vxbtZ(VNxu^vJa@Ch;c290yd+C$>ub+XqjDI`hJCi+Gn`-S9@DaZ!ZmQKZJY-0u6WUM$Vh>-8 z>&$An(GcsBk`UZeyCfymVemO9Y08Y$6&WD2lah40v^mesnQNp&v>W{us0l`+8gu9l zWV^cY86m-ho+b|P#4F^|Qc2RXIIIY(#Xk4i3lwto*QU0%_KH_u+e^xb!;XMq{T2lZ z;|`Xn&p|4Ft_&-|UUOHntopF3iUCnI9r!@Y$vEDq>)+`LCjflb(ga$bTvulo`BsWW zyGTw;D=Ny9gD>twaGbu2?VwHPcir>AiKZ5N2hRxEJ!S(rbIx*TcMLaq!Z0p3C{so{uHHKyP?k{taanb3-S@xT9mJ!H z0PU#;8-4J*?W?}vR?uOaKmn;jhFN2k$z>@q^JYY^4#+GYE>4SPAViv!>(>YhD3p8ZKumqcPs;ep3(xCUu# zZ@Jv0?ECXXV`Fn!R`%L8>$ad0tFk|&*jLm|SquJ1Pw#4Pc?B{h^3~q?8|ID1aY!K^ zHhuXf&?)(7`|^>-hESz-|D4y{HkzmB$RKZnAE5Q*hK4FJ2Tm&xbhfJG^14oe0H&hX zt3ALsgt#01rKsU2Hp!9!?-84tEA0@SQ>oYAFjXJ@wbxAm(Vh_`Za63{&V%m1j@M$I zM*XMAW=7?~2ixm4p#U;m4JTo94>z(Pmc;glLjhf}2bPD%+x@VG7kZR4V1py*SHYOI z&j)2~c_k!(ul4(15~{0#Y$k?5TohN!ERmK)gxB9k<#Tb^N#KiD35y*$N4A+eVzX#X z9JUbB%Mh1>gyE73Rc$Q*!G$yBr5i(D*awl+XuReHR)Bqht7-f8CB={SGW4V^U9)CUf@998%77t> zDrsnJX=~%5;Dkbv+T56GhNMVjL5{b~K%RLB!S(mct)J#vra=k1bFLQ6Dc-v$yE=PM zf=d&I%k2I}XWDucao@YTI)Sw3KSkUjvg<-d*(OACG%u~RiHz^X_CBTEfjgHEbDE$P z3PTa-3Q{ zsN;&0!SPLEm+a9$ky=`IiZ9;9f?a|FJH% zhpld1I4I=rH+-ImxhGVw-s@_Oxx-`DR*`*0PfhK-;s-fI!>-kpl=P&g>g(-Hj=cxQ z0?0oBpMJL=0^RlX07s{?435}l1iT%PoXnY^1SzXZjxQ=|ZKWnBGmSM+QE?XD1z_Sy zrux!$;(PYswYBhedJJ7xYm=EMs!bOPdudR&Dg&)bj`Ip0JafwY|{7y!T**t)$PwmwzPy4Y@O$(d`A-xMB-mY7_< zc;oZ7gTocfkOHr10v5SnGJ#LJc^cgC9Tv?X{~E^=bKdbk)W+dx>K(<+SblWS>@$X(?Qi` zD9X#_wLbyQ>x|0CsH~Mk=9CXqH~!d*>TI>z{u>uM^a$D$`n5J)l?)@JXJI%nw3iYYK5Jgu@f3x$l-K!06F`6 z&_b9yX&oIL4!5BJm}04n`IjSJI~R?e&o`U-dFt^*#t|4>7Qg@gs=0G460dQXGt2>wN#&IMr~uJIu(_yaPkY_+ZJaOeU2 zjAUVXe_AUz)?6zqmC9DJ7~;CXR}}E{00Lq|z{;}hc^kGsZ}{}|goTxqP#|(op|n&c zD-F~z%?|6y4#*xbn{8)j+0Ov5My=bMBw-~cnXIXanpR(1OEvd_Z=Oo(MUf>6=s-B3 z!K=C&(=}SphH2EbfKhL!#!1lQ;Ic9rt-PE@0}l)bH^D&wOiGX5P_|v%8l_M`m?%ZF z!ylpO)>fuS39YT@uZjJr;pXP6aoSJo-t_ccvADy?{B1C0TH|$Xv@Dyr{1AcYR0C4TFVDP1fx2#_{ax zZfM$@wQDCNA?_)%jo-$Pj(m0${fon{03LbABXzuxo{+`wr$j77pFdC+GgTy zJC6#&t&lS&Yc5JI3UHw`u~;C?>^r>_MgtU7*#)XJ3!P{34)&sJ=Ee;`)-5e|A>h-p zI-yth!{>LeoohXM@ZiCfD_4d?`|aTGwSq+I>!o2_aOd=2)~jI`u{}7x#~NHnKq-?l zH8Ew7JsOGfy8;2dX0$fc%Wdej0f@X3&?}$cR10Sctb&H0K(Q`*JvIO>+g8-!iADQD z4h}x>T7lG}coMb|(W`Fg46aAu&8j`e!h7zOl`54Oa+3uWaGc9wEX=Z&B7h-@(V0Jx z3jn(be{h_ncIoam8oRsgxDVk8INFUaE8^wn*VpIg3tG|}qN29fgL1XvL$wE$h5Cz* z1}2ZT^99O70S?T~_%Tmh> z7j=4Bx>{z#4Nhne&Wdo3Nu%uFWdvF`{GX^SRH8sOpSl~zciUdENr-__Vv^us$?M>S zBo!|GWHM@>oc}jYv|4A~-EujSd~MBNmFi9&t^XK|GBD|S;h)c2O+&@}QG*!__yO!C z$aT-MGOO=6EF2P?hSJn@2}6hJYC(+Gw9&~xHmNO|0{~MC z_V|;CF3DkGRi$wLQ1ZYs5^K*`{*%=tFjAW5qud7skX`jP(M1@iI2xoRi32BFL6WOG z6j@b)P_RQ~8@-{pAXz4BtocN0S^0EWZta(lkE@>o&i}@~Kx0(uQ&Byc-QCT8>dUqf zAerF`*5nVpY-O?)%uzRjuu>{(YI1TQ-od*7!`2$MF9bO}mJJpp+eV|vS|juMpA^3e z=b!j$G@2uq{3p)L-?nzfjENH`qLM1xUU}tXPiex|_Znye7e=NXukx-{&2N>cY zl6weyDPVSVWCSNEDL#zmhP))cTwoe;govFW!^*G_N4c+1cpM9%r_X!37i&21jrL@Ihg5+s*r9Njy|qx_5afhi(l9yBmq% zJ?9CaYG8#Uxjb8igEI)`Vw=Zwv?8W{kkz!p-G%DDQn21Q;;IUHv(%y_2=x=e{@(^J z+GS`_;;gQL4Wxqp{(?A5>LaJXqoLVawe7B>VtwFVKS>1+FPJs1Lkfri%9=J3N9=Iu zP)!X4&64Mj!aKjNuKw&4#vH(EBZRv z=7;L2UJgse*1zMNF4Vun$77Ek_B!IN@$j8jPusC0^``!=_JhE!A9UA3iJ4or3Z2k5 z&Kr{Lmbo-G3WZU%n!(-O*RSdo3&5}s!~TNc5ZHgggE>K1HyxFqm4YA3Ms?0TKI^j- zdJcZPvKoMb0Bfr>kDQZK@!>Bh|Ji>)ZFN@{GWR$Y6}@csH8^_EN*B&O*k(?5%I|Q@ z{K=;rm88z!pi`j83dN6ytE84}mvoyO(;=UoyqV7L#KAj*)a%!)`#Vp5gWbOH+fQG9 z`Q`fc>!Xv401GC|WX;V*)+#+)gvp6XQLf{zU92X6i}tyoC=jPAIk`&r!JCxK-;<3w7bDtM25CAk^k#~w7*#Bq_U~V}&Q`Uk0Ne#0(n~_&B^w2! z898Eso8j~Lj#G!;EiVVa@7dd41$z9geVh<5&HU~fO$JD2zHRJ2{#{l54_6ry$X`yA z@LifK>rNV7(JPwqMx&=d40Z<@NLv+-lTZZMl}g0`Cm0^m{m_{`(b2}+Ktp$_6ao0Q zBaFLG8Vy_qHN(CVi_q90ivj0gkstg#V-o5#*w1Q1MN zvWRff4ZX+n@ddPv8O8T_6&3OEEiLi!6%_)3?${xKU7)Po^sOI(Z|Q{sYed*`RRf`k z7Bx&J8nTm3)|NA**p+9ttb~@SRHjg9G`e$#J!elO@R3p}W`Dnj z3hX^7l^=lv`cP{xI36+;X~l0 zw5R90KvL+PXZWQDa4HG(;xql!$ln*#ythu=SIkneO8OEwtu4nJzpbs$ED(w(gbyDC z77PfX1jM`aI;bYvZ zkC>Te3|*JAd(SaVBsi#kF_K~Twc1|8O=Is}AX2Pfi|IL_U}h>Y6uP?EZ+?jK$gN1L zsp&48ecK*qa+X)lpOGiVox{n=`Rc0;8wMYlBgH-@i(d)cutDR|PEX?vFi~w%68S#H zgz0sswJl983PnRhv|Kqca%B5Y-<0W39c%a$j`e~;_Q5}2YR$u=1Y@A?4}PF=`+NP> zbUWiBll(v0VDq5A(8k8h%0Kf5hK|z60 zAn0R)y~k(3K_3wM#tJZq%t52byC!9T$pR$I$8Ywj$y|8Meu5dIcP|Jg=;<_Hn6tMh zGb{>97T{Kyx6lCznImCpB~7G)$hjGH+E9EOI9eJl5zhI2zzMSFF=M z;&sp)z#~d$XF|&Stb8d}=-yC!2%J0M!RYO^o|){?CzmHBB?{g9ApK_|fdL+mLy$UV zHT;wWI$gs|OM|+pIMvdXrKLw&!Eh@*495YMBKK@s4r)R}UXfInmS!CvF)gjm-Z!#~ z2+`5jJY=7wto3W>i5N{kG=2X~Eu=k_?tKC9E5fXR#RkN{26%OxIpyDcMsZqlPEyq# z_`R?n+Okp!c!@PB&OWMt(~1?<)F~8ok7p3>+68AL!!g5fEb=Z5rw58p9?v19-T^PX z2_FPh8vGx61P=>F$Vmc9#7NjHgsMGOZ*A${=RG}Zq!0zNohXk=CM1nweX^o)2W&D~ zE5RKnmOtxV=b!VTe+>Mj??U>wRtqQVkhEIlH~kP3YKZ-iPvDwsgfg>z`|Kx`Ilt@t zSq05Ny{s2V%Mfe5Ecj+FLA`7ML=0@{ZtAQB6?e#DuCO>Im?X zwx0a4gE}rs)+&pNq@Mr5QIX`_k2Qi&Tl-5dc+bF}3u)3qVFySGfNFe&0zAh(x2|9A z!*LxJ2XZHR5(&}~`>x&XvDtDdFv=YSJ|tK`K_nQ}QaZh{vF=OoAUAhn94O$IBq$`3 z-rgg24<_NA-!&Adj>MF6a>2K*_Rh=Onxhen022`;^D-(;fFVYv47zHDG`H@273w?zewyyL0$EZFi3BQiwZ}Nhm-& z5lY(Hz#S$eRbsf(I!2%#$0_+lqHA%hD7{r)FLK?3@4%ZEeN>W!AU6zvZ;#zpwCytPniiR8?hRn z9>o;Cx##rH%?+Pbw_I`c0<~+G-uRx{w%bF-iN**=aC~mskR}h>^%9O4%HO*;Osq;8 z%S9P58ocadfSV}s18n<(M;W$kc-o`5K$6l{&zI%Zm!*S;x2XYZP%0bbN^rN@_7x(v z7+%$9N*6;4S{hBqfv5lx@rSOw!=psR4KvsdyU?%p1~?MT8AzcU2U47aijen3 z6ZH5-|Cd7V2?|08{eSj1ia68f6x6ymDkh4bID%&Wy_pd}HJvZB$GhFiJI&W0;!W*F zRO9Ol79C2w^yF>_-t_`OzG4FP^d}GkdaINIzpli#+hh>Sa4E3(0rx{6yMGD$%Jx0* z9y+_ovKFhc&fRhEja3Y|_k8T$_py8OfP1V|Y8h>PALM|w{q^tzTaR|hu+6cHkKfy* zfx~xayL0UE)4m({31*orO*?< z>(?{AE3h~={mXm2U->ip!S8<`+wXmd$2|q9Q=-S%J%|S$WA{wI8uqU81h)s`0sS|g zi@mX;U+ep0vad($(p|&)-6!_DkMOvsU~cN!8;|wxjYsO;ye`Y zi=oZ!fm`_=wE>U5-~EIA?sNL?sX}U_$A0T}$Kmm)pXs@2eXzLnbA)?wPOs^m)BL;? z;R|@&ixvD^yGLEb-Ck(-R)SQ-G6#V_T*vRSHLT7Ty2ORm64^SOvaAR_M`0w zLHQjssbERC`W}_n>F>4`f4IjA=fAq3=sbwiVeAsQa@k62&k0L+Q!Dn25QTCOJRTYq zV?f$JF+a}H@ctH_;#h?;LQSFLA(WZFq98wgJa~|^?nwx_+@TG-(p(8<9A~R5EmdY^ zSsD?61F{X*!@iZ>ao`(Z@A>)^I|gFmD^{gGMC#+OQmX@Rf?*k+k+T$@ALmU-u!Hje z;PEo!F7U3-Co=7ts9ui}BT>5g{%LvnhdaL9Rk`A!2?2Iituks9R*UKS zWjHr9e_PR_4UCzYC*TB;I3+NHv$HJHLHcB{t>%m}j3R9qKG@5Cmgr#r`~C9mpvwNe z-#ikXG}88sNWuTTp12+KS5*)f(qDJNbVMB}mnp6oiEGHNbB@#d8d};r;d)P7`ROUu z2=v!z<<(;XALLP#E6GlJNT9>9 z-I|3tPd*7A&;(6;9Z01w&#Q0zgwyOdA8p^Z16;Bkx~7>ODlgf0+Ny|~eoxMXAyM%f z#+EmGgz9G3(T29O*BGa@Vbg1`fx9C5NY6wWih?{4tLTpRo20RikaG`AQsh9fy-hE^ zxR%%guA_d%f-@8fPsn}VTz#`+{Oqcr*zt+OMCyakGf}t58S?X|M^PufDs@E7T(DsK zwlCoQT&s-=Wlo<&H=OQf!iQ+v+il}9jN@(Fw;zHlOP@ocyn%3-RGVw+!4aDj9~UA| z)cSYTY~IX52~MF{{1l8>;5wMN{MRK5xIw5)x;mfO_Pi0a>fRK4S94wE;zhIgCT=fb z12vR120jITACAa4a$nqVR}H!m|Q zV@xbThK!L>T7T-ASrX{)vRyJ=x=u05!P<}z?XC5nfI4Z{uI2O`@6FQP1k}XD6|)UW zh21OYdOb^RE*iACc*XCZTW&cYp0^o{;>~ZpzLBCKXc5LD9T375kwDowISU?tmS~n# zw<%_$QBNf*jsWAzIlntPUJdVD7x5emzpu?e9U zJ2Ns8)!sKOU8jvUwNol$E|JX*G25V^xv0|;1TiF2`d3q9wD_i zkp|<;My+QDE5a4L@6;gpfJn|pA-`TUN*Xm%;M^0=Vyqno+OeZ2rKL4DH-dfK)RZ+B zEz9tMKHEvFEdnpnIx)n1StuULrE;mm)(zK43dW8zUBqCiWN)&b_hB z#X4b>$B_Ev&zTxw&3JfA_oiKkzu&&4Y(YkM)*m)m*+Dv$cVu3>tGcMW?CqVMonhzO ziz+SM;z~Xhc_WgOuM!>Rt)&`7YtY3(ucp3!*IwwqVAc<*uV*6^*|Xv(yB6&D!BVN^ zn!{}CGGDvt1FI56?DXDvXO95ZNG-9I3)hE-P*<*4tl-CYbuWAFdGI(pc6zHC;!g#PA{Y+>%%}4GM`6GHPBt0M_Ho0nNK-Mc*kkmz)yr0M?_YJ zRRlX>T>~qtsYy#y`3JxuYIb;_ouBE^s7b)0MVmJ>rgP3YOtdRv$Nb;b)S zVv3E}CtefAnD9dfS5yG=rYBY}=*ltp1N7duGhINTdvXC0ss~U3{37_pM-+;3%5w2C z)kD#p<%$(AJhxhakp&oX%drp3sH-=OH3${Laj^rwGG4b?%RcL%^y4A28=+(wgsW0> zx}}3~%3Tn}v|u9sZ4(9hMmIQ6u9OII7zH|%Du#)QJFQ5K#{-U5B)gk_(IP}9xRY0L zy#nh_f9dxCp2Z&qG->COCBI#@6xv$rVV6WcFNZJ9zAp!pXRy6`3pjdjeNeoq)VH$<~()o^~N6#~c38@(qM+}J$y3(CBeU$e4*((lNP_UO(5gL_{mXkG- z9~o{wsSKLbhp;7rXxepA>asZWddhcL0@;3`Y4*xirmNZ#7k*qr3bvTg5gD_yX7YJdg3YZ!K42Fx434%Ri=CEhnn6^V`A z3WXQ#t2X{vL0s@<^YtJ*>EOCDd3;lgLe*lQ1lirM7B7N-U8qer5ufGJj-udrEu~8w ztu)!}<}SP64U^4uP+S+*AwOO5P6jkh9vrptZ~rPO*|u#Prk|y#ffR@KtdYRsMu&6kXLZ9%HE#X_Z1KhQcQF;!6dTs2?* zhS>LIxDs45e3dJncw(u}pw;W{nMS<^L_A6TP{?d~<1Nt>H=%RKo2f{Uw{z!2jGCQC zwDQJ`6OoS~`7Z!i09gQ0nM=P|WyqS*K(iVrne#2j}g3cDz;_L|g2V>s??E zcV1B2Iq%HZosMfa{NR1>NN~)wCD^cLMyMRk7?3^f){G>DrJ+)^!zYw{q2GnWAP+%} zPE~ZiE3kM5ztO~uLQYLbY;4DIh<=Pca-|-9l*Gotmz@e;%c+sTg3KVhvl*z+>PTL& zVBvM!HM7m(4;fKdFmq9u4MY+-JS#K;o8j=d%q%6F!rq_!^UqG~ux z<7ZeQN*QCU{eJKMW-P5II^N%l9y!rvb9MiC!65AVpR;!hpvv= z_h-0XBn~I>Sq3AK-?J%Otah*qVMDfM%gy5lO@tKWSKzazrVghwC@i#Z1@7)$fwiHk zn?g;9R@ac~MqOs|86J~9tvz;z!z3yM`~0cGjwjdA|f4&;k`L?7cGC5 z9c8*?wOTGoM`p=mrp(Nl6>Vm+?#0;0*w14FKc|pqDM*MeorJa#=XIvW4ZGpd?r95v5(q6alTpXW~MsYm9S z@_&0L?&BOMgqG{Ys4oNG2lRV?qu+f@zx$AW_x<1ZFAtl85OszxU)t}!FFoHso*XN) z#|UUW?mYX)^WEKZKMWo)J?W+i9`8Iy&hy>C6cOJd&zgCrywjb?t>gPmXYuUE{`ZD{ z@0I=TC-l3I>v!M(eSi3q`lZ+QyYEZSw_1!BMdrRpbMkNEJ$g0Nlm@XYm=DytxChc=AS#VH-UD*J=lD0E0KZAdS05RG6`&zLhK*Q(jSej~ zyS{5kgVl?ob8pKjASL=Ax1j*r@vl+9*J%rd(sc{dqELF2DO2*@FD)@Q8Z`B7coQ2@ z;*?YM@4WL){V8U|h!IS*&++5OeWEj9f|3EZc5uoCJiFaB4=u<8bDSP`p6l^{Rtvr~aW&@e#C7R*HN2bWgqj?acn?Iq z_athdfTw9Z2L*z2jh}&Z{7gSXT7SpW`kfFq3R;sH>jIM z(beCausP`)wi`Apv@q{jpZ^^;hXI>^uBQBW|G$h+e-!p*f^*`vQ0w)7beowLk2{^m zox>YL!NbDBBK_KzE`8$hM;=_ie%aHjR^UAI!c@3mdLMp#RxfpCP=CkA$qtUE z5lW*O)buk2(~Mt$D+X#_sgk)|>xkNfT*@%Mep0Eg+&4U2&{3I(@~EdXXdl|g_vyRw zr>UMW;mVb}^`99^EYEmPeZ*v59`VWClXE|z#_Xr03hDz&k@GS-#q}~($c@xkR3+VY zkJr$wtgcF3&|MVyP6;3lmql9_j zf%~5XTUfbbMO~fm@Hr2}#rgUU8wPWp4b)%gg$py_mGCw1g~J?Er#e{gj;?1 z)JNXGedm`nh5odo=;xcmmoW-OND!qtohlNdHvh(}^hiM1Plz|ESl=7ES@OsA{0+5^ z?+3yODvXH2;W&zFN58dGVPGz1k5p0@z5&y7*SR`tPApNf26F>PQT)|y-P$Vmi6M;W zd!pph=B?W|#AXSjg&9G#*kB?ikx19po3}JAXylBKpOsk2*skX=f}G`~s&NZ(8eKsM zi+8Bfpn|-{#?Sw?8N85^L)M_^q{clLSR4ccWs1WFnZE-;^3Im- zD}r7(8OM?GAyZ({H76^1)?ECb9PViNY`epCuIp1`O7cxZbyNG{&ya1e(RAKcTyl&Z z34U3S(nqPJY<8#3PGW2Mt5&YWF*H?eZNaJyyh!jf?!mETe8+nH zTJ?3+0Z10RbD(aX!W7XtjL-+1tS1|R)*hUnF)@=^7065t|0rfGCmKEk9)8%^aZ{?T zs9>YO-_9Hl9#yPP8$!aQ2gR;kiz?(Q&coMC?f12{B5#4L9`e}nIXTh*L(-xbr%`|8 zXu(4LBxw^^k>y>|^k>(;_&>kPy>~7YW@ZkfE*-9cyYE9%7C{!(s?t*MYEDgAnY9E9 z%p}`SdjQ=(^~E{R)7Q#*YaW-(-g(wrY$vqIDCvUY^%WJ+z>}KeUw&Dk5akWe;@yO_ zwEGu7iawec<>>qY0+!FV{~Iu?zG`El(=*dHY}k2289g5?%5?eR4J%j9QkwUo;Z02P zN_K+OPpzhJ5TDy{2_$8D>=voRam@jz1G)g(sWdm&*VZ;((M?BHCsMJglQJd^wKYM& z&>{40KFW_(4ZjCc*4Z(an#$f>_vbC|{IkKSoCB`zJneG~?*?C4Dmy0=)7cW1vvjlA6@l-DLs?ZO41akb) zaXjQ78#%~upxFCEh2Do9BTq}6Ed%rQ-(75gMk90bC3vey34eiC98$*I-ZBK(!S1to zQAx+9viMpsMqR)5dQ+vLUgYL5;cOK81V#gYhbLsL!jZx|HNK(Yqd#UMio`13UR+ku za)MHomv^vmFy_xNE+%;N15mLHSh*-A((hV#9p+?lsl{6(l*@7I>?-0BYEJU_8JId* zvGNn2z`cUQT8*yyy0f;$d=QiJi;fHDteZbHvcol+!78cC1(u-Adi65sJh_@M9G8ud zo&*L!IC#Aoev`Kpmsq^SQuL@fU9%YBOyJD1wROdce{bK73bq#%AY2EWIu;NIOYkU5 zZ1e^t$1YklZ$aAVBpjfkZLKvMUNWCJT#0xHTxbW`KfY_fDUl=0NEEo8spHTYLqoN} z4%EZnu;LjAS7s~DHDGE0sRcRW|JQSw&?rnsMhXOCYY@YNm1;^`AtM(22Ha*ggAIC@ zvpGQ1Z#H{595&8aBGAkA^Rt=Ej~La+xtPt9>`i5V|8sHizv`}Wb2(pQ+WFbX|M;Y) z9&VP&T#iAg3|*4uTx-{o{41NgzkV0nQ@c4Brb$DMHHTpWezK$ej6@ve|K|LVpw{bu zhJX0qNJC^zVQ4fHgZ>)9v~N`?T-O<2L?yG~?{$}gRXQ$U_d4eY0EHOj=sLg7>wK3( z>A#K+6uqtm00#UHSnHdTlcDcg*`nm>=_EYYsMRr<3$#kR{p>eHywYL})ODY6DAcUC z6j47?Qi}YNBjvX47O=06bt~3UJ^V}|c3`n~EbMBq-XUD4?H7LPR0Uk<{tg?@{?4Wj z(|%kS&-p4k+D@}YJ~t@)bwpmZ_pBRy!)6$Pjl`g~VgSh=UkF@v|YX~Kx#LPLUB5{swJ_=TZ&{&O;QP#^qYK3$nFwnz8Mxj_lbi1iMl8~5hW;X zm%6*Ux^8L=LjvTcm?iVm!|aFApe8oJ2x)QC4FiO)QVA`Ud9Cxha>+0)^sAgg9BV7BDDwRPGJq4A@-VN!&N#i+a44tL| zu!EabSPe%q$6=c~)U+S_VKX&6kCi!;YR21(lC77@Xlbx7b$y-2!CW#L&nv^Q76n;l zA=<$*>sf3LXN7X6qnyZ&ZS3Z^cGNYr1HS3HT!RwLX8HL~i;Is?!$AIxVinOkrn?)g zp6k~v)*I^rd!*89CfHpnENF0--CwZG@dC8wPS+iJQ^3tcKV-SM63TcQAHKi-k>y8|e9O=l+G#HZd z9*foa_*^>x@@=2d5)p5+`h^j-POG^+s5@`TRAH+TG;@8< zv{E@pKPn@`$0sdL<+|K);J|?sm(}R8b$7RD@O2_5PW0;_v0rD+vccrH!I0xn&zc4Q ziS9$;zL@a2$(}e-b@i&sp(KtOpxqT3>gBj}(x?u)WZDDr@u0D}(|iyYT^IZVI)6Mn zWs1qv)m5X(u*j!O(d*ga+-UhQJ`&pHa!4ptpK-;Hg_=sd?j}eBP$e20B%ZBCKX0E~ z%O_s3hG}lx&@?qUnp&q!89qG9asE_SNbrrTtr)Sko*pekpmCvDSu+8{8nMG0@uX>%O=r{E{yJnJV&F@Hpx?+RtqE zL#VSeot;&xNhSsyJGhz)x%|`7<8qm~yAjLqeo%V4GiP+lNs}gqMTO~EHD42q`8aRu zs8MiFJ<8{23goEGU!%Mvx0y@%kC^nUHLD(*oiHX5H2w&^4{h)1>G6+C8XFnvNM8B) zy(9ci106b9ZrTV7%P-rH-X`Oq?&(p-#YNc9o-hUl_E=gVrayZ1>Yy02IYyJ2IW0Oq zI_|0@DsldbWsA}cu`v(|M5!Iu%oi?Pkc7t#3kmSE3}5=-j3}z@OH^pS zQW8HNC?733y>H*XBOM(+KF5y1$Gf+;*WFf<>z7riV~X248WWS8lz>GoM(My&=UR^w zoA-6~keJ=OnHZcIr)tc*$;t5~$cQfWl%+5<>RWby`EFS$_7J7QDiEyKhlhvDs4J(t zG$B{ad(q;9SFfHucM1D==y_>~=F?BFYT!a) zti1En`|lrNIgACqRXX~9HtCmO?k{No*Lxp`_5Ya>9;n*AwN?#K?fAPG=U-e~Zmh{( zBG5>`lpNy5S{m2ftWf;)OA6;_d^GwhpsudP%BV)*v^PSY7-lvfJ?>Y%V#7ELW>3^%nq?&=F@H8DG zq=u{R27}>-aUW>vea0IG0rq^fI?fi60d7F{bOcpS!+EcG)1Sf2sOdT{Rc+t4$Lx)j z(c63k4s74s78QkFJT4V9(IR6~AtGL?|e zDx>ohs_SB{wM(<3g?=J(5&E4+1zBMx?)3Rf5)<7ATcqkt}2c7>WYpAkDMla@|v3H=&r7u96lCLP7YpmbqTOJ+BUDY3=ZeJ6Vxs4 zPiynj5Ui<1ogh-YgwsI5BiLH64O_RukG!)?T1AE802WG-Nr0S9 zMT#c4Q|PG2;MR9s6*-VZFD!1ru?e-94>$B58wB#}1JQip^vQFMuu%)9QY`rdt}gHk zxOVN@OZs*x2z)URb;0>FKscNA}Yz z*1qto39+%ApHwt7RDb>UyPcg|{_%Bn!=6t+?quVj(Efg9-J)?ShPrXCz9e<_;-yQi zR*5z#t#1Ff<>k4#X=BrB8qb0s!LO_w{8s(kobkz-(-zIu>+fAOEi-w-oO|`Htv_s8 zxBm54zH(|T<$ryB{kkoCS^;0->}sq9kX(2a|8{>}M$%yT#9q2|@$A%+@6I_HscP(^ zy2|%q?ZCtLr6}GqnyJiLp2Mh%3ryVZ*Y`ZTVp9cUT3W2;p8MdyCL!`GB$ud*F)<0h zulFeuOOTd->OLmG7zs^**FS(?Z1;5k?Q1Ei2c#@5@pMKFS9kGAx2FFSi&A_d14eCN zYBDlvc>H&-rI_C)r}LUPi0*IQuX!le)vK*M6hA=yOCf`(rc4pV+zQz}@7-J*08d$8 z-(d^DF)4`Ab#xu8XXVjcyx!=*pK6OFW_zG8?&(MyURH*61F}AQx3s?Lo3i$HtHOX4 zW|$_)>bThMkyU}LBBWEdLP9i3>j|*7+Pa$*Qgw7*-b4fObSBl^fHkJDLjBcD84bGOsUDSZE0wISN_eb9+YJU4rRy*rsblHpGwYZ$&AVZ#`IJ{# zS@HH=ZjiAsmzQrKK)~-)Gz}ItTPPK&L2;kkt0NMr8{AGlrB19 zm`=N7{>*Vgj=uHAl2xT-GHQg`3C|5uZ(d&RU2JKIR~C4acf#ALs9A(LB@VGRy>4E! z+H5zR*Uc?0&5Z{;uh@Iw3Ro_=z(%A-UxgYl|Ff@dR}JQI`m`+2M%<5R2JQk9vmY-%~aUsH@XS(#1z8k~=c#=6rfEiGkRTUtEn6yl|G(FZ24#I zp86f@PT>AhN;nb+A0@$0xBgP*JMtZFJ*I43ToT(wDI>;Zj*D=09lLX%J%^Ui#CZ_D zqi=iix$O%!MeIfONT~CTR6D@Ic3ilr#Tmux0!Q!P_Jz=|nWP3Jz)yZY>l2r8KV+fz zXT+`Z4NA{m(-E@7dw* z1J(bW)c;;+3)W5_8O148z`IN6KTj9rm*$tsUT?})kWu0G>p`C0pygt!{8BkdXI-;V zRhz}7{QnEfK0#ki;W2tv*0glb16_NYIU=*)k!~RDR}Xyno5G{~l}nZzLEPzYOhVWV z?)3N4t5x0o&VK_<5A~f+ioZe4CHeVlAmj!*asIV_!ND|9#Ik|P9k|$D3QSxX+}EQ- z)Fz}UA)%>hLsLyktVNrqt+vKDmv>Q(taM3q$M$TdtVj_XUEQi`+1hSsuS)vOx^x`@+QH7{3Y@61D6^fPfGo{lZa2>QN*n- zlLxHJ-5*uB9ujt?JNHUuWlqlWf+*p0+Z1H9Q5)!9bchZPDbu_v%8zpgvqPF z`PRSTga^;YZTO}PIDEIA)^F`-?8+If8{Eg(k@WGIxSm*4kd(AwQEhcvW+|a7wzsxc zmSp5L)+|_-oSa=>lW8_Ppr^q_^3&-mD~o7+@n5Iw?#_j8Oa9wUZnN=A-Uy>O6FosK zD~hNdkiEinJjY}4#u>>928;HVmT_I~#$_S9CAAEklgN^v0ZLpB1U)=bg}{hAKHpti zw}&tV?tkK07KK?zVIyx}7!`B>ih>+VkMH2%Tlfa?&;mvCTI>((%-H8JGFcx=lCw&mEP<5j_0?CJOTbrl!WqkQlW?WGbVA>$Db?2 z(`gGuXI1sCWa|YD48mQ|*4CaASdiyHI32by!6UK3gfi!9i|Av=iV!q&AtE28)BFOuxve>UB< z-0QQ^IZc{$>hElTdvRQm{O(7*HgGwZ{rhLmETV@DDWW`cYQ&u4f0Ek`!Z6a`LRJY% zn@auNb=I|<{%rIBg>tp*&n@}6`@f=uNu#&#Um(5d7n7VYE;dM2e@u~-I4L2BmebeF z=9GA~^iJbRd-PQ8(3!(f`umVb`OR}@=ZQs@Nqs4I*^Yd>`C10;yrKRM{4Q=p)ZEX(@ zegFNT;(xc^G9YwffJn7sFu9)qlFe9ZEY%rx#(Z7AE`a1{d+`0C;+N~UK=gz3zFqIW zyX(ID*g|GsW71ebvz@Fq;>;(j2IXLdb%47wi+3~d3P#P7v$B{Vee7)T>E}f2B(|*S zlarDf8~4KbPTl^-MyOqCgT0wzC?dYu&Lkk!Gs`LFn#E+Y$%7ci%O74^dF*)<@J1Pw z{@#?`V(pOYL!s>ys+V`bPc#M3mj+wsX$S#Mb=s(CoXDf8HXO3s*ilklD7X%Tb<%bO zY@lTRs%VGtEM$UbjrM320cN$fmzK6tL!sU?lxi&%N_zsOjh4&(!{WP5J#zV2#HmS+ zgQL5yuAgeF99~zty2>GN+JCwWQHa1fKhh<^Y8TMOj#g`R287H0yewr{WK?v3-2yM^ z7VAZ8_S{F8R@5D8v8zKgIEClgj(k-9#UVyFJy$4kHcB)!R%IpQq-B(9P+sE5xl>776WDx!Vor%EA@D4zy#gqGO>fh&0OU=z4H6k^VvfAXPZo9&ILrXku zC={h-fOo=RAXHFC#}G(&?_Xp!fg^Xe1D3KzBh-=H_v9$e$X_qdoO)000_cA($-$qj zkkc)j{`OCBd&(L{{44oLem}80-SsfN;b4)pq*c-0Xir?v zVKC7iRc+W%eIBeyU&@-BTUu%|m6m3Jk@AKlw{BaeYq@I%_jywCj}kbF2uH#mvrGnM zKB_x5w%eAUkKg=zqAd+uft`Gh&I43=ZEf?1P}q30(vnW?lht;{Clc-V4C-a7LRMR= zRFW@=CcB;bhh*`a5MR`;3%g=Ie;C^R3Pt_iFH1_TS86vkH*YG%ZG9Q|wn8MlS%7X( zjmyb5T@Q^X9T*>vKLrID@uj8Ph}WpPI{c|Q&j#ysUe>Z5sKh=_T2%0BoT!TwtDkw| zi8Wn#(s9{e92sF15a&Nx(P=s$Z*BJC?8V!ww^zSZwwz&J4}c#9rjDv(T1c?n#f$kh z{u$H*?m)Dymr824Y=u?hi9r4MN0&tp8=EpqbOh!9`-N$XA3>O> zufD=}Cp%8Bf>&@$fNI$?=;AI;U@ji`vV7N3V~2ydmhz`ciDS)AkJ? zuD;pbE$9OFar5N)GfSE2-?{v_k#%2z?&g}~U*4i0HrVsL?i0TDft!=^pYIry?s{H6 zKBAa_Z(eTRLfEJ+%p;eH_T#K}!UV()($9jHDSGc3So^TPRHCcC5Is;&!N`E` zM<*sugXe-ge4bWr`#v%8`@M$`AKptYwq>}UcIB}e4^THL?_NN6>`Ql!DdBbGmwLN# zFx-0`JB7$=>}|2PTi=mgVLeQ;_?E}u4nBX^+tBo7RpoeILX-HF=;$RPRkZ)dcHiHh<`}*DqFm7-`ne6<5R8-OdlO_DTEdNA6r7~_x$p7RbhzlISnp^z?DHc?>WP8(qb=ddWz7!` zjDb5AEZD))%J>CTIrSE0rj>LGol8DcC-*r`nJ6=5p{`R7?z531pAV=edc_KXPDq8b zvS6-eAS8)75(IwaBMBzO#z@O|l$UMYT84kpn0eb#RxVdo6QFDqpjuE0%Hv8-p_PTy z3a-uZy^sk^H`u|1wh7+h2|Jk3Hw_ayzt{rIXRsPASu#t{!AU25K(gFnCWe#T9#d$b z+1Q`=*O{*0&CeQcC2^ZMga+11(E!6B_~OitaRR9m2?$mXa?* ziaHt`i$y-5ke`!?>9})t6Dv*R&e&z{?~Dnn6S@&-TbfwSENJc!^?lC z?LBpoy;_!;pNYN(m)WpYztxaT@o|VbuA$k^$P{YOwTp8nM5$zs>sHelvw3TIeaG$J zut~|uW5<6&IR_(;*zO%C9Mr@kU z3J&K)QJ9;g3i!%gMlUa+2MJWJaSSB0Wcd(7Wd4H;$D!>ZBOrfU$A&r)~IWrzr>7{l*mB6QiuCI6{p?t&>8OK0j6v z_xIMG7}%sShbx5|&!VVEJy~2Jz#@x`u!J$ZjE3Cf$KPr`f8K1B1`!7b(v}SP5L!mR ziYN&nGX0t|r(KAjo>;X<)_hQZ)y^nzHc-nL`_;<@5vFfGG(~8vJs-@EF{{Si_kJ`t zcSwIoX0M@(=nelyAm-O!f1iXPNB=3@0j~lBNZrUUx3uCaK=a6|RcNV$Q7Ykz zYgc!`$|-8cCWqZ@w&S1r;gwt|JS0(4mxeNR?t5&%y%`%WNVVP#x8FY9xBI&9SsW(w zDiX9r#$;!2U9zOYAyaI$b&+4L7TCEcd0yVy`1rMXdDYbjV8~fV!6sATSiQQ4Sti{o z@G6K63X_wQnn!%&|4x$FQNl{pZ@vjFkTh`PC^f&PV7w?bsO6lD;_X#cyRJCGN5{_r z(OF+F#7mH_zBj>ExqUkus7Rg=McExcc9}uzTP(*vLh+Lhr`TJ^AFo_Zh32S$(Gj;y>WTKt6P}_9M>c4r$2$2>jyuvF)N>Ycw&ShT7fa3 z2S>-J;#9C?X|BT2(BM*xfed)bSexdO5I>u6A{atRup7Ak(BdA{%cKbX)(^LX7+DC9 zoD-f{$f+6e7D8lYRV-YH1#$a_TlI01a~HC#PoDx32gQ99Zg*V>IMZBXV2XW|+Auz0 zB90Cj2~jv=Mm4r!s5=|K0g?YrWBs>aMu>^wVL}Ovr?ibjo1cu`jWveR<60gN#0K!ibFQ6mz2{8OMoWZTJMt?FkWDjjKC8 zK2jTqyn))m@ppRH-hP46$o*q+u8%{!(o5~IjY8xy91dZDEzH8(^|1SMoMVGj9GT)a zS7}(<`W4k_@O)ix*l?yAYdy4<$ zx^Iv5JcDsEu-niuh3Y$wcw|05-Nyvg7hLRs2=-)5Q3hM08d#OKAGk0p&P}LJ?KWhTu-`@D>avtO5K4b<;SD1m+aCxpEBvY-#T>5Y$UwPX|6TSvs5JY zvER#e75VuM4T#KJ@iHq5d(8A9iJe&Fy>@M5V;W&_KpQRxISLJKvTf=%*X)pq6V*42 zyLaz4-cV1x-L-(Tw>hKYD9az(Tz-6;-08ks&mEqpI`>|7zeZV%b&Z4S>G+H;^Ix4HmX#`uTOKf zxk6pBu2{Y%6OoHCr-d%sr& z$w=N*st9D<_movAc_d)SqZ@yytSUvAlZt8ZM*bA)@Hhp6B4HY}4WA0?iaa&3x;iZ- zB{8vD$d^pY&dYmn8Jg?06`{`-qpi&59c3Uz^E2t8bTXYszd(H|$<}6PQlHY#({t(3 z^e`&ly~XX>h)F~J3Grgz^~uSotjy2Ko{+@)CR8J0XG&Uibz6s%a=JojnKrn&;5 zC-nkdTtF0s>#0k0PA4&vZb8KEOH>E7jd^PE*4L(D7!0mJx+)qqe;x7QF$4^TfUl01 z`E_ckT&O35dWz#hBZMS3i^xe=z$R~kO`aX?O**;{y)xCMSclQ3+x!-@^_x1OGOIG9e2SE>GQua^1br+KRfxE^vLjW)ZVHr9z!FE zW)wwKqX^k10dc8Vrmomnp^gn6q|pT1ne>dXzmur<$|j@#pc}A@c=qjq7DXxfXg|TtIyk%%;1Rc)eyHVHZ90 z8pu1Qu8vAAlBJ5&zA`SZw3K{9mC7ATWvGB1MBA}YJ@%(-QMLOcBKAYxM`V5{PmURL z5|h7YBQz=LjXi(6Wp%|UhlSEoB~dnGXa?HF!jEuKD52Z`1p%+*U+qhvYw5jY`d8&t zd8TWI^Cf4w^O|c=;dED+OYS`6e8>5cYeo^$NS1Ipe2~K~?VbHz?~%zrji3B3>#e;_ zW|qVgc993{J1r$#yT}Y75VHGfN1dbnzy?`O?UdwFxwEOA^lJJsdL%pwdBbUP9!Ho+L^E?9$Mp@D#5IG} zKwR54bZAKl>73fH{{2BL)%rkwW}3Jn60IG-mX`Q<^1V3uB0I}9#Wle-%r)5cFV_qB z4#xEa*Axk>T04u{jTNAU>Y|o_q+f#nEx6y!EkwL*tE6OT|8nxIX_@&Cv{JDj{QIj~ zab0qs8=0gvgfIVc;hl#>HgDdJ9lc|Gn-$(2GPgH#kc;lJx4<^svEyfYY!0a}rCZM! zKmR;pz4u9q>`7VJlR90=SP`%$I6JxBC}if$N6F93nN?M9lOK3=685M0%+{)`#TnE` zZhI4%Ro(?z1?5%cMN|Qf*<7GcTB^t-ZZs%47inC6D>k^dm|VMSL#-F2etoo0N_|Q_ zgKr9lRV31VA>FbP{)Jo{T)+3hMpO?+Jt_4pg$V0#k?&Vp+R}n&o(8;s}I`7;M+jsQ}sdv%%Fi%%1PZw?RrzzW(g_5 z*AwHa3$69-O`A{oiM8AqB-B%b-j*m|Pk7qll!ZK<<@L5LtJI?I?9tiMl{c+1_yWH4y z(mDlV?kA?l%38lFFaPEg;WCVwH7{MK^Ti?S=?+WR1IH2Y`NcPCR+XV^~N7b zc;K^_E8u-2L zF72*8c&z(6qET@D{0eG2MJk<;r4J2=o`3`N!ra_(=rbHy(cqN9_6v=*#&Z|i8^PEr z`@D<@Oe(9s1dp!vgglDGUI?-tuV$*N_g-M3h8e1<-U-g$K{FK+89ipCZqOigke`$? zVJzA^va$hjnA~=%y}j{Z$LW*Cu1l6{zPh?blS8GCPZ=|aVJ>wZ7J6|F>BV8HVGuv>6X_ z2lInQTcF-%yVzOtDbDG8j8}SL71OT8c%ndcno|BH5kWe z5M4H9q=vabf;cxGw=fKPpE%v4ZvsDV(g=g8)I}?eQZ3kPNk9t^mw0#Rj zgKyhRHv&TSCX@M+>D+l#?)*8^C9}!lusR3?@Fr{yqY+SKcB9aCvU7ySN7uKvpSD`; zO%}6LD%F&2W0;p;uCBHjJHdgn*`_*gVqIS1y?%X8&ieIJT}xc!oY(zqHUy%;SFK(p zQi$n*7M_xJAIA2+w3N}|C@Oq(%H(-Knt78`65+fgkqt+H6vlqJ6Nq`@l8shr>k;qT zrWy+K$OwB2R!t69B8jHBjP@pq;)Kp2^p0}G2y1imPuA4?QqO(+?{Cj3{i(y0f8>a7 z&+$+AoE*Pt@nX12;`vQ|>-OTUi?=csxlPHHKe&FJ{pbn0*NB~SCQ za2%qwiTirJAZNk$itXO9o2X5(Qm*`d>#Q6pxHJ{p<*D13w@@w1x2N(c*P^ClGcx2# z<)F9;P#LePf<9r#9!!kHL@=Hvjz!lcj82Ll4HnMm_@w*547@KX01V_{!fU3BiZWdf zfYA4LTAUY&3&iQ%0f^KYp2Q(o4aMlm=Ar<(cKPxVBxG`NaZ_u`JXlt>xl!H zOoz|gg(N(VxVOc9zb9ISg1G_;e+4ecM|2o&?hL~nUjJ)x|LOl++_CQVxjUSJu35BW%HHH;ZS!fJ*SMgt zGsm^b$$R&9Cx@N3?zbAlCUx(nY1fVG*RS7jVN!be`1<<#c+rxpCm@MGaaE#>g3SaS zrDWIn4v!vj=zA(T;qcKmHsHq-hZDwA4NW5=hEqK~cE>uY#2a24yd~>`9QK|OBO<{H z;6PX@MdXOSeiG|QxFqW&P=aD*(0lr1F8qIHP={P2SqbPuxVkK2@Yqy@E3Z_Xx<1Lk zNxnkB8{jEq_GAH(NFJr$S?8@-OTDV#xy<}dFYctE5#&BNFY*M1&t7U=Moq-Yh?Cyq z;>K5uH>SIupr5jG7+!(;jD!k}t?MZExuad$VVHKqv~tWht6aDdUfC4;_a8pdbQDTr>5x|LnQk3*U@8J;jdd-h z4&0^&?xo)D`fhN2y+Eh;ZDtj|vezWj9Tn9<|I(p~=( z*;wD=x^(K~$&ohB5>PB=D0C9dHneCqXtWQc0xK+(khV# z&gMKHQ-yIatWtzvf;z4{q^ckvr_<@J@RbaoGQ#IvW25n=Lk@ek(Xqq!?`h=m(S83- z&?hu?HhF7}lu^s?0ir}dwT?DxxtZNZDWuk?)-%@F4xUozLN5$RWvkUcOJys0Dx3Px zXmpUfznDh%$P)8Q=z21P+-HjWwfn3QXC>i9D^pTxYPhdlPOiW~p;B0X2(KL6H@X8? zQ^A*ITyyx*AsSM?$;s8#DegJsw@FQ8qf(EQ-i}*glKDGDF86D#Y-;Mf3{dgYrU5CY z&lo{8T95uHOGuDiHoNPzc2$G^6SZ1l>$I_T1J%S%QRmNFwsJ|?+i(4Ib4o%GB~j_U zTgofCySIN)Q@MS?(=R;5>$r}Yo2M>bydW>C^~aBj-{Z7gVHdR_lc7ZYivCm{(JRTS zCi*3EqFaIwbWAwxgEoiKzwg{lHX?td?c*N>8^#|t>P8c%K9hAcGN*CBK#B56aCi#(tG4od*&1Y zaQ*fO^7rHLS6BCP_y>W*pPwHee~TT(z+C@9;2{!okXwu@_%(x*1|~pT1~zfGSi~)c z^33)Q!@w4Coc4i`^EM`R{sMrXwXAcWj{{v3ib+*pzq-D@sVOBPAthx)3U?j?2@NI~ zL%kvG?l9=1J4_^qD&zVMBe&V)!f5=W8FYqdg?r4PWCiJ)|7->=D<}O(iCRc+pf&%& zoaSo;@0;A*{*R_MUon}1pW@;S=VqWVvYsKi47iEwVtRj00j3ndN6vZ z&?g~*YHEU?`qivFBf6u$!?2nuW`t37PkpCraYc7e18y7T3k|VYV^dRF865QZ3R+?{ zOs}7wID&D4C6{|rm0-|yYYz7kT9Eq|&f1haa@NjKQ4u|8~lB&90tstHu|O$K)qDHFwE_S;->|;X1;ZD=+uy z<@4vvRW1zWi?gzVD!R@BUNOBEJ)_ zdkhzYrc>i6b74X@YZz1ovJLokYMF7^eZpcZb_w!B+&Gg_5Sbh=gUl zD-mMNhrR#sheCG4x)&j5&2dd~4TpGSjB6^c=i#jITh|I05#=DI&J~I0GjM$$WHQU4 z|4p9XF8w_au?&Xt`5L6VAL*vKk^px&(&r%G3cy_o_&F$Nv?~s8@O&;RuoklGrBEyP z%QL8V4AX zzVVB6AH`d)2Oc_+QlJ$2{QNqiPPnM94vq)Bh|Xtm5#srk#KuC!kW1%{ey1Ua_yc#x zpLad&AP2sKHUo66`IE2&CuhlqbZTc2LifSGjyIpO$!&7J40z>{dXuz_gryg6^(HCA zckXi>F#9Y9m`ABcDFG&DY}W_RBVD27(RX^&Rb^FW^`(=G9H=6c%4AgyRHlkM{d4Uo zq`)fR+TiUD#l41i+Y+v13hm`eCeZkv@O*AvEnn8#L)2enqM;v8`}R^`g_3wGo+0*z z+!*yfXTblX`koUBV-fw=zj9v^m-Wv@++WFwQ77(kJp+u6hj`T2^%}7JHT)05{b<)S zbR_+&=~Jms=tz90|B8(jYatrZ5hQaLXtuRk^M;lwhVr!}65b6=)KgJkOoNF9LWsI% zOAdWPpS-Ac+o_)^grtkrk!^OJxhfMB8i7uh4&=b%aiXnk%1(k;{clFx?>=*s*FGxI6K$IdyqTb zd9w#phPrNFC&E??)r948$&o%f=8tDN^bZaPjn|Hb-qnnK*b+yUxHKn26NgeocI zpk@-N)KMA{UnR?zE@uNgq4a7T5q;1?X=^JdCFZe1-j|few4Z6OnEcl6;@a!J4*b7x zZ9t0^%h^+tO5-7~fJ3)gXjzrpy8sx!3p4Bws?p)u|gk?YQCAGS_8PbGbL;P@llCqQ>J|}$I?e{~^3FeGV8j1a z@TR7w>!(+1Yd_m}*{j#oE{V6V+dr^<-N@<0zK*Y?mo6b*)?pa`4`wQfR{u6)T&?q2 z*;_qs0N zZ1bbrPov;w{!On^uTpGxJfXn#@h$RtKX<$AUZR5Jx#MgE#}1+v$g~8^C$mIp9|Sp2 zTvCR$WiJF`KeBM8ZZjU))vi*Nl-9Lg(gQjxD3RzYNYz=%jn!rbiV7Q;T(vqE|Eab7=ttvyfVAz~`Z`sBkCe8UQzuRx z$p*;fad`#HABTqf6Q@|B^`?`s~=bw+@yP>($#U3ACNJpm1MXh+H+@`5sFN zTDx5C+2oeTguc-jZisGgA%^c54W;sY)3WKuL;0wivXyQ&(JGSv=N+N{jXR5puP#l2H!CN)%b;a#S@xmli>D&*tG_d-)$ zoys5Md(D!THZGhEfbvFga%wu1AktHlgHJaJsZ&vhFh}S_Pz4i19VhFcFj05X;R~Gu zU&m!A2V7>uAbC$R1fIuX?R=miY2I?BGQuzfQsW_p2yrwBSIb+78|m*EHC#x087e}c%k#6FBevJXFK@AOis~cdufE=S#=FX*GwG~a}pfON1zA+wpUSnb`glQ?E$Lz3YbJy<~$ zBK+ia#A4$xlQ?~%kdqss)-|b>EMriv-z+?J$6gNO&|tC6{qH#lwyf9|mRXr=wY$TW zXE5z7vxc$e3Qzmz<;F89Q$?Ao8v4&?oIxmW6&Y*Odg<~cn=NVi61SPm9Nk@43ttZm zKa&&K0F%jYTvjfzh@O?3HO|j;n=<>?q5r*m+rihRn2Ib-H5QaVOOg~>0!;3Cc_#P# z4N00##CL9$U_}2G+`Lx6Jg^B^6K~M#5@SMGWoxTTYqRMfR*2Abw6wbSS6RNclx3Et zb$j$;O{TV*Ws(%tBJR#Wt^8Wj^eq)l&`oKocw;K`$nlZ9k^AIS>Tl#DeKL16q(Y@i>7zV$7HPXCAvTB%iKKla$v*w70n>~^aoC^qde0e)|u zrVG#vqO2E7KHT!!Yp+#^d8Wh$Ij-96ofpGmr+MV*UXyLVwVZ5~_73HcJk6IN5NB+c zx9`}BaB-C=2YCt#CdUNcxYE<}lSvzsQ6SXq0rbm|`YL#K__F0Paw*l)mIDWlwjXP6 zf2+84ypn!{#r=EIh)w4OEn?9#5aG%T6RpE1m zYNmEkYj|Ad%1|}e?}dG97eg2u(T;1^oQT85)YP4_(_T)y({4jJBsN4Y*N5nnh{4*d zq#*e(D1&$c2uqp^UAnnRq0ns#ZMuNgTxcRx>=%Y?c>{Z=sJ;?J_2uiz!MRiH-aErV zd|n>Tlc>+nMd9tgn*Q%1?Me`7moL+OR&y&>bZo;G%&MkpktT9a;ePEor)Q$>hMb)0 z>bACTKE`f{ZE@!KxS>N~Oi#>+OH00Fq~%PWgJo4YIq9KJ%FB!D-uLwv6&0U-bCUIz zXeX9bB!ViT6GcsnK%zBDEFonQ+FL@)Uv{ir(YaBlTiIDiuUyG%To5b64`MMv7zf6$ zzJ7mm!dMV*DPt3w_t)1`(2X;}=nR7@w<;7?wj|mJ9kCW8Wf%(0l7yj#jyA$_Z0qPv zhAb8f&)xC?Y_IwH`Bd}zm-rRHz4h+b(MTD<9Ib)#5-+T~c5`a#)ZuJENy$-vwRQ-$ z&LLX0|51^L*4u9cJ~h|%me&&R?;%5xQE?O~lHe#+RE#Q0MXRMl3`56_OHLj)cIXg; zRL0$oO-@c4GiXqVS}J44l1p46*<7!{8<&{(Z#K{$Mg|4zm(LnCTR$o^z;96KxZ83e#riw#A{G!=%5d!({m@~`uR!2g2RRcW-Loxwkp7R zjU?3%A5KXq&;wqpydOgCz)7N`m?3l$Jp})m)s8RLJV)1Wr}wOPJV9T*PXE^V8Uah6 zV!T`~KA*HlGL)jxPN~etm+F0bs`shF(fd^9+xrwH^`_m~`_$X3_o-8}D=4XeQ~YU!{)!=Q@+?#aDLU|62JX=XQGB{10EcZ`Lyz_q_HHz2@mPBORR~ z6CRhe7e46>f7a=>;*CYI-Va62`Qu}Y)@CdHr=t=y^{UI{^@#UM3X*Yp%pi>nRWL|V zR?r}nK3*dQrbSD}jSY&H>|@L3&YAYN+~*Gb{<*ztSN|h<=EQF|zU#ET^Do-ldu2xY z!jyy+PS;PZPUq8^2@g)VZ!10N^jUi17Sj7%DO?W_YJv2?tK6vcf9{7+v0QrRXi_VT z3rR1P1wPUXg~J&him#ZOv_aY_q?XB~U~OU?VWvfSWuku-6wZ$H*pU*hPtzph)k=oz zRG6VNRrCH-oc;CgoZ>&^{bkk*|J*Ux*+PdrbK>(SC1315^;GnYqQu{y{=Do;@qB~# zL*rg^Ud6Z}cCptyz-6ew|HIjPz(sX@f1o?}-eoNj1qAGh2-v`a6j2cr1w~L%X)1OU zq$^E8P!ItHM8yvF8a0*}qp`;rHN_MYP1MB1UyLy(CMIeW?(n`dvkMEF{NH<@-w(qc z?wvVv=FI7HR)c&tv9xi~zJ7G6LR~3u{MQ+(l9GnKeiG1(W6x>Ed;}9+(>sg?`ne?& zjU}L{W(6+IIS(Oy4HgwYI#MDvQvZ<_Ro6%l&6G#9akBb2UK^2AQzPEsjfC zgjU6E7^3afSR$>^Jt>3_=3`I-5Z>U&zjuJhP>3 zYJ@gI-7k%Qxs9Cx2sC9se;(hYN$|Yk9WA(4uF6qQ=Hy7jNuR1vt{*DZ>3I7sY3wg4 zDS`*(XB=Oan>EovN&|=Qfy3u|o)aAB0$g0=&*^32u9^~edRZG0Ta_6btK`Mv`PMaW zC~fgPs#vt1k_$r^lRKN);x))O9V!0&hYm` z(>nqx^p1Fz=^X(TdgpsOl+i>F1(zbR!FEwR%`}X7nrRrK*;(_ed<_&qr7&S6fI4?@ zvtl9_)Nzro*-brIIO)Qe!BaN6Z`@2{wGq`*Mr~gnGI&tf0Q*b3WZMLc%*ObWug_KN z&2+ZkzhS?@^pH(B7dBuI3n*`B@0jfDCer8%^*w3sZtQT5l%pw&QucSg6L_3S^cuuQAVCz5(Q2WJZ{4#7sLtd$nXFF58fIebR)#fLI1p>XG1xjtTI;3WWoVH9O(7d2s&fQ7 zL^BL;%*7kvFk)dVJIM|(T3VVgi^A%v0JR-(vN2zCJ43pQ69`K26U!;(%_-7|ybjv*Ifts>u+t4XiD$tqOpnp2 z{LDAkbjJGXSjEK|Hi7&KX42CUb3692AMWbulU?dsA4@vbsZ~U)wxa^eR}|%wEw4qo z7H7t_0uR$FhR0k;(P5CH%{9oSkd_j&Lb)u3O=_-d0WOxzT9`ZcHCKkk-P*DJc3j-; z?K^J873?~DcGvzBXLd^mKB4E29VP=m|CD&Ydz7C4g0vE?x0?JOffQl2&q5K30s5s%`S$4t&RGe_}EIZ2rD$cTiM%F?bPpQL!opA9iPB_lf z+!|YDn8|RydSj>$7szo zh4I)`r_HF%JBEK5x-u$v*m+u`j0k(?oku^ zmn}ZH2II}3yC4q}Va0S|T+WSdYaNWoe`9uEx6C<{^Cotx=oVd>vf)NT;&+IQsZ=X1GNIFpd?BoE8z{S&t%w09=E#gtf{cXVgSLjdR|IfkwnENNJB?@aXk@<_{qhgl`~z7vT`mbMV-khyfPu!|3KL2{2-sLg)`roM^fe; znH4;4>d>(RGpG8^8r{WiN?H8W4dH$ z;!t=Iz#3~2&$i$)mXE-thJZE^&tl!i&x&=wS@Tp$)@Eqzv2J)rmV~?EOzs)fbw7It z7s8z;rXBjZN&&eKX4Cxp4`;u(aK!v>UAu$~DysbH9?1#ZA6ZhFc3YbfFd&G=w7PUC zxvC&DZv*|GTxvBD? zs+IB}B?bIqcuIy3sUa>lmWF2$K&haAi07rx)6yhs@eU}+-{BOT#wpm8GFpX$R+ta8 z63`Y+ITTbehANcdwjJEi47dsF1!t|ZP>C&t0i!faxU@L${kaSG6)k@g%5>tgYx9yn zE0A|q_gcMb)oS^3HZmWBV-ab@lLE@*ynqTh&!K$B1XRd*@hp?`0xIOZc$Ud|0Tpsy zK$)BuP$B2V2u#iksIcU=!{5N_YN68cT6}r@Ks+nr2Vw*!X$4eRcV5^#I9nPMjmD0L zPMoEQq&%D2B+yRF-d6U#+=f4bj?8yszaj=lWLp{khpED>m2Gz~ymjF6r}>B9KDYlo zGg6fHRrg?53|HDz-B(UBeE7SZey}rZ^(2RKN(rc-lz5g=NowCS&l=N zz@aZ2w;{AC^M>`%A3!njtVvG>=;_pXV1$L+&N-Woy!d@{@dB6ppe|E3jyQ3eP6=Mq@8El@W3G7( zFrC~4e z1Z`Ujt*V1+Kdps6tAm;}u7&cz zwa}W!*qoZbA;->xl8*3Iut%gX3_4~L)kePT|BbHbH!cgRvS;n>kwwHplb?7o{LdXpD(Za~M_&KxO z)5)E!9~^uau|>WHz88q7vAsZ8NYdQG%B;25HD=%v4XKSELsC2FY|Y%j6-;ll2(y`$ z6$u%*F{0$)=qc|mJr(^%OeWE-+&CzG;`G&yj?3i2(Gv=uZm)b+yd+WkzS+yXTep{A zh)f=$-W@s?C+&lpM{*S?2;a}n5H5r+sAmi?TR^H9U+UpK?A-YEU&Y6NwPDJE5kq{J z`IemyUK`P`+jtM}C4cYO^v{Zc1H$_Bx&7^`(-YYa^RZ1Vv1hBq%0i#iLYvh>s|A$y zVR#szIucknLfx}fbt7n*%ogK54}AiPt;b5f0>#WVoj@^bGh4CswQI5CXNa?g88$jB zGp5DhjX}$f22VS_c0WhnW)AZq_<0b2DbRGG(eKApWL9RM>%U6+6S=HWK?* zzXkps!qyHd9JlDe&g5$a>6g=zFC<3q@@TVS_CE5NthgPH2`CCan7{6nGUa$%`xbGQ z&bF&Y?Vyg~5rNwmpZ@q~MzdMKZWHKWuUY>w zlV(UM!y=G1`vA`cTnoF{9(W^yW8-4?f70oG1&rI}Wd47V%Puwbt^cIhA|o;U^y@Y(o@st|l<&FCVaOu7lEY6NA{O+c$(3$3by za+xQdeP#rGT06q?Iw+Tf;@N-dpj;AisE#=avgQ!%6-FIPO>d1G&Y_OQGdZK`3|hhU z|0J4h(Ih(7-qE|0d$$%H`*(|*KkhC1=Kn#*=FR(z8P>T+Ka)l&CXM3!yypdx+y72k zNQ+C*%Y(r~t+0!=xduy1sA%T%x!5qam-~-eIMA_AlIOfM64i|E$fVUonYCMcy8nOY3Na;;W=<25ClMOqQ*vGtjvg;w&;}3O`lO+$R^wH2^Rj zP9HyOo|2ZIZ*Ud_qte>RcU^E;X!zdr0V8c&+j@_?Fl*;DT63@BZNG zSeVwoe@JlTJ86a66Y12F-2AfioE#;+pkk#$sW2hn?Do3xq?5FQetj^r z{-`+W`(86J*3R+M#RKaDZ0(3N&qAaC7PMTW#hn(G?ch;<9%%;mh#V+3Px_SfQFUY# zJwrzHc6aaX=PTOQqd4j9n0n+GDAd@Q9+ZN7kyRQGo6OQ4~6mdk*{ zLI$vSupY|xM?h60DBB+at*V3a(=MRTjG%091oU|wl%IA1{fEb!qG*JC4{NtV)X#~n zo`nM(JZ0nfxrGrSY>a-FKP|kou(Q{)bbmVb8}-4}b2YfX=ji0_F1e#SjFXd_8`ky1?3=W^mQq?~ zZ;2Jv;BS)V8demI6*bee7VA;49+nSqG2T!)dL#Y*s^x}frL;eJ8-1{PJ92a*x7^O} zG|hU}(L&j+-p-0~v9rwh2bF3^H697;tv3L$WbY}KCT!EUDS$O{SNlHfH?|@pgOm|V z8W}aFZFJX?c{&&RVB+coj?XDH%L~(mw{0 zQT5Q3sxF0Y+7l)ZYk)OYJrA@R1Wkr~7Z}2d2ULWSs+UwuP&vc)hEQh~cuJ2+UJF`# zxkmLWYVGAdyH{GIu3PNbfr)LqMJtXD3$m*Jl%6Nd96GA{qT#|of$*9C77nc=R zgsiAx`_81zJ?%~Sgk9iC^P{QL*$RDQ@!IJYcXhYu5;V@++Z zPwO)*tVipR2(B4`+J}=Wm)jTbn&lX7*Q{Q>rd)B%|9jV_XQhQtw{Cs5EcWZ~ zzrAte_MNXWG#{7mz-M9yxc@DnOj--5Y6N98640tTD3{g(`m7Gh<+6bOV+37LJHpFR zjLLjAE+hG~2-|@HG`nbx(nM=*lrvz8t9H#IXCOOR@SFjUnhFcVUYb~VE)o8B#q6YR<0YKH+g0G@Wu5>^3aC-JSKg0XTzD` zufN@NCYWK!aN$(C*^o+nr^FhuQBb)QJM|@Ys*A8Gxn~Ry_f^-}V1VN|8e35Ko%_Ru z`zz6t;|J5IxPhVlyaz29lTdDNzc@2#rLWJb`HL5Iw#}pdb0P-VR@ME9do<<8z=g1?Xs&mTTXq?=n@qzbft2xqVpJdT@z-@eN z&TZcdZu4TNL_pc;6VPe_h2{hvdZ^CiNlhx=;c;g91}M>kM;Bh3X<)$xBpURGih0tK zWBz)Z*u=!0;WG}zW*qnQ@FmY!AWuH2QyFzYkk&X z{M7Q`-hO_)$7g1ZkK8qN%t99rhp0Y@`JU5arg`=Y2S9jdi$ znZCE<$he?*!`a0RbpbYd`$Vqpw|a2p(SQEQBuQp;^Ni$ykv;o%?y@Ia+C1k;b6PV; zojGwvI}9Mzj;7^RXWWM%|2FCpx{+?ZCxyN`xb$93jGFqI8L&eF-^rTy3sBe=;EbYS9Il0}7Jl8H=*ICH35(T4@$G)TO?1eDh3Ie*Kh7lBky~D~(5b#&J(DYKea1jY4zC2&irh2Bli9L&RtSrH^$amNn zr8}JE_di*){lkw6H=HP=a@hqd2fPz-QCl~lQ0-vS~AD-(F=?<$^WI5flo-`pX%IS8pY%9GY^&pRF6j@8H z)obKB-Yun56dSzToUI!*OmJk}#PV%uVdt5v znG>+MG4dg-i;uz9MTpV51QhGiL&dr{l&wn-73&huVqJQuSQlg~=i0_Nt#$d23@O|~ zZ7+o(YxDlRc{611lt|#fpXE4U2N`X7q)9*-4gxCTS{%weK0Q>#s(74M`weKz;;A~F znPy`Ri`3o%7B_jEmD_+ivmtCRg`M;>o)&hJ8P9)kiOQel5>;n5nmsG#!?R*Oof(oN z1U=?e`Fq8TXFRP@DUM1&LfnX45P~dvuMqkfy&8hN`bQzeRWS>p*Vu3U=*NJOK6s=y zs<89_V^l%DSiL7EM*2OP{9y2nAzi=9$>`(I}b3TYDKLF zD8Ec$RI1bM|Ek$vr_^6j=xiT8((IMLmrqM3q&b=?ljm{R+3&#n@N9^)NL(8KE0UN- z|H{)d&wN&P^p}i9Px4nkEGm7nbjycV3pSoOx_j@5U2ncyvFk+f7f1IoS;5YJ!=GAN zz~q6^50F521C4we8nYvOMiwK1p9OWq$~yHTx_(BCRqB$uyp1%pVymr92e*+e`>gOU z*!|#YTEdhbi$-(}Sxs(Nzm$69t}Tq5=$+P0dwpdV3a5HD4b!>1yALW!S+dkObhK5Q z>784@Jd~Fwmxlz7he`!LSAowx;L{u$qa(+sp1sfKH}-Qv(+^LZemE`t$c!0pld9?} zvM8;jBrR>(GVS%Kiv^1=#m9WGB==$*n?<>|b@%QaJ9h8h3V{XHYJGE zvDCZt(}d9reMhgJn)$y?%btdXjXRro@V$xar~K3W#+b6n!7D=34~`u(`<6B_d`r}X z1;ZPgj9wX&{=vM+h>?C{b}XBb;hx@iZt&PB=TTl0#*YUsJR6R+wScFAHL;Kb0sT=i z<3>*AD@__n*2nT&=+s}qKiYYFmXA~(z1${iR#c6zvSBiazi&c8M|(~&7jBbqD5tJ~ zvKj^%^^y;jefT;%En=sD+kup}ZrX;kS|HJ;x2fH%O(kVt$rSI-QuS?PWbO{h7}sb< zt6*Q>DXpeA3eF0nWyC5h>@_%=bm$uD*J^0LenVUNg?44T3E9LeaanZ-E8)Vjc{zoo z*_V^^7P(wbn@iTar1k1-40l8dRIzbvrTjh4|H$t%{%3+s<5csQ*MOSi0|v8^O<9;z zcC(P5Wz(tsTlaApG}3WUd&sADKo1ooKhr*^)UC6IcbVPBbHV-dQYjmI7;r+JEV$FF zj(+?zP{!YRbpk4;On7xd-LAo46xHT7qS9O*sQkpvE3a@h)bru3aeNeB5y3~nX~3vZ z+q{a%gx3}kjUV_jP4EJ2C)vn$N~6O&`bU<|u$+?<(#?Z9FCn{0E{@$Ve)B>+nkTgw zG;f;xef0u4AEWY7ScN^o4Jy#-4FpSNO~;y#l``#W=*`v|mMyeIR<(sjXKCwVuR(FD zn+r>iwXm|bfD6y!UDD2~KdJi5hKH0sc_}AX1nzrh%RBo5E3~WUTF^`M2E9tJG>wmM zMBMSeZp6c4?sw9xyQk>Ozf6@TRnJWSA||Kq&SI+!#41ra11h8fA4vnT#dpk%oo5R} z6qna}qkx!2fuC+F$bGwin}F=R;Q5DV$crEa)fdHu69*>@9BDJ-V3K4lDuq}D@IxgX z6w@&&%FYj~$wpxZ#Meny^`Fb66zF88Jbt-tK9@(}nHj(+0B^y*MeaoZmW`PbP;Ir8 z^vEYY*aqUQcFOemztjUG$`}!K?RtG?G$JbqsvEQTFO0eLxAnA$ zQfVjsiP%qG6J|83a(AJ+L|xIhXz~0d{TYY(VB8pt+XN9B;A(-9c{a+RCS6*v1Nu!x z&13a9Xvm=l-&wbfY%d3PPrmu!n{POl%U10tu2LG`UP;re=CN`JBU*EgH50=@WXSw% z;EdPlU+H|+-!*r3f6=dnU9Ul1$69x@?a*w9WYW3Av}OJ%`c$8O_|0#ZlzVE)$sZT` z+DvLUH1Tw~^rxDqmOCw7av+cKhA4jvh}Us@`-npS3e57kboTSgiz^j?~`NzozA1=aq z9}hj$2_I_nzRv;a&EBK^zR)JpgLLQb^u3)k0s@8&!&m9G zNhhryjCTq0p3T8r(p&I4We2^&F*irF&~UxU+y(XAvPtPq-=mkyb`FzQm6n#jvH#+@Sx&uX1qIA< zc8=60ZlxbQz{1N8klq*7dDz_D#E}e6OQbb7Z&I3=K*-ITto9sp2kYfqGhW5baEJfT z^66cit@Spx4O31#=%=g5hy`gxe*W2`{kv9{kPb}lNd46hrEs?oQ%`;sSFmQ~N=BU; z6HXm&t?6lFl$&51$4P|CDA)S0pZd;$5oL2bhE45app)FkRQZLPItPGKU*_(a(GEIbgjgI7x_wO%NhV;u%S$TKi;(KM0=>x{} z3K}+f-7ItRH#KQGedE;NnO(J$)V&#Migwb=e|iiuoWY(w!rQl>a_3C?g~xGyT0>sy z{R~8iny?B^8F*wiY~xXdLaF*wwB`6GX9eqB5>UekAJ5iNUCrBImeKfHo?Wdy?-pm%#aS4kmOjB1$ z4Q5Z7&Ssyk7D;mw64>lV=p>n%{DakXM&)Q9aK9*iaRYDTMyw?2hO7y{XW-`SYGtP{ zoF&#;TRS&vayVw*s5J?5*N$E4nXoQAI@xK2uhf3&z8#lSBJMm=XOOqm3b`pYA+etH zc^G}_^^8vHl{UsZypN8dVRI8RuI`gq~XJA1>mT7b*k873?AMiqZ#P+u1 z#IQUiY;ePkQ5+O5EgW#IhlyEs*@-}txQV)L*;FE9lJni&^OKX7dUz~NnladO=FGvv z$VcWAW?K$ESgVnc6ZPd~+d5Gli| zpg@EPtL`LhV>$P7teaVYT5ipWm^t@=8%yTg*Nzvyoy;2rtPYZ`<xJ;sgta-|U4<<+2dQ zjlshluoA{BS-yrGSWlhEi~Z7CHHz7>$0UF5Wder}K%ERuomxv@2TPw}!E}$3!H6?b zf2mlIWq!lE#hZY^VT>X3C^#a`ve5`~E^&H;KFp+zb8^UYa7-u95- zq49ZMX4}Ys`v-{bP}m^Psjj^|^6&2cv?iIp9dY>J;fR?#XHMBXb@F=~Coj5r?0>m& zk=sgEhOjlRppLw|g9VfKcHD?S8reWiR2GBQdgX7h66^JRC|XdFJ$Lw|w)U;P+}sCD z36A)W9uU2{SI(G{*11J+v$kGtetEtBvnK>_3kL_{ZV@C}E&VOPe_&%=8fNtGDXuSx z4N&ImFFoPB4*}odmILfTcRW|Y^vXW^$Lt0wTBHZ!oc&yh>?86raVTgv$2KO30uO}g~g%R z36svC=SnGiZb551bxs+%T!tWMdX<%kCTcrZ1u$ox*(S+&O2~d|W*h2d+3O+-f^pRz z4Fe0ch`uJgfbsQ~yaG$UjgW9=wFO;nuxGgJdF+R5`6=5z z<54TeO%V!8Pi#hG1y*ttbbcFXO6D2h>bS9YT6fPGl^*z$lSB}?M8UCTOJ`Wro$Zw< ze4|V+W#Xy{vy*%I^{L1z{3bKyTHgGVv2;f8lAxy2_$DLMsvo#@m}b#7dRuW`u5`6o z&o*a&jULb`v}@2>(&zqNGW_r=`Xw1P|KX8S4`Qg_kl9^(cO7m&Yr#VByn-rk;0GNC zV-7k_;x`-`dZ9dm%%h~p&EP2){L3geU9kY=ng~A;3Xm%bm=89r0@$S!_N1X%a5DQF zGG`^7)s6lsP275!DF351M&!Q`Lc?~U)k7Llm1RTPDDfGSdTn&few(9etkgt&Sbt_~ zqkq8gwedfhXC7XO0xs4k8(wpqs;pR=LDF;qhI@gb6_4QDxEAM2I-z(lRQyoo@NUNLmX-&HPHN+)o z@C3S-?z=}%zO|Y-(!==1HgkISDX`@;vgiz1$nnrVXZF81EetA7i-_6qtORxu$P$#)eE}ic-+;?^6zCCM;YBb{#-uW^- zkZsbe&LQnbwGssN&8S8|j&vuBL zsRGLI71<7fFOS)Ce39o7ktdvaeIy@J*NVr&j5-wnS#v>LbBoRr>hz@g{Tisnu^n2~ z+hp&N{X3gUC!6kgrEf#^J<^Wo(2eh&vYtMxsv=E*a~&ScQ!_-s*nOg|Cd|h|+>}9| zvQA+lcF)!)V)xBkvHcKGwmt#X)m=cgaW=@hp85%NI z@$y*UbNZLLSfd+wli5|)dN1Drp>`hit2Z~IZ|pM8EGi{wI=Vk4(*MLRpHwf8g=|tOIX-9Y@{EKF z$Bv%v(1^*E4dB?(z`>GPb{1%S!K(dOOap>M%xfd8nhhirtsYqChuvH7B?s4u>(-+? z4$u<$7~^c#@4?XhAufA;Nk&zk$O1{47BxRBrADhXgfw}G-#}qIo=ap}6IlmE4oKd* zZmI>Bj$L~6X}#x&biE-_8_jC#o&D&Nl%;ABT>EL~-IbGJ ztV^0$;IIKWH05z>II0Hi%#yILMMxS$4~y(n1s;x{DLmB#i^DwHrVYsz(FUnEX>caVH}5ki|C`ng1vRyj!@2OS}a$Z z(&@*7ii2}zgb!UbUaMWCXh$zBlR8NkGBZ_A_2V&{lD^(hS>k(g|DYrt= zL-FS(ObAw&Z}@S+)bhaL*`w!ws!bd}euCGieo;XaqWh-z&zM!XeT?78DYN3vrp1+y zYusc+`skRgVOX_Ot)0~Qb#{`mO;*oRDt#rZ+(3T4HpMJyte_`Zyr(I*Ojr>RLM{CN zHYl^uC#}h*b&nq`r?<$M_4FZqUP^+fDe*Ah)Rl2o-}X~DuffFpQR<*(tF}@aVyJhe zg-g{xIY-$FF2m|_;9IQVybWCr>BQAAJQfx*=i7-kFg7R-0}?qmiY`R@Wo{0Mi5^!x zVS8Sv^cOAfOT1Uod;%ji_PvzoZE^1N+=~`$SW{&oRZf;>sFT#;OgcjX>LV@IjF+7C zfm4V>c3cSl!vz`P)v(BFp$DHOG0)40`)2d)vYl1Lykth%)|L47*nws=l6cW`5)+-)IE+Nj_)DJt>NDf`mU3|_jhwQwUMNYfc>(RisA!JWK|)*ClLZa+5Ck>9 zHK>F426|hXg&9P{i*?t9XprcL_>LYt9J66$PVeE~Lo)+RJ(5Fn)|naP1Gwj&UOvz< zPOYM>+5`mVXV1v-gfVW2*zC$sw_R`J5+rB<3XQ{3K*mjxq|ucmv(g-$k#1gn=ScaI-zp4^ zkV1ACkN{{9_eIGx1Mc zoO5i&LL}YsZt?ui~_bHz_t;5x{ew<#!1fL zU~>zBoG1yCnIf>l266*mxMxE9?lI{;bGqF?$y)6x`Oqrcc7B2W*EV?+rjS1L{OYT- zrEc75lYeK*IMx0`^uKCER-+a}iJ|}diC#ZGN4ff2V(HL%WbEnf)s5lBks_g>!B@@n zR_p8hWEL}Wkl%rcRo_pRo(Q%7Ix(ydYd{C;dxbz^i0lcw#jj{@@azw2o^)^+t?P6j zQ%x*2Zt!Lh)({C%G^7plY(HUspy#ZBzD<>ig@KC#m&_SjvcN&Izg#?T@1)oZIrA>0 z4BobSR7{BWMx0r1w+^iaMefaQ^7EyeLl1Aiy4}5e`IekFlfGQF=TSxm(O$bndcW`5 zu4iwo{t2X5YkuE_Whlfs(&?R%UO*K{&AB(AEx#n z?(EaEnYE;)vCSH{>F(WIim3kcgoRI=IQdpw8y^cKhQ`Il_Q-i~iHuLUx%ShgA)RBv zPq{RUSj95SN8c|2yI#TdhUi_us>BcTbr^ROU_Dsy6jq0R1h8FDr=X+*TW0k$j9w{1 zl&lxu&i(uLveSzeFS?L_=kH}Vv&d80RO(0W(;#w?|Fls*W-vBh7VaakZZ%ADi%kTV z88MmeH3f;bwxsxU!jj_L(TDv9kNRd#+_Bi?@!n~p(ylGpaNT#X?}@C6it^%5r5O?a zlR}+)kM$VlnKdmmuC>XaIV0oNj+*EZ?CO&|ZE851{}yBtyTQ>MAD|alxgoPXVa5~r zt3@Uz)OODz6NP-us*k0%liwazU5aZQ52l@QmZKRh`THgkX!j1IlCB@`UM--Eq8y5> zDzg(l!cO~|z~Y96fQMdxK1?X0GEk_7-~p>Uluu?fQmDi343owRZWFsDMh+R)lAdZ% zcqq^-{?e&BgrPUCBE6klQSC`r601<UTBHIL;d7!9#7wj#vvSj8TzJbaQ# zhqh~O-#>V;OP2w?yEN;}OSt#ZGY4q zwKCDis}vHD)dx*P@2#n6Bx$v_S^g*g`I)b|_t^c>xV3O^?1fS4Wh}je^rO+Pg2jyE zb8?tUGczSAliZ{2u|8LFwdy|GMSkl5ce70Rt%EwQ&>7xGU1KQKWJxdO1J&c$#C-3? z-9o%|o1Y_o(}9n&3iKhGGOVfxR)tYS9Kgm!>0wIKGij>QCZRf5-pBg1@;e&1Wn;qb zXc#_ojuMeGa1?mQ8*{~@a@+=W>;o{Kb-gQwaEoRl(d69ik@xX_IE*Vcjd}24?ptgFD-X=adlBs-3DH}|H~Du zBNwa3?HQ~K!~iwUVHu}D4GVk#pXe`i>AiV3Gx=2Jpd&Natj&y=J?`CpjKt)V{yv+_ z$Obw;ahBg;atpfPI!+L12Z|ym1jCvoN^G=3GLFqsO|m2nu@^Fs$ybnA2tA@fsf*%` zH<{28ud!Fn6z^)MEYdxXbZ0a2H}o(q~t95j!blc(RONoznAdT7#?*=buwn8&x-9aF$=l!N8(5MpWd1n9Fgx=Dz(kUs5>{mvuN{3{Nh2|b&r{`D4JYi zOJ^R7DZIlC__dYr!Ns_+a~qaABHki>)Zv3ikFIY1!?cmT*Q7yx+q(7Y(zvzMv76K4 zVq7Ald$zv)-VymtdUOAGMPUwMtp+8$UqKGgLA1^6RXHqzwFi{hg1K7q9_@8h24#Rc z+oih2NT0XQeLp7VY}S7I^Ri{6_1-Q{W7CH$#WZn)mZxWw43ccr@7X8BlVm!!^~C9m zLfKj7_m;RsxW~_cUPAC0Ycs2?(2<`_V~1bb5piIY_lUeP*=MZCU$n^^=L&)fMhqHp zDq!Qy#JH~&M;DLKKHZPMll0LEr#``+gG7fcY({O*EoMm=ypGzaq#Fz*Q5FL`PIBDx z@${(AHcUM4>*Z56y7X96^|92V#lE6|av!gumlVg`KX&YRxqPt46ldp?SCdX2?d1~Q ze-PG1Ouz=Lw}*-55R+N@&&*a376k8RqQCpZo;t-Pn@7_baoY`>piV ziGqok`qTTVo>JXqW)^&rUZigu8@M$qb$x(#WkEriE@*vXdWdcKxZugQQxwNVf4_-# zP5D0-QD_=EVAYpNDPP^lJ{KK*KIg`lm@gCazs+|X`6lQEAt6D12OeZ`28dY8vU`mt zB^TdJ)|D>unHPQI07fum)lwk znNM1GEKiUo7SGogUr){Zu7Ij1PZFmi2SQ6G?ABWRn)<|N?ZV}oJmtfw->740JGzvI+%lGlLTzjmYD8zjwmtZWK)OkW$w<3xxS;hGjM zz1vC^&d7q3`fBGmDQV^HKR#wNs5~x9`lM0hX)?{OpRTzcIU~{(fdJ&Ah z(pMWwr_jGt_QmQmw-Op?g{!>l9^rs%=l0S7M2NDx8Jg>oi4|C{X zE4E}AC1$5F-r}`}7NXWrM~un>Cl<3ZB66AjF^Onij-!9kv$AAkqT1dgAKqHJf7H^E z2e1~m4BDN%AYc2VZs>|Xem@c)Up+w@tG-3P#wYx+bGd^~#s#UiIF-yQ=VyZz0fLWN zX*^3{=>@)_Bv4-fcw|x9!4ruaN6(!=x1!o_wQNf}@7r-D{{4k+Hslni~>N<|aqdtfI}41%8cmt-Ez{3hJSoHT;JkhQH0YeIhKMxt!av znfP35t4UT|rWS%=htcDU?JToo`SH^SRbf-t(4wVe0BLJGCZvORXIJLVJD5@MUiEC* zebz+FmVu2-9Q#&}#>jjmb~l<}CfK)+x3m40Q0;dd+;504@teH76DzCeWAWkIDjpLP z2N9DO@xGtUlGaXY<@52IYf5%rY@Kt1?oZ5f@1LI-lj|`kZ*H)Q%eV<1ZgfhT#gJq$ zIlJ^*^?dQkXtGH3vk>h}vafyl)n}jG`1~5%8QdRK#)2;tZTy1Pttcp9 z7&Gq{$iPx)%VvL_$H?<=Zm>#kEdKq*^5gIuPc6Oq`?4>xB(oW9hPC`R?@?G>j3cse zYoGV}B*)mk>4?H+zK@yVtHFK)XNWmiZH*}IgXyD`G6PO+QP1fSgT~^h82dhu^56*W zGr>dQJ`-{RhLLc02)3`4u>1GPZrWbGLVmBRqCi8^OvX6l zVaLD0uo7+;8g4SI>~Ox(ylD%08{XHc%*-?J#j1ZI@8Fiv&r(0(g`ve}^%`>MlT=(G z5*6Vqu);T3eAh;dB8HT4N=e(yFG%1PI?N}^Pn)sCs@}Jj3H|Mz);M}7G@M8eZ^U1TO%4t`)6j74>RS1 zF)`Ia4M+G4Sj^*Cz_vHW0#^DwjsbVT^z+yHVVKbq5#a53Q(q^@q&qX>8b+oKfoT!J zvNZFQGD_(->C7lr8|dRaG+_CM)kqm}=E}WJtl%l4Ycl zY#SFA7BFSPwDNh>pHVLZ)qb9k4;@)-L|fbH+)&fUbAwzSSXo1sid2A=v#w5XSj%~3 zZw2}+nVP?TWZ~HqC2#vkUmw4bLpSEpA05W`Te@a=;Vh-#!b`&J+X{@zu+PjZuB+=qW`ggSi#(X^GubJ8 zWUZc9g&jqfcJ6r9^(8B)UQzK-egmMv*`f5K2J(o6U z3jtnbm47VK!B)>aVP5%Xqc=!Um53Ohbf7W)E06vrk6oe;TtZH&^V;|{fjp1X`(`Ho2#I_HRx+>htFMJDaaQ5~PmB+bE$!da^+@iDH&tz>6p}wTVbbuZ zyaT0bvG!c^mwkW_^Z(N@idJ}@1}PyDPKI;MMpM$*nq%q@Y1ow4job=0?g*~syRnnP zs*X@}z+&ILd{1k16V0IUQS1+017!-2s#U*^6I-@*?e}JJK{i<;hZK(sh#EB9V@GJg zM+s49vQK`2{<0aVmCYn4r9e99Io+vOx8e5v`p-?t$k{cvhutJ6)@v5c%jn}@^}S}_ zLHA}&D^&FXD||-?6dN>~#CwDnAZB_OefLaQ_dYxYxuc}>h|$~pDG@Px1l|7@cCleq zAM^Y{FgKQ)YbYWgWfqZcE9s8r-;$3K3!3aZPhT3Td}uUxSeWu4+Ub|#=(Mc|=rbl9 z>*@R1*rDN=)y%*D1G^c%YhyD{hUAqiqQ9-Gi$27UTZ5SNXhcMY$zJ>LO zNG&XhhKO4jX&dR95zejjYO5ZikmAMxKuPlhu=WSm|5nlGP1`|p{V%hGV`}_zC=anR z{LUfLBjQ^;Ci3cuk$D^+ajt=H&){*c@$Whp@wh!(I=SY~qFrlgYSJt}Px38d_$cMW zxS7ChGjJ2xA08b=ouOPC8|7qmkZ%Sq?xRyoJ}G~oRkXH?{7-)KAz7FdH^fWFMwfbz zeJfdQF8w+2Qf-{nKwEH-=-7@Zw&>Wd>-UK96^HU(Ir)sQOn4V|LsxWg-wMusB749h z;N17u^$tomJcSyT`9b9SCXY))zbAv zYc}dut{a^<%yZao#WC;iJ#YP$O`8ASrmID~wvoxc<0l_Bxqr3$fNA|%A1>w-G-8-a z$bmCVU(}up1||Glm^|b7@{EJ_3qZNGXz~p0R3*(abX9u^D)ah1X4O0Bzi$gig|$Br z?sRSap7WFqna*Lp8xqQQ?m4i1{HXOelTtsW7s!Wdq1;5R38N7XV+RlQAH1uweDU1y zBYBI@M9OZGMN+i-mMie(`2p4qP@gpb(zQ^A?>k}@9LoJ2zKXL3C?uiY3xYfq^?L?? zUvE|r5mC}hr+WPo$pQ7;8>LH@K-LtjY9x8<%IdcXR1bb|@}#u;_~AoL0@cpWy)95y zVwmzc7RTwj!0As06+MX9szl^ktg5av(M1FPhG)62C7_}Y)j6hl__&wFvoO1nQNsxk zc{oIGh0M3+ZjY40quUCd zOJ%{lE23s*78yyCu41Yhcw4ct4MYkiru*Q&%ZMCLSNiK`LABoN=78}~YemROAAaa% zG>IDV8hfJQYz-|7$q;Xc3_~u<#%O#y=CO;ORU46YHeD-vR(*U-Vegs%tHUjwAl}pc^N*ZAI#Mj{8hQ-Md^&eDFdQzeOYv7M(UcOi;A3UlwU2X+?ecX4Scge z|E~C;4}-zGb>KxmO!cAofCsE~)*L%t)`ftYcIJ+0`Rj+pet$Eupmfy>Qgi9n!kh%R zc%K1tytIn+hnT%E|gPUb=PT5OJU%WRsEHo+Jn6=qFgSx)~iu?km(vFgN5B zTiaSb2SPRVDsg01l;8p?H>g!JF$w6`xtDF5W*x{M#dlkq**OPD7kn267JCox8{(o> zR-ig@o!O+egOWaZlN8g|WFCEX{6TSOpCQEwWK1{uSwNC8^?}1|;IIuiyuMn`#i(My zP(COPrpJnliGN9@}s6=C5%+P(lcE#)w*}3sY#pRnS($DyL4*za#-Y3Z+3;G46 zMjwltb9>Za|D$6TFI$oz%}5EKIxX49EyQDDz?#@GG5tyVxCxUNdJXd!+uJ#Gl79rV zEM~!?Vwv0KJloPB0K`0rI@?WpWF(+gH_YqSlZ4uL5ejN($6+>fs8M!tu3?cNh(A&L zC(CHN#A<-7*=*z@v9HmrI`u&weM!2P|9GFa?$_4It`nGddO!N8Rf{hD0_%%D+S6=O zE7!O$-X_KI^iRgPIEmNAH6p&FdX0~gSWKVZGd%iE8qkHM*JSk``8knXuvq?d^Paz#40WSTEwrbW zdWFYF1gU@fPY60)x$aCD^o=R@crWmcR238{qE5dOmFJD z%R=^l$E^==C+o?G&sER`66Z-+{K!>5wSB#qnw%9uk55)V z0^y8NB&n#r!Jz@6mlFCKw=1|K{)9RtK=F+m82eY3q;-2lF$Dou0(z?2)wHM z?BM)YY-uy7-3k7$F6uY5N5^YwJnDH3gs zkn;F0GpBwY`(|0ph9J3lZZ3B15l%)sa3rf*Wwtr1C9FLb|8gpb%E}6FiiX8UVl!up z-pEcpm-)vpbaqQ1@2D%4pX!Pu(Ii`pT`-Nd=67h`v!D~Z*TM3+y`YZK-9uv{7Ii$H16i^vtr5KF{?7;$#6PD>RElQ!-!$dP3UJQ+6`+h zw`t>JeI`ZjT$A>P&xqnZ5d z>0>-~vL4YMR%!NLCXMaT!ohulr@nee?!m0>*SqQCcu)%RL;uaikQazb;PXImFmB1< zGkgMk{sy1B@Xv_yB6G~-3vT3~N~ArPFZ$=fpC;f=f`lxwk@l0zRhP+!V`-s;{%@>x zKvq>DdmG-KaW_5j4Qzb$EIu2*5yd~l7Q~o_TTl9XG%T5=ZE*9+_E# zvLAfKozl3vQhKB&Ne?ZnKgrF_l@=5fNYfTA!l-(h03+Y}G$V+EfySs_V&BG!zmMY> zSKu?dEsE+f><=5Cz`?K~a(miN`nI}=eTko(qIM<^qy_5B`Ki)Csc(7;s{Jq*O77}9 zz2Wl^e6G8xEi);nti{;1-PsfeS0H{2n#d~#lN^RzW|G-~@1j>#oL_f(^QyloS<-azwS`DE zwx~GWTn?+=Yx-U#&OSL$tITOSc6lylVBd^v3z~_BOV-T2th+UgE<-w0L%X>0CQMT3 zye&a%m(qkkvx+jmTebR5W=Y0hbY6b>xGhR`GOhaNPx`CZj0A6D_Vce~;MT45;;%o` zCq4-?yh+PHzaiRWwkmOwQuH@4bvi4Gr~EWpE1Ni&fris3ZM`dMDsgvIS>8-PcoT~&9ITrs|WBE_2Z;1>Qr0_Ie=3> z9y8%f?(vlHg_*(5a_4xQwH1<3d89O<1Jw7j<%eT)lNLYNP=0Z-bI-82fT)#-uULX!wxCyI7CB%!D$ol)hv=Xx z&+QcGO)n8Y-*HZ5?82fnyJ_=O^On+baX%8&VG_X_@5`LxuiN5mFUR zU1(f;d2+kzKcdLx4bpqwtdm-5s+*UD+YOq*csmhqE6|RRDG(%Rb%PoA$2WG9O=`d>`R^16yhm8RL zpLJPc-`J)P(Q=WguNo)+?0dd+6a8mf>4gD)t{YM^KT3Ss>A_Fv zs5H)fvXf5|k-qt!kT|FQ;hsY=r+#IicQjVo+~j|nIck#kHT*?CJN^ z_uMIG&YU@O=A1J#$RWcQw7~79#^y2TYm^La2z!;4^t~m!=23v7$1UJ}q;3qptrgrs ziem7S44&Uoj-!;q;QkCgqXphq>L%gV(`Ff;q84~RsUL;6nIl}JJjQ#i=MJ5;#ssHl zsxtg>rYeheXQ}CKbOkE!Mh}$MGR@BjwPANg$xuqM5>QN|HHT7qm71W<1*`;0tuixc zQ46%(47#laT44q~$)J=@PwTHYnOvP4R`C!szTNb)h}n zjMcFP++O^d!ll<3oZ>8}?=4o+p24~DG`$JlM}bp)&>Zd{Ze=|QeGqVpxm=E;c$mR| zU~oFS%ConNDAAs2Gpp;AS$#i*#w~_F)e(Wec$VS6ycOJD+|2L?^^l(8DW~r(_G9=% zpSFPaQQ%uz!5zd1mi`2TQ~c#}9K~b?_hE2Kdl}wW>`XaP@@8;KeHq?Q?8!KH9fQ;M z%36tw_#|s@Yi&g*Yb!YSV=eH^Xeq}=RnOAzXK>n&D;XV(@Z~M=RpxN1g25>rR$IX5 zwZJhVKu@I{X-f+nUNJNH2?nQhfJed%?!(}e4rrkn+?&BE9oCz}o8JH(-edhZn!$UD z*I7S)%;0q7$Z&h{dnRc*FgV3uhW8eqVe|*Lpd1stkGO}y&$og*h%*>mE}!Brm*XhT zV{pt)D2L)N!~2TESU;vPIK^Lv_Y;FyKi*()+K;jp=^{3>e!1KVt`nJdsc3~%($I2@ zlIBaAnn@ZN$|Ozm$81ideH*RNhKDk0=9;mKxRJG$dP>dVIuTL<=|N+xuqgg941d~(RL0Bz zyjV@~#|i~JVlU2S_+u6Voc5s%?<00)_)s}q%w&cPcQkxM;dEpGPWwcL_cJ`n`Xr0N zX`jfNx{ElQ;e!!~^d`7YWE#A@T4U0mmV-XgP+eKp)T#8Bp&+jajBwVb1f@@Y zWNo6lVx)S33abE4Zqrk&O^`cO!$v7`dZXN_Z3XWmIBL06b6TG zWl?@#F@W)FPAhmnF^bU!@=oq61s`J{9&H8JiSJUHVTG{PqI?_GVn)jk7@YR)IYtK~ zdo$W7B>G!7zTTxy=oBCy|666Z39?(z`>`}(Zj!(*F}!gr|016Jvfe^v?#5YUqzy~ z#>LemYVsr9`XtVqeEjtZPcErmP(6EK(u6U694D3u?g1N?k}&a{^lg7PtFq2n2^BFb zQiwph@4LHt#*ZI=`dmJinsEzacU9Ieo}2QN`pUR1B_)kx zJ9KbQ-Bh;l`KbZH<>CGjOS6tVGtF;a?xO1Ld+vrls{WwvYz{EWlhP2IGaU9t?8d@* zxs)QfFc^Ul&`WW!GJko#6f>wx|J=TI-5vT)shStCAZq2DA;R!Jh7MV;EU^jNeQ-V<3bUYi_%iX*VVGxQ;u6hs}%2$weh$JW)GP=ZEZwo)ZECl za_^GV#V1mNs-7%b`*u<4`iTXTrtTfGW7(mN8xM@!p#C7hf4rY-{1~s05ia^=Z*0jt zwKi$hjV1FhF77vCR%}Xjp!i0}=X*|k_}2M(+aPXC-m1ZPXwO;IuCL0A6OXN3uy@7m z=f}iE{I+@SD;3LTPcJTezBKKVv0+gM;_KHhEjvU0o18smW~4sDFL~^`>9ec5^_ZQQ zF*n%LccQy%a@x4bwDucPxX=yvonkePTbxy9i(k4`v}JMJU8M(oobvW>VY6@goMFWoi%zC(Aj5yOFDmLSJ%_?3Uz9$RmgdhJ=h7!2J-+Z@*i?_{32t6P z`VA@Aw{RsccN%!M(<1`CCu0X`x~38tpr=+C79gFiqm0M-NU1MCa0;CI1co8SLkz2tbDq< zfiqLK4Iz%BJM|28huMf7D`y$XaZ)^?4z0_|nm4abcjnJ0T7Lc<@s(G^Ih3X=F&lMc7GM=|(i^X7vy-C-vE_3^ck zF$lx&nE`)tU{wC-AwCmhT%>V9u3c*!?S!G}hy^|u9o}tv$ANzR$V=p#>0cy>wcP%~ z6Uo4=7&2#!`g2yU7fRGS@^*AYX)(BTL`Mw%y%Uxe_nfh#EY{w?q&{(B%%X~6(&{R~ zK4*Di_adu^^2bYlljce{$B#&XcenC;!-!r~MxU3``QNB7OTdhadY}~uK9Fr)V0AE! zTiTSLozjYChcrxBR_;y;7D&lUVMOTvt*=)mu8Z1qhCk`h^c(VD1y_zn-}#|13mC@{@^3x@UlUJ^!VI&@qR`uUNORgy1MLF}Xf+!r{fWo5MD3@{OJ{%sFL3 z;fw1gjLMm=^P3S~`I7nrePH}B_u|6b$|dpj(d7$bb*|xQV~W7K&f)Q1u0wUb`i(8x zT`_qZ6YWoIijwQxd!`B=ef%(nT%oI%PK za;Mz=yk(T{_77n|d zGXyoL+Ereycc*u`(8W52O*eYnylu-yR97zh>x;>!S5IE6uX+Ea?Q@5$p0H+9;5=OL z`Hdv4y}e~*kfg=FQ1}=h$^Z3T>HE=Rzk6r(%hN#lPa%7|p$->w%HK;WfYK+6woD2i zU6q-#Ez@)5lH7IUR&Nf>m^G-Pr2b$+Ey4oagHnbJ%6fiT?(C%DF45Vs1#3gIom1o8 zy*+h9tB=+l`xy$79Md*I7{IK!=xf=igWl*vPwBx>S3GW1mlxNJ1q0lY{(SDI>dw+4TheIN z^v!dmSHY9bGv=L|-i7PEgQPoQ`gyDjl>QO2&tRal;z%n`y zUgyGoz$Ft>S{0ckB_FKCbZ+Rti#iFBd z!A^Lz;OSX;#CC0iw0-T@OFB!ltjLy5rB6-ac8Zk?S9a%*pblk6AG@QBnYZYGVIeJy zg35`(bYm@Io8_1)dDauU4G7t~Id5(!o0{w`YXV$n=>~M{GiLPYs6MOuM1_tXPO_On z;|txC%1MpZmYuW5pfsXRhH7qIZ%M1|Y=mm<7?g1sE8$zY1Qxfye zlJ~uUA?PJy?1UJNhTB{t>3a3|8s*K;HOw94?#7?L`?QsM%8;T*ItwK{-x2w*U@SVb zQI63_-O@Cs+)GQ;bnsxRpxteEWr12vuI(+8Tyer~46p61Eps1^Esi&*91rCSP8zn@ zIBl3ev~J76Nhb~0CxrF@M_q>W_=Sy0dK#r-DP;<>+3qh$X0BWIW3m2WMak2*CLY?F zF*`VP(qmH^-><0t*v3mA?=oQW3+uo7$W@mR;IZ`1p{IUjHoR9*b`yMFH@8_>7(P4i;6TOF7v0JM_DeIQF1KL(59B6h!dN~)+%;roxDL&@spTTMRxEuP9EYzS7z%1{p$0`%bBb|hKoeSrM+VlvhD4aff{1AtcQxozU!!ie@MF#{p_vjIl zyK83EzTBSO`wfW#ACYdDmu%6SvQEU*0A&qga;tFRS3f?*DJ;kAQBmx(XygB&$Q9eWKOY-1HxSu>7YagowyG|u4MW`0re zbR?-STsy-HZ|06iO|gj3_z9=~P#+5AMrcCJmm{cTk*O& zu<52N$vWC&fbBB-0qdl4O;F_o>;8@c#ZU!Yy3Hh>CrD3nlq5F7 zU$aD-DhvicbY*cUUKn*PTDFbi z)d;wHFxj)k7&`)q&TK|62$RgzAEDLb1Sx0++>yMQp3}C(4)2w|VWQ8BUDJ1+OGw@H zOycAN1%b8M8TF$F6igpIGp0~o`0;y@>JP@2`=@Uyuaxi2l{0c{4$LPXN^YNinz=9c@prRs+Kk(fPwJ%I^X9F_ z23o{Hs20^_)#O*c(wMn5^_cX=n^LJn&3!D|E{g5#kxyV#j_i?FW;z{~6d2cZZ9qr4 zH6m2C)>>YNnT)I5`DRw}TdUN2wrtroLD;=v!)~(ujVZ;K|0W!nLpWZr;g;Q8xA#A_ zW!ewUpZtPU7OOuwclJ}RQdo9#{hl9d$#YWg;f5WaQj8UO)svq(oP2~n>kC@YNW)H4 zGq-M$$1eAuS$*_WO_2kvVB7HN;S@bHi;pmb1c&guhlZ`+Fs-(e&HT*uOGggP>EE|Q zpYY(|us-X0hXsa2IzHm;%x^8|)RE8UIwVY%{yu(F`i;%D+TV|nj;VzwpO`Gqw%2WL z$#ZSmfm214c8h^49S3UI5uEAhzCYKKV_@`ym#g-fnA@<@^!pLY**^J(oc`++&dwJ* zB!srh*>6e{nV#N_okNLb7Wzj|oyz#1m^MGiR+Mht%{ZR#_~^iljIs@pHSY7OSJv2y z$9UJr(l%^bzH;x}n)fcPdOqDNZ~OF|ozleKeeJqhM=mb0PR{VKwh8y-B9^5W{&?Z! zJAZsE^|t1EV3pmm=8JVX=eMLLQ7%?y78-%!a^HQ4JMOg)@gDmQF*nIK@tRJfFwSBc z0{sB*Kc_R4`U9+zzQEi?R9<*a1Q$UFBT|+A@63Zr*m^@J7T#;_^IzV&m`D%M*6_`X z{}MDpoRpzHXSmMy$9|i5-K2_fhHJc|@AT}U1_$(XHp&}=o)%DIe?&WCG&(EF@;#PE z+1zZ&=O`E6-XdwmOtr@YmPu%ntQqMsAIq9iPimWO1GT5IR0`CkC2j9>?Lqr&X%Fha z?#q#D!6POG{7t_g~JuodVX6O`UJu9Q2_ z1jR- zTjevo1I1gtGt%8v3%cL)9jJfLcj$vw?~Fa+szpz=N85w;`KdjqL#_!*TPK&`IMM{Ayu+ZH z+w5Lg83)>%GV~6E%Buj1ue=KA=|f9s4YhyT1f}@OX?uUy9<v)^D2owbK@EA;Oxyc0a%r?Z`_Nu)4Yl8Fg3{K@X?wrf z9<z)!a6%=b7}Ap?6GB)^fRo zfhH)EwQ^d~1ZA>TPD?iu2nrou!zzZJ^X`rbmIbgoGlkU2?6ls4X?V}cPE*51#Ef!v@a&VSoAy_0jD_#K zbc4LT2kE?w-$XaubC}1_kx9dcySaOeA0=+HKps3U+iEE1Q_TsSA58hHHPrq&6O?kk zoVGX95#+QcXrIgNrF955K`H0UB{({opp=^#l%BZRf&-OqGV~6EG7Gha;){3!if
e%L*2#&7!4HF7%D4x5E%Y;v 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

0LX$`->m8 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 z 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 YMe+k=W{_bo@~33>CBxq3=M;zk2j1$H>Hq)$ literal 0 HcmV?d00001 diff --git a/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/components/environment/EnvironmentComponent.kt b/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/components/environment/EnvironmentComponent.kt index dc96009cf5c..2dd14f830d7 100644 --- a/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/components/environment/EnvironmentComponent.kt +++ b/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/components/environment/EnvironmentComponent.kt @@ -17,4 +17,28 @@ package org.apache.solr.composeui.components.environment -interface EnvironmentComponent \ No newline at end of file +import kotlinx.coroutines.flow.StateFlow +import org.apache.solr.composeui.components.environment.data.JavaProperty +import org.apache.solr.composeui.components.environment.data.JvmData +import org.apache.solr.composeui.components.environment.data.SecurityConfig +import org.apache.solr.composeui.components.environment.data.SystemInformation +import org.apache.solr.composeui.components.environment.data.SystemMode +import org.apache.solr.composeui.components.environment.data.Versions + +interface EnvironmentComponent { + + val model: StateFlow + + data class Model( + val mode: SystemMode = SystemMode.Unknown, + val zkHost: String = "", + val solrHome: String = "", + val coreRoot: String = "", + val lucene: Versions = Versions(), + val jvm: JvmData = JvmData(), + val security: SecurityConfig = SecurityConfig(), + val system: SystemInformation = SystemInformation(), + val node: String = "", + val javaProperties: List = emptyList(), + ) +} \ No newline at end of file diff --git a/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/components/environment/data/JavaPropertiesResponse.kt b/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/components/environment/data/JavaPropertiesResponse.kt new file mode 100644 index 00000000000..abf8e1da16f --- /dev/null +++ b/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/components/environment/data/JavaPropertiesResponse.kt @@ -0,0 +1,10 @@ +package org.apache.solr.composeui.components.environment.data + +import kotlinx.serialization.SerialName +import kotlinx.serialization.Serializable + +@Serializable +data class JavaPropertiesResponse( + @SerialName("system.properties") + val properties: Map, +) diff --git a/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/components/environment/data/JavaProperty.kt b/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/components/environment/data/JavaProperty.kt new file mode 100644 index 00000000000..8e14c411d68 --- /dev/null +++ b/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/components/environment/data/JavaProperty.kt @@ -0,0 +1,3 @@ +package org.apache.solr.composeui.components.environment.data + +typealias JavaProperty = Pair \ No newline at end of file diff --git a/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/components/environment/data/JavaRuntimeInfo.kt b/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/components/environment/data/JavaRuntimeInfo.kt new file mode 100644 index 00000000000..787171d7f3b --- /dev/null +++ b/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/components/environment/data/JavaRuntimeInfo.kt @@ -0,0 +1,10 @@ +package org.apache.solr.composeui.components.environment.data + +import kotlinx.serialization.Serializable + +@Serializable +data class JavaRuntimeInfo( + val version: String = "", + val vendor: String = "", + val name: String? = null, +) diff --git a/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/components/environment/data/Jmx.kt b/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/components/environment/data/Jmx.kt new file mode 100644 index 00000000000..8683d30dade --- /dev/null +++ b/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/components/environment/data/Jmx.kt @@ -0,0 +1,11 @@ +package org.apache.solr.composeui.components.environment.data + +import kotlinx.serialization.Serializable + +@Serializable +data class Jmx( + val classpath: String = "", + val commandLineArgs: List = emptyList(), + val startTime: String = "", + val upTimeMS: Long = 0, +) diff --git a/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/components/environment/data/JvmData.kt b/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/components/environment/data/JvmData.kt new file mode 100644 index 00000000000..c984ad11cc6 --- /dev/null +++ b/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/components/environment/data/JvmData.kt @@ -0,0 +1,15 @@ +package org.apache.solr.composeui.components.environment.data + +import kotlinx.serialization.Serializable + +@Serializable +data class JvmData( + val version: String = "", + val name: String = "", + val spec: JavaRuntimeInfo = JavaRuntimeInfo(), + val jre: JavaRuntimeInfo = JavaRuntimeInfo(), + val vm: JavaRuntimeInfo = JavaRuntimeInfo(), + val processors: Int = 0, + val memory: JvmMemory = JvmMemory(), + val jmx: Jmx = Jmx(), +) diff --git a/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/components/environment/data/JvmMemory.kt b/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/components/environment/data/JvmMemory.kt new file mode 100644 index 00000000000..974b4404a1d --- /dev/null +++ b/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/components/environment/data/JvmMemory.kt @@ -0,0 +1,12 @@ +package org.apache.solr.composeui.components.environment.data + +import kotlinx.serialization.Serializable + +@Serializable +data class JvmMemory( + val free: String = "", + val total: String = "", + val max: String = "", + val used: String = "", + val raw: JvmMemoryRaw = JvmMemoryRaw(), +) diff --git a/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/components/environment/data/JvmMemoryRaw.kt b/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/components/environment/data/JvmMemoryRaw.kt new file mode 100644 index 00000000000..f5c915c95e0 --- /dev/null +++ b/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/components/environment/data/JvmMemoryRaw.kt @@ -0,0 +1,14 @@ +package org.apache.solr.composeui.components.environment.data + +import kotlinx.serialization.SerialName +import kotlinx.serialization.Serializable + +@Serializable +data class JvmMemoryRaw( + val free: Int = 0, + val total: Int = 0, + val max: Int = 0, + val used: Int = 0, + @SerialName("used%") + val usedPercentage: Double = 0.0, +) \ No newline at end of file diff --git a/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/components/environment/data/SecurityConfig.kt b/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/components/environment/data/SecurityConfig.kt new file mode 100644 index 00000000000..a106e445752 --- /dev/null +++ b/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/components/environment/data/SecurityConfig.kt @@ -0,0 +1,8 @@ +package org.apache.solr.composeui.components.environment.data + +import kotlinx.serialization.Serializable + +@Serializable +data class SecurityConfig( + val tls: Boolean = false, +) \ No newline at end of file diff --git a/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/components/environment/data/SystemData.kt b/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/components/environment/data/SystemData.kt new file mode 100644 index 00000000000..33e6bd2a938 --- /dev/null +++ b/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/components/environment/data/SystemData.kt @@ -0,0 +1,19 @@ +package org.apache.solr.composeui.components.environment.data + +import kotlinx.serialization.SerialName +import kotlinx.serialization.Serializable + +@Serializable +data class SystemData( + val mode: SystemMode, + val zkHost: String, + @SerialName("solr_home") + val solrHome: String, + @SerialName("core_root") + val coreRoot: String, + val lucene: Versions, + val jvm: JvmData, + val security: SecurityConfig, + val system: SystemInformation, + val node: String, +) diff --git a/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/components/environment/data/SystemInformation.kt b/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/components/environment/data/SystemInformation.kt new file mode 100644 index 00000000000..856995b87c8 --- /dev/null +++ b/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/components/environment/data/SystemInformation.kt @@ -0,0 +1,25 @@ +package org.apache.solr.composeui.components.environment.data + +import kotlinx.serialization.Serializable + +@Serializable +data class SystemInformation( + val name: String = "", + val arch: String = "", + val availableProcessors: Int = 0, + val systemLoadAverage: Double = 0.0, + val version: String = "", + val committedVirtualMemorySize: Long = 0, + val cpuLoad: Float = 0f, + val freeMemorySize: Long = 0, + val freePhysicalMemorySize: Long = 0, + val freeSwapSpaceSize: Long = 0, + val processCpuLoad: Float = 0f, + val processCpuTime: Long = 0, + val systemCpuLoad: Float = 0f, + val totalMemorySize: Long = 0, + val totalPhysicalMemorySize: Long = 0, + val totalSwapSpaceSize: Long = 0, + val maxFileDescriptorCount: Long = 0, + val openFileDescriptorCount: Long = 0, +) \ No newline at end of file diff --git a/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/components/environment/data/SystemMode.kt b/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/components/environment/data/SystemMode.kt new file mode 100644 index 00000000000..c8207e02382 --- /dev/null +++ b/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/components/environment/data/SystemMode.kt @@ -0,0 +1,13 @@ +package org.apache.solr.composeui.components.environment.data + +import kotlinx.serialization.SerialName +import kotlinx.serialization.Serializable + +@Serializable +enum class SystemMode { + Unknown, + @SerialName("solrcloud") + SolrCloud, + @SerialName("standalone") + Standalone, +} diff --git a/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/components/environment/data/Versions.kt b/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/components/environment/data/Versions.kt new file mode 100644 index 00000000000..33e7d0bea14 --- /dev/null +++ b/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/components/environment/data/Versions.kt @@ -0,0 +1,16 @@ +package org.apache.solr.composeui.components.environment.data + +import kotlinx.serialization.SerialName +import kotlinx.serialization.Serializable + +@Serializable +data class Versions( + @SerialName("solr-spec-version") + val solrSpecVersion: String = "", + @SerialName("solr-impl-version") + val solrImplVersion: String = "", + @SerialName("lucene-spec-version") + val luceneSpecVersion: String = "", + @SerialName("lucene-impl-version") + val luceneImplVersion: String = "", +) diff --git a/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/components/environment/integration/DefaultEnvironmentComponent.kt b/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/components/environment/integration/DefaultEnvironmentComponent.kt index c9e5fe8feb3..551387be18b 100644 --- a/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/components/environment/integration/DefaultEnvironmentComponent.kt +++ b/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/components/environment/integration/DefaultEnvironmentComponent.kt @@ -17,11 +17,33 @@ package org.apache.solr.composeui.components.environment.integration +import com.arkivanov.mvikotlin.core.instancekeeper.getStore import com.arkivanov.mvikotlin.core.store.StoreFactory +import com.arkivanov.mvikotlin.extensions.coroutines.stateFlow +import io.ktor.client.HttpClient +import kotlinx.coroutines.ExperimentalCoroutinesApi import org.apache.solr.composeui.components.environment.EnvironmentComponent +import org.apache.solr.composeui.components.environment.store.EnvironmentStoreProvider import org.apache.solr.composeui.utils.AppComponentContext +import org.apache.solr.composeui.utils.coroutineScope +import org.apache.solr.composeui.utils.map class DefaultEnvironmentComponent( componentContext: AppComponentContext, storeFactory: StoreFactory, -) : EnvironmentComponent, AppComponentContext by componentContext + httpClient: HttpClient, +) : EnvironmentComponent, AppComponentContext by componentContext { + + private val mainScope = coroutineScope(mainContext) + + private val store = instanceKeeper.getStore { + EnvironmentStoreProvider( + storeFactory = storeFactory, + client = HttpEnvironmentStoreClient(httpClient), + ioContext = ioContext, + ).provide() + } + + @OptIn(ExperimentalCoroutinesApi::class) + override val model = store.stateFlow.map(mainScope, environmentStateToModel) +} diff --git a/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/components/environment/integration/HttpEnvironmentStoreClient.kt b/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/components/environment/integration/HttpEnvironmentStoreClient.kt new file mode 100644 index 00000000000..8a24e911473 --- /dev/null +++ b/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/components/environment/integration/HttpEnvironmentStoreClient.kt @@ -0,0 +1,41 @@ +package org.apache.solr.composeui.components.environment.integration + +import io.ktor.client.HttpClient +import io.ktor.client.call.body +import io.ktor.client.request.get +import io.ktor.http.isSuccess +import org.apache.solr.composeui.components.environment.data.JavaPropertiesResponse +import org.apache.solr.composeui.components.environment.data.JavaProperty +import org.apache.solr.composeui.components.environment.data.SystemData +import org.apache.solr.composeui.components.environment.store.EnvironmentStoreProvider + +class HttpEnvironmentStoreClient( + private val httpClient: HttpClient, +) : EnvironmentStoreProvider.Client { + + override suspend fun getSystemData(): Result { + val response = httpClient.get("api/node/system") + + return when { + response.status.isSuccess() -> Result.success(response.body()) + else -> Result.failure(Exception("Unknown error")) + // TODO Add proper error handling + } + } + + override suspend fun getJavaProperties(): Result> { + val response = httpClient.get("api/node/properties") + + return when { + response.status.isSuccess() -> { + val javaProperties = response.body() + .properties + .map { (key, value) -> key to value } + + Result.success(javaProperties) + } + else -> Result.failure(Exception("Unknown error")) + // TODO Add proper error handling + } + } +} diff --git a/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/components/environment/integration/Mappers.kt b/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/components/environment/integration/Mappers.kt new file mode 100644 index 00000000000..e14e47d37de --- /dev/null +++ b/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/components/environment/integration/Mappers.kt @@ -0,0 +1,19 @@ +package org.apache.solr.composeui.components.environment.integration + +import org.apache.solr.composeui.components.environment.EnvironmentComponent +import org.apache.solr.composeui.components.environment.store.EnvironmentStore + +internal val environmentStateToModel: (EnvironmentStore.State) -> EnvironmentComponent.Model = { + EnvironmentComponent.Model( + mode = it.mode, + zkHost = it.zkHost, + solrHome = it.solrHome, + coreRoot = it.coreRoot, + lucene = it.lucene, + jvm = it.jvm, + security = it.security, + system = it.system, + node = it.node, + javaProperties = it.javaProperties, + ) +} diff --git a/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/components/environment/store/EnvironmentStore.kt b/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/components/environment/store/EnvironmentStore.kt new file mode 100644 index 00000000000..34ada1037df --- /dev/null +++ b/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/components/environment/store/EnvironmentStore.kt @@ -0,0 +1,32 @@ +package org.apache.solr.composeui.components.environment.store + +import com.arkivanov.mvikotlin.core.store.Store +import org.apache.solr.composeui.components.environment.data.JavaProperty +import org.apache.solr.composeui.components.environment.data.JvmData +import org.apache.solr.composeui.components.environment.data.SecurityConfig +import org.apache.solr.composeui.components.environment.data.SystemInformation +import org.apache.solr.composeui.components.environment.data.SystemMode +import org.apache.solr.composeui.components.environment.data.Versions +import org.apache.solr.composeui.components.environment.store.EnvironmentStore.Intent +import org.apache.solr.composeui.components.environment.store.EnvironmentStore.State + +internal interface EnvironmentStore : Store { + + sealed interface Intent { + + data object FetchSystemData: Intent + } + + data class State( + val mode: SystemMode = SystemMode.Unknown, + val zkHost: String = "", + val solrHome: String = "", + val coreRoot: String = "", + val lucene: Versions = Versions(), + val jvm: JvmData = JvmData(), + val security: SecurityConfig = SecurityConfig(), + val system: SystemInformation = SystemInformation(), + val node: String = "", + val javaProperties: List = emptyList(), + ) +} diff --git a/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/components/environment/store/EnvironmentStoreProvider.kt b/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/components/environment/store/EnvironmentStoreProvider.kt new file mode 100644 index 00000000000..efc875ac025 --- /dev/null +++ b/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/components/environment/store/EnvironmentStoreProvider.kt @@ -0,0 +1,109 @@ +package org.apache.solr.composeui.components.environment.store + +import com.arkivanov.mvikotlin.core.store.Reducer +import com.arkivanov.mvikotlin.core.store.SimpleBootstrapper +import com.arkivanov.mvikotlin.core.store.Store +import com.arkivanov.mvikotlin.core.store.StoreFactory +import com.arkivanov.mvikotlin.extensions.coroutines.CoroutineExecutor +import kotlin.coroutines.CoroutineContext +import kotlinx.coroutines.launch +import kotlinx.coroutines.withContext +import org.apache.solr.composeui.components.environment.data.JavaProperty +import org.apache.solr.composeui.components.environment.data.SystemData +import org.apache.solr.composeui.components.environment.store.EnvironmentStore.Intent +import org.apache.solr.composeui.components.environment.store.EnvironmentStore.State + +internal class EnvironmentStoreProvider( + private val storeFactory: StoreFactory, + private val client: Client, + private val ioContext: CoroutineContext, +) { + + fun provide(): EnvironmentStore = object : + EnvironmentStore, + Store by storeFactory.create( + name = "HomeMainStore", + initialState = State(), + bootstrapper = SimpleBootstrapper(Action.FetchInitialSystemData), + executorFactory = ::ExecutorImpl, + reducer = ReducerImpl, + ) {} + + private sealed interface Action { + + data object FetchInitialSystemData: Action + } + + private sealed interface Message { + + data class SystemDataUpdated(val data: SystemData) : Message + + data class JavaPropertiesUpdated(val properties: List) : Message + } + + private inner class ExecutorImpl : CoroutineExecutor() { + + override fun executeAction(action: Action) = when(action) { + Action.FetchInitialSystemData -> fetchSystemData() + } + + override fun executeIntent(intent: Intent) { + when (intent) { + Intent.FetchSystemData -> fetchSystemData() + } + } + + private fun fetchSystemData() { + scope.launch { // TODO Add coroutine exception handler + withContext(ioContext) { + client.getSystemData() + }.onSuccess { + dispatch(Message.SystemDataUpdated(it)) + } + + withContext(ioContext) { + client.getJavaProperties() + }.onSuccess { + dispatch(Message.JavaPropertiesUpdated(it)) + } + // TODO Add error handling + } + } + } + + private object ReducerImpl : Reducer { + override fun State.reduce(msg: Message): State = when (msg) { + is Message.SystemDataUpdated -> copy( + mode = msg.data.mode, + zkHost = msg.data.zkHost, + solrHome = msg.data.solrHome, + coreRoot = msg.data.coreRoot, + lucene = msg.data.lucene, + jvm = msg.data.jvm, + security = msg.data.security, + system = msg.data.system, + node = msg.data.node, + ) + is Message.JavaPropertiesUpdated -> copy( + javaProperties = msg.properties, + ) + } + } + + interface Client { + + /** + * Fetches a set of system data. + * + * @return Result with the system data fetched. + */ + suspend fun getSystemData(): Result + + /** + * Fetches the configured java properties. + * + * @return Result with a list of [JavaProperty]s. + */ + suspend fun getJavaProperties(): Result> + } +} diff --git a/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/components/main/integration/DefaultMainComponent.kt b/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/components/main/integration/DefaultMainComponent.kt index dc0da8a9647..5e55fb8583c 100644 --- a/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/components/main/integration/DefaultMainComponent.kt +++ b/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/components/main/integration/DefaultMainComponent.kt @@ -23,6 +23,7 @@ import com.arkivanov.decompose.router.stack.bringToFront import com.arkivanov.decompose.router.stack.childStack import com.arkivanov.decompose.value.Value import com.arkivanov.mvikotlin.core.store.StoreFactory +import io.ktor.client.HttpClient import kotlinx.serialization.Serializable import org.apache.solr.composeui.components.environment.EnvironmentComponent import org.apache.solr.composeui.components.environment.integration.DefaultEnvironmentComponent @@ -54,6 +55,7 @@ class DefaultMainComponent internal constructor( constructor( componentContext: AppComponentContext, storeFactory: StoreFactory, + httpClient: HttpClient, destination: String? = null, ) : this( componentContext = componentContext, @@ -63,6 +65,7 @@ class DefaultMainComponent internal constructor( DefaultEnvironmentComponent( componentContext = childContext, storeFactory = storeFactory, + httpClient = httpClient, ) }, loggingComponent = { childContext -> diff --git a/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/components/root/integration/SimpleRootComponent.kt b/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/components/root/integration/SimpleRootComponent.kt index 577ae2abbbd..a58888f92cf 100644 --- a/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/components/root/integration/SimpleRootComponent.kt +++ b/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/components/root/integration/SimpleRootComponent.kt @@ -22,6 +22,7 @@ import com.arkivanov.decompose.router.stack.StackNavigation import com.arkivanov.decompose.router.stack.childStack import com.arkivanov.decompose.value.Value import com.arkivanov.mvikotlin.core.store.StoreFactory +import io.ktor.client.HttpClient import kotlinx.serialization.Serializable import org.apache.solr.composeui.components.main.MainComponent import org.apache.solr.composeui.components.main.integration.DefaultMainComponent @@ -55,6 +56,7 @@ class SimpleRootComponent( constructor( componentContext: AppComponentContext, storeFactory: StoreFactory, + httpClient: HttpClient, destination: String? = null, ) : this( componentContext = componentContext, @@ -63,6 +65,7 @@ class SimpleRootComponent( DefaultMainComponent( componentContext = childContext, storeFactory = storeFactory, + httpClient = httpClient, destination = destination, ) }, diff --git a/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/ui/components/SolrCard.kt b/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/ui/components/SolrCard.kt new file mode 100644 index 00000000000..a681501cf23 --- /dev/null +++ b/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/ui/components/SolrCard.kt @@ -0,0 +1,30 @@ +package org.apache.solr.composeui.ui.components + +import androidx.compose.foundation.BorderStroke +import androidx.compose.foundation.background +import androidx.compose.foundation.border +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.ColumnScope +import androidx.compose.foundation.layout.padding +import androidx.compose.material3.MaterialTheme +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.unit.dp + +@Composable +fun SolrCard( + modifier: Modifier = Modifier, + verticalArrangement: Arrangement.Vertical = Arrangement.Top, + horizontalAlignment: Alignment.Horizontal = Alignment.Start, + content: @Composable ColumnScope.() -> Unit, +) = Column( + modifier = modifier + .background(MaterialTheme.colorScheme.surfaceContainer) + .border(BorderStroke(1.dp, MaterialTheme.colorScheme.outlineVariant)) + .padding(16.dp), + verticalArrangement = verticalArrangement, + horizontalAlignment = horizontalAlignment, + content = content, +) diff --git a/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/ui/environment/CommandLineArgumentsCard.kt b/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/ui/environment/CommandLineArgumentsCard.kt new file mode 100644 index 00000000000..c34c5b9602f --- /dev/null +++ b/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/ui/environment/CommandLineArgumentsCard.kt @@ -0,0 +1,53 @@ +package org.apache.solr.composeui.ui.environment + +import androidx.compose.foundation.BorderStroke +import androidx.compose.foundation.background +import androidx.compose.foundation.border +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.padding +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Text +import androidx.compose.material3.surfaceColorAtElevation +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.unit.dp +import org.apache.solr.composeui.components.environment.data.JavaProperty +import org.apache.solr.composeui.ui.components.SolrCard +import org.apache.solr.composeui.ui.theme.Fonts + +@Composable +internal fun CommandLineArgumentsCard( + modifier: Modifier = Modifier, + arguments: List, +) = SolrCard( + modifier = modifier, + verticalArrangement = Arrangement.spacedBy(16.dp) +) { + Text( + text = "Command Line Arguments", + style = MaterialTheme.typography.headlineSmall, + color = MaterialTheme.colorScheme.onSurfaceVariant, + ) + Column( + modifier = Modifier.fillMaxWidth() + .border(BorderStroke(1.dp, MaterialTheme.colorScheme.outlineVariant)) + ) { + arguments.forEachIndexed { index, argument -> + Text( + modifier = Modifier.fillMaxWidth() + .background( + MaterialTheme.colorScheme.surfaceColorAtElevation( + if(index % 2 == 0) 1.dp else 0.dp, + ) + ).padding(horizontal = 8.dp, vertical = 4.dp), + text = argument, + fontFamily = Fonts.firaCode(), + style = MaterialTheme.typography.labelLarge, + color = MaterialTheme.colorScheme.onSurfaceVariant, + ) + } + } +} diff --git a/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/ui/environment/EnvironmentContent.kt b/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/ui/environment/EnvironmentContent.kt index 1df34042b4f..73b503b5640 100644 --- a/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/ui/environment/EnvironmentContent.kt +++ b/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/ui/environment/EnvironmentContent.kt @@ -17,16 +17,86 @@ package org.apache.solr.composeui.ui.environment -import androidx.compose.material3.Text +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.material3.windowsizeclass.ExperimentalMaterial3WindowSizeClassApi +import androidx.compose.material3.windowsizeclass.WindowWidthSizeClass +import androidx.compose.material3.windowsizeclass.calculateWindowSizeClass import androidx.compose.runtime.Composable +import androidx.compose.runtime.collectAsState +import androidx.compose.runtime.getValue import androidx.compose.ui.Modifier +import androidx.compose.ui.unit.dp import org.apache.solr.composeui.components.environment.EnvironmentComponent +@OptIn(ExperimentalMaterial3WindowSizeClassApi::class) @Composable fun EnvironmentContent( component: EnvironmentComponent, modifier: Modifier = Modifier, ) { - Text("Environment section") - // TODO Add logging content here + val model by component.model.collectAsState() + val windowSizeClass = calculateWindowSizeClass() + val isLargeScreen = windowSizeClass.widthSizeClass > WindowWidthSizeClass.Medium + + if (isLargeScreen) EnvironmentContentExpanded( + modifier = modifier, + model = model, + ) else EnvironmentContentMedium( + modifier = modifier, + model = model, + ) +} + +@Composable +private fun EnvironmentContentExpanded( + model: EnvironmentComponent.Model, + modifier: Modifier = Modifier, +) = Row( + modifier = modifier, + horizontalArrangement = Arrangement.spacedBy(16.dp), +) { + Column( + modifier = Modifier.weight(1f), + verticalArrangement = Arrangement.spacedBy(16.dp), + ) { + VersionsCard( + modifier = Modifier.fillMaxWidth(), + versions = model.lucene, + jvm = model.jvm, + ) + JavaPropertiesCard( + modifier = Modifier.fillMaxWidth(), + properties = model.javaProperties, + ) + } + CommandLineArgumentsCard( + modifier = Modifier.weight(1f), + arguments = model.jvm.jmx.commandLineArgs, + ) +} + +@Composable +private fun EnvironmentContentMedium( + model: EnvironmentComponent.Model, + modifier: Modifier = Modifier, +) = Column( + modifier = modifier, + verticalArrangement = Arrangement.spacedBy(16.dp), +) { + VersionsCard( + modifier = Modifier.fillMaxWidth(), + versions = model.lucene, + jvm = model.jvm, + ) + JavaPropertiesCard( + modifier = Modifier.fillMaxWidth(), + properties = model.javaProperties, + ) + CommandLineArgumentsCard( + modifier = Modifier.fillMaxWidth(), + arguments = model.jvm.jmx.commandLineArgs, + ) } diff --git a/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/ui/environment/JavaPropertiesCard.kt b/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/ui/environment/JavaPropertiesCard.kt new file mode 100644 index 00000000000..b2a6bae9469 --- /dev/null +++ b/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/ui/environment/JavaPropertiesCard.kt @@ -0,0 +1,73 @@ +package org.apache.solr.composeui.ui.environment + +import androidx.compose.foundation.BorderStroke +import androidx.compose.foundation.background +import androidx.compose.foundation.border +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.padding +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Text +import androidx.compose.material3.surfaceColorAtElevation +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.unit.dp +import org.apache.solr.composeui.components.environment.data.JavaProperty +import org.apache.solr.composeui.ui.components.SolrCard +import org.apache.solr.composeui.ui.theme.Fonts + +@Composable +internal fun JavaPropertiesCard( + modifier: Modifier = Modifier, + properties: List, +) = SolrCard( + modifier = modifier, + verticalArrangement = Arrangement.spacedBy(16.dp) +) { + Text( + text = "Java Properties", + style = MaterialTheme.typography.headlineSmall, + color = MaterialTheme.colorScheme.onSurfaceVariant, + ) + Column( + modifier = Modifier.fillMaxWidth() + .border(BorderStroke(1.dp, MaterialTheme.colorScheme.outlineVariant)) + ) { + properties.forEachIndexed { index, property -> + JavaPropertyEntry( + property = property, + isOdd = index % 2 == 0, + ) + } + } +} + +@Composable +private fun JavaPropertyEntry( + modifier: Modifier = Modifier, + property: JavaProperty, + isOdd: Boolean = false, +) = Row( + modifier = modifier.background( + MaterialTheme.colorScheme.surfaceColorAtElevation( + if (isOdd) 1.dp else 0.dp, + ) + ).padding(horizontal = 8.dp, vertical = 4.dp), +) { + Text( + modifier = Modifier.weight(1f), + text = property.first, + fontFamily = Fonts.firaCode(), + style = MaterialTheme.typography.labelLarge, + color = MaterialTheme.colorScheme.onSurfaceVariant, + ) + Text( + modifier = Modifier.weight(1f), + text = property.second, + fontFamily = Fonts.firaCode(), + style = MaterialTheme.typography.bodyMedium, + color = MaterialTheme.colorScheme.onSurface, + ) +} diff --git a/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/ui/environment/VersionsCard.kt b/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/ui/environment/VersionsCard.kt new file mode 100644 index 00000000000..6888474351d --- /dev/null +++ b/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/ui/environment/VersionsCard.kt @@ -0,0 +1,74 @@ +package org.apache.solr.composeui.ui.environment + +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.width +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.text.style.TextAlign +import androidx.compose.ui.unit.dp +import org.apache.solr.composeui.components.environment.data.JvmData +import org.apache.solr.composeui.components.environment.data.Versions +import org.apache.solr.composeui.ui.components.SolrCard + +@Composable +internal fun VersionsCard( + modifier: Modifier = Modifier, + versions: Versions, + jvm: JvmData, +) = SolrCard( + modifier = modifier, + verticalArrangement = Arrangement.spacedBy(16.dp) +) { + Text( + text = "Versions", + style = MaterialTheme.typography.headlineSmall, + color = MaterialTheme.colorScheme.onSurfaceVariant, + ) + VersionEntry( + label = "solr-spec", + value = versions.solrSpecVersion, + ) + VersionEntry( + label = "solr-impl", + value = versions.solrImplVersion, + ) + VersionEntry( + label = "lucene-spec", + value = versions.luceneSpecVersion, + ) + VersionEntry( + label = "lucene-impl", + value = versions.luceneImplVersion, + ) + VersionEntry( + label = "Runtime", + value = "${jvm.name} ${jvm.version}", + ) +} + +@Composable +private fun VersionEntry( + label: String, + value: String, +) = Row( + modifier = Modifier.fillMaxWidth(), + horizontalArrangement = Arrangement.spacedBy(16.dp), +) { + Text( + modifier = Modifier.width(96.dp), + text = label, + textAlign = TextAlign.End, + style = MaterialTheme.typography.labelLarge, + color = MaterialTheme.colorScheme.onSurfaceVariant, + ) + Text( + modifier = Modifier.weight(1f), + text = value, + style = MaterialTheme.typography.bodyMedium, + color = MaterialTheme.colorScheme.onSurface, + ) +} diff --git a/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/ui/main/MainContent.kt b/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/ui/main/MainContent.kt index 1799cdc6874..bb9f373bc8a 100644 --- a/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/ui/main/MainContent.kt +++ b/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/ui/main/MainContent.kt @@ -19,20 +19,18 @@ package org.apache.solr.composeui.ui.main import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.fillMaxHeight -import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.width +import androidx.compose.foundation.rememberScrollState +import androidx.compose.foundation.verticalScroll import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue -import androidx.compose.runtime.mutableStateOf -import androidx.compose.runtime.remember -import androidx.compose.runtime.setValue import androidx.compose.ui.Modifier import androidx.compose.ui.unit.dp import com.arkivanov.decompose.extensions.compose.stack.Children import com.arkivanov.decompose.extensions.compose.subscribeAsState import org.apache.solr.composeui.components.main.MainComponent -import org.apache.solr.composeui.ui.navigation.MainMenu -import org.apache.solr.composeui.components.main.MainNavigationComponent import org.apache.solr.composeui.components.main.integration.asMainMenu import org.apache.solr.composeui.ui.environment.EnvironmentContent import org.apache.solr.composeui.ui.logging.LoggingContent @@ -49,6 +47,7 @@ fun MainContent( modifier: Modifier = Modifier, ) { val childStack by component.childStack.subscribeAsState() + val scrollState = rememberScrollState() Row(modifier = modifier) { NavigationSideBar( @@ -65,11 +64,13 @@ fun MainContent( when(val child = it.instance) { is MainComponent.Child.Environment -> EnvironmentContent( component = child.component, - modifier = Modifier.fillMaxSize(), + modifier = Modifier.fillMaxWidth() + .verticalScroll(scrollState) + .padding(16.dp), ) is MainComponent.Child.Logging -> LoggingContent( component = child.component, - modifier = Modifier.fillMaxSize(), + modifier = Modifier.fillMaxWidth(), ) } } diff --git a/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/ui/theme/Fonts.kt b/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/ui/theme/Fonts.kt index 66b96886544..a4059b037cf 100644 --- a/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/ui/theme/Fonts.kt +++ b/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/ui/theme/Fonts.kt @@ -17,13 +17,14 @@ package org.apache.solr.composeui.ui.theme -import androidx.compose.material3.Typography +import androidx.compose.runtime.Composable +import androidx.compose.ui.text.font.FontFamily +import org.apache.solr.compose_ui.generated.resources.Res +import org.apache.solr.compose_ui.generated.resources.firacode_variable +import org.jetbrains.compose.resources.Font -/** - * Custom typography that styles headlines and titles with a different font. - */ -val SolrCodeTypography = Typography( - // TODO Override headlines and titles -) +object Fonts { -// TODO Add fonts for code blocks + @Composable + fun firaCode() = FontFamily(Font(Res.font.firacode_variable)) +} diff --git a/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/ui/theme/Theme.kt b/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/ui/theme/Theme.kt index a4c1c52f594..224f89735e5 100644 --- a/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/ui/theme/Theme.kt +++ b/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/ui/theme/Theme.kt @@ -435,7 +435,7 @@ fun SolrTheme( MaterialTheme( colorScheme = colorScheme, shapes = SolrShapes, - typography = SolrCodeTypography, + typography = SolrTypography(), content = content, ) } diff --git a/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/ui/theme/Typography.kt b/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/ui/theme/Typography.kt new file mode 100644 index 00000000000..83ac39a8254 --- /dev/null +++ b/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/ui/theme/Typography.kt @@ -0,0 +1,41 @@ +package org.apache.solr.composeui.ui.theme + +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Typography +import androidx.compose.runtime.Composable +import androidx.compose.ui.text.TextStyle +import androidx.compose.ui.text.font.FontFamily +import androidx.compose.ui.text.font.FontStyle +import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.unit.sp +import org.apache.solr.compose_ui.generated.resources.Res +import org.apache.solr.compose_ui.generated.resources.raleway_variable +import org.jetbrains.compose.resources.Font + +/** + * Custom typography that styles headlines and titles with a different font. + */ +@Composable +fun SolrTypography() = Typography( + headlineLarge = MaterialTheme.typography.headlineLarge.copy( + fontFamily = FontFamily(Font(Res.font.raleway_variable)), + fontWeight = FontWeight.Normal, + fontSize = 32.sp, + lineHeight = 40.sp, + letterSpacing= 0.sp, + ), + headlineMedium = MaterialTheme.typography.headlineMedium.copy( + fontFamily = FontFamily(Font(Res.font.raleway_variable)), + fontWeight = FontWeight.Normal, + fontSize = 28.sp, + lineHeight = 36.sp, + letterSpacing= 0.sp, + ), + headlineSmall = MaterialTheme.typography.headlineSmall.copy( + fontFamily = FontFamily(Font(Res.font.raleway_variable)), + fontWeight = FontWeight.Normal, + fontSize = 24.sp, + lineHeight = 32.sp, + letterSpacing= 0.sp, + ) +) diff --git a/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/utils/CoroutineScopeExt.kt b/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/utils/CoroutineScopeExt.kt new file mode 100644 index 00000000000..3c61eccbf1b --- /dev/null +++ b/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/utils/CoroutineScopeExt.kt @@ -0,0 +1,57 @@ +package org.apache.solr.composeui.utils + +import com.arkivanov.essenty.lifecycle.Lifecycle +import com.arkivanov.essenty.lifecycle.LifecycleOwner +import com.arkivanov.essenty.lifecycle.doOnDestroy +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.cancel +import kotlinx.coroutines.flow.SharingStarted +import kotlinx.coroutines.flow.StateFlow +import kotlinx.coroutines.flow.map +import kotlinx.coroutines.flow.stateIn +import kotlin.coroutines.CoroutineContext + +/** + * Function for creating a coroutine scope for a [lifecycle] that cancels automatically + * when [lifecycle] is destroyed. + * + * @param context The [CoroutineContext] to use for the scope. + * @param lifecycle The lifecycle this coroutine should be aware of. + * + * @return Returns a lifecycle-aware coroutine scope. + */ +fun CoroutineScope(context: CoroutineContext, lifecycle: Lifecycle): CoroutineScope { + val scope = CoroutineScope(context) + lifecycle.doOnDestroy(scope::cancel) + return scope +} + +/** + * Function for creating a coroutine scope from a lifecycle that cancels automatically + * when lifecycle is destroyed. + * + * @param context The [CoroutineContext] to use for the scope. + * + * @return Returns a lifecycle-aware coroutine scope. + */ +fun LifecycleOwner.coroutineScope(context: CoroutineContext): CoroutineScope = + CoroutineScope(context, lifecycle) + + +/** + * StateFlow mapping function that maps one stateflow to another stateflow applying + * [mapper] on the state. [coroutineScope] used for the mapping work. + * + * @param coroutineScope The scope in which the mapping should be executed + * @param mapper The mapper function to use on [T]. + * @param T The state to map + * @param M the mapped / resulting state + */ +fun StateFlow.map( + coroutineScope : CoroutineScope, + mapper : (value : T) -> M +) : StateFlow = map { mapper(it) }.stateIn( + coroutineScope, + SharingStarted.Eagerly, + mapper(value) +) diff --git a/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/utils/HttpClientUtils.kt b/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/utils/HttpClientUtils.kt new file mode 100644 index 00000000000..30de3618d4c --- /dev/null +++ b/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/utils/HttpClientUtils.kt @@ -0,0 +1,24 @@ +package org.apache.solr.composeui.utils + +import io.ktor.client.HttpClient +import io.ktor.client.plugins.contentnegotiation.ContentNegotiation +import io.ktor.client.plugins.defaultRequest +import io.ktor.serialization.kotlinx.json.json +import kotlinx.serialization.json.Json + +/** + * Function that returns a simple HTTP client that is preconfigured with a base + * URL. + */ +fun getDefaultClient() = HttpClient { + defaultRequest { + url("http://localhost:8983/") + } + install(ContentNegotiation) { + json( + Json { + ignoreUnknownKeys = true + } + ) + } +} \ No newline at end of file diff --git a/solr/compose-ui/src/desktopMain/kotlin/org/apache/solr/composeui/Main.kt b/solr/compose-ui/src/desktopMain/kotlin/org/apache/solr/composeui/Main.kt index 2a3e2497b31..3f2e055dca1 100644 --- a/solr/compose-ui/src/desktopMain/kotlin/org/apache/solr/composeui/Main.kt +++ b/solr/compose-ui/src/desktopMain/kotlin/org/apache/solr/composeui/Main.kt @@ -19,6 +19,7 @@ package org.apache.solr.composeui import androidx.compose.foundation.isSystemInDarkTheme import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Surface import androidx.compose.ui.Modifier import androidx.compose.ui.window.Window @@ -29,6 +30,8 @@ import com.arkivanov.decompose.extensions.compose.lifecycle.LifecycleController import com.arkivanov.essenty.lifecycle.LifecycleRegistry import com.arkivanov.mvikotlin.core.utils.setMainThreadId import com.arkivanov.mvikotlin.main.store.DefaultStoreFactory +import io.ktor.client.HttpClient +import io.ktor.client.plugins.defaultRequest import java.awt.Dimension import kotlinx.coroutines.Dispatchers import org.apache.solr.composeui.components.root.RootComponent @@ -36,6 +39,7 @@ import org.apache.solr.composeui.components.root.integration.SimpleRootComponent import org.apache.solr.composeui.ui.root.RootContent import org.apache.solr.composeui.ui.theme.SolrTheme import org.apache.solr.composeui.utils.DefaultAppComponentContext +import org.apache.solr.composeui.utils.getDefaultClient /** * Entry point of the Compose application for all JVM-based (desktop) targets. @@ -53,12 +57,16 @@ fun main() { val storeFactory = DefaultStoreFactory() + // TODO Let the user provide the URL via input field on desktop + val httpClient = getDefaultClient() + val root: RootComponent = runOnUiThread { setMainThreadId(Thread.currentThread().id) SimpleRootComponent( componentContext = componentContext, storeFactory = storeFactory, + httpClient = httpClient, ) } @@ -73,8 +81,11 @@ fun main() { ) { window.minimumSize = Dimension(720, 560) - SolrTheme(useDarkTheme = isSystemInDarkTheme()) { - Surface(modifier = Modifier.fillMaxSize()) { + SolrTheme(useDarkTheme = false) { + Surface( + modifier = Modifier.fillMaxSize(), + color = MaterialTheme.colorScheme.background, + ) { RootContent(root) } } diff --git a/solr/compose-ui/src/wasmJsMain/kotlin/org/apache/solr/composeui/Main.kt b/solr/compose-ui/src/wasmJsMain/kotlin/org/apache/solr/composeui/Main.kt index c0d9d6326ac..0723c4a1c17 100644 --- a/solr/compose-ui/src/wasmJsMain/kotlin/org/apache/solr/composeui/Main.kt +++ b/solr/compose-ui/src/wasmJsMain/kotlin/org/apache/solr/composeui/Main.kt @@ -19,6 +19,7 @@ package org.apache.solr.composeui import androidx.compose.foundation.isSystemInDarkTheme import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Surface import androidx.compose.material3.Text import androidx.compose.ui.ExperimentalComposeUiApi @@ -27,6 +28,8 @@ import androidx.compose.ui.window.ComposeViewport import com.arkivanov.decompose.DefaultComponentContext import com.arkivanov.essenty.lifecycle.LifecycleRegistry import com.arkivanov.mvikotlin.main.store.DefaultStoreFactory +import io.ktor.client.HttpClient +import io.ktor.client.plugins.defaultRequest import io.ktor.http.Url import kotlinx.browser.document import kotlinx.browser.window @@ -36,6 +39,7 @@ import org.apache.solr.composeui.components.root.integration.SimpleRootComponent import org.apache.solr.composeui.ui.root.RootContent import org.apache.solr.composeui.ui.theme.SolrTheme import org.apache.solr.composeui.utils.DefaultAppComponentContext +import org.apache.solr.composeui.utils.getDefaultClient /** * Entry point of the Compose application for all wasmJs (browser) targets. @@ -55,15 +59,22 @@ fun main() { val url = Url(window.location.href) val destination = url.parameters["dest"] + // TODO Set default request url to values from window location + val httpClient = getDefaultClient() + val component: RootComponent = SimpleRootComponent( componentContext = componentContext, storeFactory = DefaultStoreFactory(), + httpClient = httpClient, destination = destination, ) ComposeViewport(document.body!!) { SolrTheme(useDarkTheme = isSystemInDarkTheme()) { - Surface(modifier = Modifier.fillMaxSize()) { + Surface( + modifier = Modifier.fillMaxSize(), + color = MaterialTheme.colorScheme.background, + ) { RootContent(component) } } diff --git a/solr/licenses/firacode-OFL.txt b/solr/licenses/firacode-OFL.txt new file mode 100644 index 00000000000..0e38b887465 --- /dev/null +++ b/solr/licenses/firacode-OFL.txt @@ -0,0 +1,93 @@ +Copyright 2014-2020 The Fira Code Project Authors (https://github.com/tonsky/FiraCode) + +This Font Software is licensed under the SIL Open Font License, Version 1.1. +This license is copied below, and is also available with a FAQ at: +https://openfontlicense.org + + +----------------------------------------------------------- +SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 +----------------------------------------------------------- + +PREAMBLE +The goals of the Open Font License (OFL) are to stimulate worldwide +development of collaborative font projects, to support the font creation +efforts of academic and linguistic communities, and to provide a free and +open framework in which fonts may be shared and improved in partnership +with others. + +The OFL allows the licensed fonts to be used, studied, modified and +redistributed freely as long as they are not sold by themselves. The +fonts, including any derivative works, can be bundled, embedded, +redistributed and/or sold with any software provided that any reserved +names are not used by derivative works. The fonts and derivatives, +however, cannot be released under any other type of license. The +requirement for fonts to remain under this license does not apply +to any document created using the fonts or their derivatives. + +DEFINITIONS +"Font Software" refers to the set of files released by the Copyright +Holder(s) under this license and clearly marked as such. This may +include source files, build scripts and documentation. + +"Reserved Font Name" refers to any names specified as such after the +copyright statement(s). + +"Original Version" refers to the collection of Font Software components as +distributed by the Copyright Holder(s). + +"Modified Version" refers to any derivative made by adding to, deleting, +or substituting -- in part or in whole -- any of the components of the +Original Version, by changing formats or by porting the Font Software to a +new environment. + +"Author" refers to any designer, engineer, programmer, technical +writer or other person who contributed to the Font Software. + +PERMISSION & CONDITIONS +Permission is hereby granted, free of charge, to any person obtaining +a copy of the Font Software, to use, study, copy, merge, embed, modify, +redistribute, and sell modified and unmodified copies of the Font +Software, subject to the following conditions: + +1) Neither the Font Software nor any of its individual components, +in Original or Modified Versions, may be sold by itself. + +2) Original or Modified Versions of the Font Software may be bundled, +redistributed and/or sold with any software, provided that each copy +contains the above copyright notice and this license. These can be +included either as stand-alone text files, human-readable headers or +in the appropriate machine-readable metadata fields within text or +binary files as long as those fields can be easily viewed by the user. + +3) No Modified Version of the Font Software may use the Reserved Font +Name(s) unless explicit written permission is granted by the corresponding +Copyright Holder. This restriction only applies to the primary font name as +presented to the users. + +4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font +Software shall not be used to promote, endorse or advertise any +Modified Version, except to acknowledge the contribution(s) of the +Copyright Holder(s) and the Author(s) or with their explicit written +permission. + +5) The Font Software, modified or unmodified, in part or in whole, +must be distributed entirely under this license, and must not be +distributed under any other license. The requirement for fonts to +remain under this license does not apply to any document created +using the Font Software. + +TERMINATION +This license becomes null and void if any of the above conditions are +not met. + +DISCLAIMER +THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT +OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE +COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL +DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM +OTHER DEALINGS IN THE FONT SOFTWARE. From c58ab93faba9676936e10e6b6a266509e6c54241 Mon Sep 17 00:00:00 2001 From: Christos Malliaridis Date: Wed, 10 Jul 2024 16:45:59 +0300 Subject: [PATCH 07/66] Add vertical scrolling to navigation sidebar --- .../ui/navigation/NavigationSideBar.kt | 29 +++++++++++++------ 1 file changed, 20 insertions(+), 9 deletions(-) diff --git a/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/ui/navigation/NavigationSideBar.kt b/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/ui/navigation/NavigationSideBar.kt index f04ff163300..2b94ce95d1a 100644 --- a/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/ui/navigation/NavigationSideBar.kt +++ b/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/ui/navigation/NavigationSideBar.kt @@ -24,6 +24,8 @@ import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.fillMaxHeight import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.rememberScrollState +import androidx.compose.foundation.verticalScroll import androidx.compose.material.icons.Icons import androidx.compose.material.icons.automirrored.rounded.Logout import androidx.compose.material.icons.automirrored.rounded.TextSnippet @@ -41,6 +43,9 @@ import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Tab import androidx.compose.material3.Text import androidx.compose.material3.VerticalDivider +import androidx.compose.material3.windowsizeclass.ExperimentalMaterial3WindowSizeClassApi +import androidx.compose.material3.windowsizeclass.WindowHeightSizeClass +import androidx.compose.material3.windowsizeclass.calculateWindowSizeClass import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier @@ -66,18 +71,24 @@ import org.jetbrains.compose.resources.stringResource * The application's main navigation / sidebar. It is used for navigation between the different * sections. */ +@OptIn(ExperimentalMaterial3WindowSizeClassApi::class) @Composable fun NavigationSideBar( onNavigate: (MainMenu) -> Unit, selectedItem: MainMenu? = null, modifier: Modifier = Modifier, ) = Row(modifier = modifier) { + val scrollState = rememberScrollState(48 * (selectedItem?.ordinal ?: 0)) + Column(Modifier.fillMaxHeight()) { SolrLogo( modifier = Modifier.fillMaxWidth() .padding(horizontal = 16.dp, vertical = 8.dp), ) - Column(modifier = Modifier.weight(1f)) { + Column( + modifier = Modifier.weight(1f) + .verticalScroll(scrollState), + ) { MainMenu.entries.forEach { item -> MenuElement( text = stringResource(getMainMenuText(item)), @@ -88,15 +99,15 @@ fun NavigationSideBar( onClick = { onNavigate(item) }, ) } - } - // TODO Add condition for displaying logout button if user identity / auth present - MenuElement( - text = stringResource(Res.string.logout), - imageVector = Icons.AutoMirrored.Rounded.Logout, - modifier = Modifier.fillMaxWidth(), - onClick = {}, // TODO Call logout on auth component - ) + // TODO Add condition for displaying logout button if user identity / auth present + MenuElement( + text = stringResource(Res.string.logout), + imageVector = Icons.AutoMirrored.Rounded.Logout, + modifier = Modifier.fillMaxWidth(), + onClick = {}, // TODO Call logout on auth component + ) + } } VerticalDivider() } From 3d433ae67134163e7b593b75c6787844a1b4caad Mon Sep 17 00:00:00 2001 From: Christos Malliaridis Date: Thu, 11 Jul 2024 00:44:50 +0300 Subject: [PATCH 08/66] Allow special floating point values in JSON serialization --- .../kotlin/org/apache/solr/composeui/utils/HttpClientUtils.kt | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/utils/HttpClientUtils.kt b/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/utils/HttpClientUtils.kt index 30de3618d4c..8f8c291ca9f 100644 --- a/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/utils/HttpClientUtils.kt +++ b/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/utils/HttpClientUtils.kt @@ -14,11 +14,13 @@ fun getDefaultClient() = HttpClient { defaultRequest { url("http://localhost:8983/") } + install(ContentNegotiation) { json( Json { ignoreUnknownKeys = true + allowSpecialFloatingPointValues = true } ) } -} \ No newline at end of file +} From d95ffd4e7f4f297e364c9c63988d7bf7b08909ca Mon Sep 17 00:00:00 2001 From: Christos Malliaridis Date: Thu, 11 Jul 2024 00:45:23 +0300 Subject: [PATCH 09/66] Remove invalid JS dependency from WasmJS target --- solr/compose-ui/build.gradle.kts | 1 - 1 file changed, 1 deletion(-) diff --git a/solr/compose-ui/build.gradle.kts b/solr/compose-ui/build.gradle.kts index cbd3a7538d8..4dc583b8c61 100644 --- a/solr/compose-ui/build.gradle.kts +++ b/solr/compose-ui/build.gradle.kts @@ -109,7 +109,6 @@ kotlin { val wasmJsMain by getting { dependencies { implementation(libs.ktor.client.js) - implementation(libs.kotlinx.coroutines.js) } } } From 08413a734cc1ebd7abdf9c3d255c70bf96ed390b Mon Sep 17 00:00:00 2001 From: Christos Malliaridis Date: Thu, 11 Jul 2024 00:45:50 +0300 Subject: [PATCH 10/66] Undo temporary forced light theme change --- .../src/desktopMain/kotlin/org/apache/solr/composeui/Main.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/solr/compose-ui/src/desktopMain/kotlin/org/apache/solr/composeui/Main.kt b/solr/compose-ui/src/desktopMain/kotlin/org/apache/solr/composeui/Main.kt index 3f2e055dca1..3f3ce43ccf7 100644 --- a/solr/compose-ui/src/desktopMain/kotlin/org/apache/solr/composeui/Main.kt +++ b/solr/compose-ui/src/desktopMain/kotlin/org/apache/solr/composeui/Main.kt @@ -81,7 +81,7 @@ fun main() { ) { window.minimumSize = Dimension(720, 560) - SolrTheme(useDarkTheme = false) { + SolrTheme(useDarkTheme = isSystemInDarkTheme()) { Surface( modifier = Modifier.fillMaxSize(), color = MaterialTheme.colorScheme.background, From 442340297c2cd7a6549c3bdc86f22459bfecbf11 Mon Sep 17 00:00:00 2001 From: Christos Malliaridis Date: Thu, 11 Jul 2024 00:47:11 +0300 Subject: [PATCH 11/66] Update Ktor to EAP version to build WasmJS target --- build.gradle | 3 +++ gradle/libs.versions.toml | 3 +-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/build.gradle b/build.gradle index b7ca805d4e4..90aef97d229 100644 --- a/build.gradle +++ b/build.gradle @@ -42,6 +42,9 @@ allprojects { maven { url = "https://maven.pkg.jetbrains.space/kotlin/p/wasm/experimental" } + maven { + url = "https://maven.pkg.jetbrains.space/public/p/ktor/eap" + } } } diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index e2bfeac65b8..c86c6d84f23 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -11,7 +11,7 @@ kotlin = "2.0.0" kotlinx-coroutines = "1.9.0-RC" kotlinx-datetime = "0.6.0" kotlinx-serialization = "1.6.3" -ktor = "3.0.0-wasm2" +ktor = "3.0.0-beta-2-eap-972" mvikotlin = "4.1.0" nexus-publish = "2.0.0-rc-1" openapi = "7.6.0" @@ -48,7 +48,6 @@ kotlinx-datetime = { group = "org.jetbrains.kotlinx", name = "kotlinx-datetime", kotlinx-serialization-core = { group = "org.jetbrains.kotlinx", name = "kotlinx-serialization-core", version.ref = "kotlinx-serialization" } kotlinx-serialization-json = { group = "org.jetbrains.kotlinx", name = "kotlinx-serialization-json", version.ref = "kotlinx-serialization" } kotlinx-coroutines-core = { group = "org.jetbrains.kotlinx", name = "kotlinx-coroutines-core", version.ref = "kotlinx-coroutines" } -kotlinx-coroutines-js = { group = "org.jetbrains.kotlinx", name = "kotlinx-coroutines-js", version.ref = "kotlinx-coroutines" } kotlinx-coroutines-swing = { group = "org.jetbrains.kotlinx", name = "kotlinx-coroutines-swing", version.ref = "kotlinx-coroutines" } ktor-client-core = { group = "io.ktor", name = "ktor-client-core", version.ref = "ktor" } ktor-client-cio = { group = "io.ktor", name = "ktor-client-cio", version.ref = "ktor" } From 0a0cdea432208a3399980a55ee18ea395de294ec Mon Sep 17 00:00:00 2001 From: Christos Malliaridis Date: Thu, 11 Jul 2024 01:05:22 +0300 Subject: [PATCH 12/66] Add README.md for compose-ui module --- solr/compose-ui/README.md | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) create mode 100644 solr/compose-ui/README.md diff --git a/solr/compose-ui/README.md b/solr/compose-ui/README.md new file mode 100644 index 00000000000..ee977fcf164 --- /dev/null +++ b/solr/compose-ui/README.md @@ -0,0 +1,29 @@ +# Compose Admin UI + +> **⚠️ EXPERIMENTAL ⚠️** +> +> This is an experimental module developed as a proof-of-concept. + +This module contains the code for the new Admin UI written in Kotlin / Compose +Multiplatform. + +## Supported Targets + +The module is available for desktop / JVM targets and web (WebAssembly). + +## Build and Run + +To build and run the desktop client simply run `./gradlew :solr:compose-ui:run`. + +The WebAssembly app is built and deployed together with the current webapp. To +run and access it, you can build the project as usual (see +[Quickstart](../../README.md#quickstart)) and then access +[`http://localhost:8983/solr/compose`](http://localhost:8983/solr/compose). Various references are included in the +webapp for already migrated pages. + +> Note that the standalone WebAssembly app executed via +> `./gradlew :solr:compose-ui:wasmJsBrowserRun` runs on port `8080` and will run +> into CORS exceptions. Therefore, the usage of it for development is +> discouraged. +> +> Consider one of the above options instead. From 9bc5c89ac7488ec6c632dd0d939d601e834c1027 Mon Sep 17 00:00:00 2001 From: Christos Malliaridis Date: Thu, 11 Jul 2024 01:34:38 +0300 Subject: [PATCH 13/66] Add missing Raleway font license --- solr/licenses/raleway-OFL.txt | 93 +++++++++++++++++++++++++++++++++++ 1 file changed, 93 insertions(+) create mode 100644 solr/licenses/raleway-OFL.txt diff --git a/solr/licenses/raleway-OFL.txt b/solr/licenses/raleway-OFL.txt new file mode 100644 index 00000000000..7e00c5f9e2e --- /dev/null +++ b/solr/licenses/raleway-OFL.txt @@ -0,0 +1,93 @@ +Copyright 2010 The Raleway Project Authors (impallari@gmail.com), with Reserved Font Name "Raleway". + +This Font Software is licensed under the SIL Open Font License, Version 1.1. +This license is copied below, and is also available with a FAQ at: +https://openfontlicense.org + + +----------------------------------------------------------- +SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 +----------------------------------------------------------- + +PREAMBLE +The goals of the Open Font License (OFL) are to stimulate worldwide +development of collaborative font projects, to support the font creation +efforts of academic and linguistic communities, and to provide a free and +open framework in which fonts may be shared and improved in partnership +with others. + +The OFL allows the licensed fonts to be used, studied, modified and +redistributed freely as long as they are not sold by themselves. The +fonts, including any derivative works, can be bundled, embedded, +redistributed and/or sold with any software provided that any reserved +names are not used by derivative works. The fonts and derivatives, +however, cannot be released under any other type of license. The +requirement for fonts to remain under this license does not apply +to any document created using the fonts or their derivatives. + +DEFINITIONS +"Font Software" refers to the set of files released by the Copyright +Holder(s) under this license and clearly marked as such. This may +include source files, build scripts and documentation. + +"Reserved Font Name" refers to any names specified as such after the +copyright statement(s). + +"Original Version" refers to the collection of Font Software components as +distributed by the Copyright Holder(s). + +"Modified Version" refers to any derivative made by adding to, deleting, +or substituting -- in part or in whole -- any of the components of the +Original Version, by changing formats or by porting the Font Software to a +new environment. + +"Author" refers to any designer, engineer, programmer, technical +writer or other person who contributed to the Font Software. + +PERMISSION & CONDITIONS +Permission is hereby granted, free of charge, to any person obtaining +a copy of the Font Software, to use, study, copy, merge, embed, modify, +redistribute, and sell modified and unmodified copies of the Font +Software, subject to the following conditions: + +1) Neither the Font Software nor any of its individual components, +in Original or Modified Versions, may be sold by itself. + +2) Original or Modified Versions of the Font Software may be bundled, +redistributed and/or sold with any software, provided that each copy +contains the above copyright notice and this license. These can be +included either as stand-alone text files, human-readable headers or +in the appropriate machine-readable metadata fields within text or +binary files as long as those fields can be easily viewed by the user. + +3) No Modified Version of the Font Software may use the Reserved Font +Name(s) unless explicit written permission is granted by the corresponding +Copyright Holder. This restriction only applies to the primary font name as +presented to the users. + +4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font +Software shall not be used to promote, endorse or advertise any +Modified Version, except to acknowledge the contribution(s) of the +Copyright Holder(s) and the Author(s) or with their explicit written +permission. + +5) The Font Software, modified or unmodified, in part or in whole, +must be distributed entirely under this license, and must not be +distributed under any other license. The requirement for fonts to +remain under this license does not apply to any document created +using the Font Software. + +TERMINATION +This license becomes null and void if any of the above conditions are +not met. + +DISCLAIMER +THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT +OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE +COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL +DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM +OTHER DEALINGS IN THE FONT SOFTWARE. From 682da1fde72b2af036f15de793c59a4aff559531 Mon Sep 17 00:00:00 2001 From: Christos Malliaridis Date: Thu, 11 Jul 2024 01:50:49 +0300 Subject: [PATCH 14/66] Use correct name for environment store instance --- .../components/environment/store/EnvironmentStoreProvider.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/components/environment/store/EnvironmentStoreProvider.kt b/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/components/environment/store/EnvironmentStoreProvider.kt index efc875ac025..726fcd338c6 100644 --- a/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/components/environment/store/EnvironmentStoreProvider.kt +++ b/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/components/environment/store/EnvironmentStoreProvider.kt @@ -22,7 +22,7 @@ internal class EnvironmentStoreProvider( fun provide(): EnvironmentStore = object : EnvironmentStore, Store by storeFactory.create( - name = "HomeMainStore", + name = "EnvironmentStore", initialState = State(), bootstrapper = SimpleBootstrapper(Action.FetchInitialSystemData), executorFactory = ::ExecutorImpl, From c487ebe7d982a3c5c3cc3e5077dabe7253be7069 Mon Sep 17 00:00:00 2001 From: Christos Malliaridis Date: Thu, 11 Jul 2024 01:52:10 +0300 Subject: [PATCH 15/66] Remove unused EnvironmentComponent state values --- .../environment/EnvironmentComponent.kt | 18 +++++++----------- .../environment/integration/Mappers.kt | 9 +-------- .../ui/environment/EnvironmentContent.kt | 4 ++-- 3 files changed, 10 insertions(+), 21 deletions(-) diff --git a/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/components/environment/EnvironmentComponent.kt b/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/components/environment/EnvironmentComponent.kt index 2dd14f830d7..addd5dd4d11 100644 --- a/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/components/environment/EnvironmentComponent.kt +++ b/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/components/environment/EnvironmentComponent.kt @@ -20,25 +20,21 @@ package org.apache.solr.composeui.components.environment import kotlinx.coroutines.flow.StateFlow import org.apache.solr.composeui.components.environment.data.JavaProperty import org.apache.solr.composeui.components.environment.data.JvmData -import org.apache.solr.composeui.components.environment.data.SecurityConfig -import org.apache.solr.composeui.components.environment.data.SystemInformation -import org.apache.solr.composeui.components.environment.data.SystemMode import org.apache.solr.composeui.components.environment.data.Versions +/** + * Component interface that represents the environment section. + */ interface EnvironmentComponent { val model: StateFlow + /** + * State class that holds values of the [EnvironmentComponent]'s sate. + */ data class Model( - val mode: SystemMode = SystemMode.Unknown, - val zkHost: String = "", - val solrHome: String = "", - val coreRoot: String = "", - val lucene: Versions = Versions(), + val versions: Versions = Versions(), val jvm: JvmData = JvmData(), - val security: SecurityConfig = SecurityConfig(), - val system: SystemInformation = SystemInformation(), - val node: String = "", val javaProperties: List = emptyList(), ) } \ No newline at end of file diff --git a/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/components/environment/integration/Mappers.kt b/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/components/environment/integration/Mappers.kt index e14e47d37de..e248cae0929 100644 --- a/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/components/environment/integration/Mappers.kt +++ b/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/components/environment/integration/Mappers.kt @@ -5,15 +5,8 @@ import org.apache.solr.composeui.components.environment.store.EnvironmentStore internal val environmentStateToModel: (EnvironmentStore.State) -> EnvironmentComponent.Model = { EnvironmentComponent.Model( - mode = it.mode, - zkHost = it.zkHost, - solrHome = it.solrHome, - coreRoot = it.coreRoot, - lucene = it.lucene, + versions = it.lucene, jvm = it.jvm, - security = it.security, - system = it.system, - node = it.node, javaProperties = it.javaProperties, ) } diff --git a/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/ui/environment/EnvironmentContent.kt b/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/ui/environment/EnvironmentContent.kt index 73b503b5640..7ab09e6b671 100644 --- a/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/ui/environment/EnvironmentContent.kt +++ b/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/ui/environment/EnvironmentContent.kt @@ -64,7 +64,7 @@ private fun EnvironmentContentExpanded( ) { VersionsCard( modifier = Modifier.fillMaxWidth(), - versions = model.lucene, + versions = model.versions, jvm = model.jvm, ) JavaPropertiesCard( @@ -88,7 +88,7 @@ private fun EnvironmentContentMedium( ) { VersionsCard( modifier = Modifier.fillMaxWidth(), - versions = model.lucene, + versions = model.versions, jvm = model.jvm, ) JavaPropertiesCard( From 2d608afbc96fd95adf8b8d453a69207515bff0e0 Mon Sep 17 00:00:00 2001 From: Christos Malliaridis Date: Thu, 11 Jul 2024 02:14:51 +0300 Subject: [PATCH 16/66] Add documentation to environment classes --- .../data/JavaPropertiesResponse.kt | 5 ++ .../environment/data/JavaProperty.kt | 7 ++- .../DefaultEnvironmentComponent.kt | 3 + .../integration/HttpEnvironmentStoreClient.kt | 11 ++++ .../environment/store/EnvironmentStore.kt | 14 +++++ .../store/EnvironmentStoreProvider.kt | 57 ++++++++++++++++++- 6 files changed, 94 insertions(+), 3 deletions(-) diff --git a/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/components/environment/data/JavaPropertiesResponse.kt b/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/components/environment/data/JavaPropertiesResponse.kt index abf8e1da16f..6f634de88ea 100644 --- a/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/components/environment/data/JavaPropertiesResponse.kt +++ b/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/components/environment/data/JavaPropertiesResponse.kt @@ -3,6 +3,11 @@ package org.apache.solr.composeui.components.environment.data import kotlinx.serialization.SerialName import kotlinx.serialization.Serializable +/** + * Response class of the `java-properties` API endpoint. + * + * @property properties List if key-value pairs / Map that represent java properties. + */ @Serializable data class JavaPropertiesResponse( @SerialName("system.properties") diff --git a/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/components/environment/data/JavaProperty.kt b/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/components/environment/data/JavaProperty.kt index 8e14c411d68..827e3907419 100644 --- a/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/components/environment/data/JavaProperty.kt +++ b/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/components/environment/data/JavaProperty.kt @@ -1,3 +1,8 @@ package org.apache.solr.composeui.components.environment.data -typealias JavaProperty = Pair \ No newline at end of file +/** + * Typealias of JavaProperty, which are simple key-value pairs. + * + * This alias is used for better readability in code. + */ +typealias JavaProperty = Pair diff --git a/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/components/environment/integration/DefaultEnvironmentComponent.kt b/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/components/environment/integration/DefaultEnvironmentComponent.kt index 551387be18b..151eca7d385 100644 --- a/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/components/environment/integration/DefaultEnvironmentComponent.kt +++ b/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/components/environment/integration/DefaultEnvironmentComponent.kt @@ -28,6 +28,9 @@ import org.apache.solr.composeui.utils.AppComponentContext import org.apache.solr.composeui.utils.coroutineScope import org.apache.solr.composeui.utils.map +/** + * Default implementation of the [EnvironmentComponent]. + */ class DefaultEnvironmentComponent( componentContext: AppComponentContext, storeFactory: StoreFactory, diff --git a/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/components/environment/integration/HttpEnvironmentStoreClient.kt b/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/components/environment/integration/HttpEnvironmentStoreClient.kt index 8a24e911473..03fe3508dcc 100644 --- a/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/components/environment/integration/HttpEnvironmentStoreClient.kt +++ b/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/components/environment/integration/HttpEnvironmentStoreClient.kt @@ -9,6 +9,15 @@ import org.apache.solr.composeui.components.environment.data.JavaProperty import org.apache.solr.composeui.components.environment.data.SystemData import org.apache.solr.composeui.components.environment.store.EnvironmentStoreProvider +/** + * Client implementation of the [EnvironmentStoreProvider.Client] that makes use + * of a preconfigured HTTP client for accessing the Solr API. + * + * @property httpClient HTTP client to use for accessing the API. The client has to be + * configured with a default request that includes the host, port and schema. The client + * should also include the necessary authentication data if authentication / authorization + * is enabled. + */ class HttpEnvironmentStoreClient( private val httpClient: HttpClient, ) : EnvironmentStoreProvider.Client { @@ -28,6 +37,8 @@ class HttpEnvironmentStoreClient( return when { response.status.isSuccess() -> { + + // Map the response data to a list of JavaProperty for better readability val javaProperties = response.body() .properties .map { (key, value) -> key to value } diff --git a/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/components/environment/store/EnvironmentStore.kt b/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/components/environment/store/EnvironmentStore.kt index 34ada1037df..fc272b8e7a3 100644 --- a/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/components/environment/store/EnvironmentStore.kt +++ b/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/components/environment/store/EnvironmentStore.kt @@ -10,13 +10,27 @@ import org.apache.solr.composeui.components.environment.data.Versions import org.apache.solr.composeui.components.environment.store.EnvironmentStore.Intent import org.apache.solr.composeui.components.environment.store.EnvironmentStore.State +/** + * State store interface of the environment. + * + * Implementations of this state store manage detailed information of the environment. + */ internal interface EnvironmentStore : Store { + /** + * Intent for interacting with the environment store. + */ sealed interface Intent { + /** + * Intent for requesting system data. + */ data object FetchSystemData: Intent } + /** + * State class that holds the data of the [EnvironmentStore]. + */ data class State( val mode: SystemMode = SystemMode.Unknown, val zkHost: String = "", diff --git a/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/components/environment/store/EnvironmentStoreProvider.kt b/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/components/environment/store/EnvironmentStoreProvider.kt index 726fcd338c6..8b21128335a 100644 --- a/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/components/environment/store/EnvironmentStoreProvider.kt +++ b/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/components/environment/store/EnvironmentStoreProvider.kt @@ -13,6 +13,13 @@ import org.apache.solr.composeui.components.environment.data.SystemData import org.apache.solr.composeui.components.environment.store.EnvironmentStore.Intent import org.apache.solr.composeui.components.environment.store.EnvironmentStore.State +/** + * Store provider that [provide]s instances of [EnvironmentStore]. + * + * @property storeFactory Store factory to use for creating the store. + * @property client Client implementation to use for resolving [Intent]s and [Action]s. + * @property ioContext Coroutine context used for IO activity. + */ internal class EnvironmentStoreProvider( private val storeFactory: StoreFactory, private val client: Client, @@ -31,28 +38,52 @@ internal class EnvironmentStoreProvider( private sealed interface Action { + /** + * Action used for initiating the initial fetch of environment data. + */ data object FetchInitialSystemData: Action } private sealed interface Message { + /** + * Message that is dispatched when system data have been retrieved / updated. + * + * @property data New system data that have been received. + */ data class SystemDataUpdated(val data: SystemData) : Message + /** + * Message that is dispatched when java properties have been retrieved / updated. + * + * @property properties New list of java properties. + */ data class JavaPropertiesUpdated(val properties: List) : Message } private inner class ExecutorImpl : CoroutineExecutor() { override fun executeAction(action: Action) = when(action) { - Action.FetchInitialSystemData -> fetchSystemData() + Action.FetchInitialSystemData -> { + fetchSystemData() + fetchJavaProperties() + } } override fun executeIntent(intent: Intent) { when (intent) { - Intent.FetchSystemData -> fetchSystemData() + Intent.FetchSystemData -> { + fetchSystemData() + fetchJavaProperties() + } } } + /** + * Fetches the system data that are part of the environment state. + * + * If successful, a [Message.SystemDataUpdated] with the new properties is dispatched. + */ private fun fetchSystemData() { scope.launch { // TODO Add coroutine exception handler withContext(ioContext) { @@ -69,8 +100,27 @@ internal class EnvironmentStoreProvider( // TODO Add error handling } } + + /** + * Fetches the java properties that are part of the environment state. + * + * If successful, a [Message.JavaPropertiesUpdated] with the new properties is dispatched. + */ + private fun fetchJavaProperties() { + scope.launch { // TODO Add coroutine exception handler + withContext(ioContext) { + client.getJavaProperties() + }.onSuccess { + dispatch(Message.JavaPropertiesUpdated(it)) + } + // TODO Add error handling + } + } } + /** + * Reducer implementation that consumes [Message]s and updates the store's [State]. + */ private object ReducerImpl : Reducer { override fun State.reduce(msg: Message): State = when (msg) { is Message.SystemDataUpdated -> copy( @@ -90,6 +140,9 @@ internal class EnvironmentStoreProvider( } } + /** + * Client interface for fetching environment information. + */ interface Client { /** From e41d8db7c3f3ae3c59de2635b548e80dea33d886 Mon Sep 17 00:00:00 2001 From: Christos Malliaridis Date: Mon, 15 Jul 2024 16:31:44 +0300 Subject: [PATCH 17/66] Add reference button for new UI in java-properties.html --- solr/webapp/web/partials/java-properties.html | 3 +++ 1 file changed, 3 insertions(+) diff --git a/solr/webapp/web/partials/java-properties.html b/solr/webapp/web/partials/java-properties.html index 9c67c7b7593..7599abec41d 100644 --- a/solr/webapp/web/partials/java-properties.html +++ b/solr/webapp/web/partials/java-properties.html @@ -14,6 +14,9 @@ See the License for the specific language governing permissions and limitations under the License. --> +

diff --git a/solr/webapp/web/partials/java-properties.html b/solr/webapp/web/partials/java-properties.html index 7599abec41d..9c67c7b7593 100644 --- a/solr/webapp/web/partials/java-properties.html +++ b/solr/webapp/web/partials/java-properties.html @@ -14,9 +14,6 @@ See the License for the specific language governing permissions and limitations under the License. --> -
  • From cd949089cf0a63f06446d83c6287908e5f6e0679 Mon Sep 17 00:00:00 2001 From: Christos Malliaridis Date: Wed, 29 Jan 2025 17:54:13 +0100 Subject: [PATCH 64/66] Add compose-ui module to labeler --- .github/labeler.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/labeler.yml b/.github/labeler.yml index c12fde05c72..2e08d3d7649 100644 --- a/.github/labeler.yml +++ b/.github/labeler.yml @@ -96,6 +96,7 @@ admin-ui: - changed-files: - any-glob-to-any-file: - solr/webapp/** + - solr/compose-ui/** # Add 'prometheus-exporter' label prometheus-exporter: From b8be6c2a4fe0984c91d83206b0f66dfc8127d191 Mon Sep 17 00:00:00 2001 From: Christos Malliaridis Date: Thu, 30 Jan 2025 00:00:30 +0100 Subject: [PATCH 65/66] Add change entry for new UI --- solr/CHANGES.txt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/solr/CHANGES.txt b/solr/CHANGES.txt index a66ae9098aa..b0a43cf4942 100644 --- a/solr/CHANGES.txt +++ b/solr/CHANGES.txt @@ -14,6 +14,9 @@ New Features * SOLR-14673: Solr CLI now has bin/solr stream tool that executates streaming expressions via command line, either locally or on solr cluster. (Eric Pugh) +* SOLR-14414: Introduce a new, experimental Admin UI that can be used aside the current Admin UI. The new module is + loaded together with the existing Admin UI and available under the URL path /solr/compose. (Christos Malliaridis) + Improvements --------------------- From 23e53d29f5beea9f7b514b1e37791c3944d7d0ce Mon Sep 17 00:00:00 2001 From: Christos Malliaridis Date: Tue, 4 Feb 2025 20:38:00 +0100 Subject: [PATCH 66/66] Remove "compose" from packages, paths and names --- .github/labeler.yml | 2 +- dev-docs/ui/introduction.adoc | 2 +- dev-docs/ui/module-structure.adoc | 6 ++-- dev-docs/ui/testing-and-deployment.adoc | 24 +++++++-------- settings.gradle | 2 +- solr/server/etc/jetty-new-ui-dev.xml | 4 +-- solr/server/etc/jetty-new-ui-prod.xml | 4 +-- solr/{compose-ui => ui}/README.md | 4 +-- solr/{compose-ui => ui}/assets/logo.ico | Bin solr/{compose-ui => ui}/assets/logo.png | Bin solr/{compose-ui => ui}/build.gradle.kts | 2 +- solr/{compose-ui => ui}/gradle.lockfile | 0 .../karma.config.d/wasm/adjust-timeouts.js | 0 .../drawable/solr-logo-dark.svg | 0 .../drawable/solr-logo-light.svg | 0 .../composeResources/values/strings.xml | 0 .../environment/EnvironmentComponent.kt | 8 ++--- .../data/JavaPropertiesResponse.kt | 2 +- .../environment/data/JavaProperty.kt | 2 +- .../environment/data/JavaRuntimeInfo.kt | 2 +- .../ui}/components/environment/data/Jmx.kt | 2 +- .../components/environment/data/JvmData.kt | 2 +- .../components/environment/data/JvmMemory.kt | 2 +- .../environment/data/JvmMemoryRaw.kt | 2 +- .../environment/data/SecurityConfig.kt | 2 +- .../components/environment/data/SystemData.kt | 2 +- .../environment/data/SystemInformation.kt | 2 +- .../components/environment/data/SystemMode.kt | 2 +- .../components/environment/data/Versions.kt | 2 +- .../DefaultEnvironmentComponent.kt | 12 ++++---- .../integration/HttpEnvironmentStoreClient.kt | 10 +++---- .../environment/integration/Mappers.kt | 6 ++-- .../environment/store/EnvironmentStore.kt | 18 +++++------ .../store/EnvironmentStoreProvider.kt | 10 +++---- .../components/logging/LoggingComponent.kt | 2 +- .../integration/DefaultLoggingComponent.kt | 6 ++-- .../solr/ui}/components/main/MainComponent.kt | 10 +++---- .../main/integration/DefaultMainComponent.kt | 18 +++++------ .../components/main/integration/Mappers.kt | 6 ++-- .../navigation/NavigationComponent.kt | 2 +- .../solr/ui}/components/root/RootComponent.kt | 4 +-- .../root/integration/SimpleRootComponent.kt | 10 +++---- .../solr/ui}/utils/AppComponentContext.kt | 2 +- .../solr/ui}/utils/CoroutineContextOwner.kt | 2 +- .../solr/ui}/utils/CoroutineScopeExt.kt | 2 +- .../ui}/utils/DefaultAppComponentContext.kt | 2 +- .../apache/solr/ui}/utils/HttpClientUtils.kt | 2 +- .../solr/ui/views}/components/SolrCard.kt | 2 +- .../environment/CommandLineArgumentsCard.kt | 6 ++-- .../views}/environment/EnvironmentContent.kt | 4 +-- .../views}/environment/JavaPropertiesCard.kt | 8 ++--- .../ui/views}/environment/VersionsCard.kt | 8 ++--- .../apache/solr/ui/views}/icons/SolrLogo.kt | 10 +++---- .../solr/ui/views}/logging/LoggingContent.kt | 4 +-- .../apache/solr/ui/views}/main/MainContent.kt | 12 ++++---- .../solr/ui/views}/navigation/Footer.kt | 18 +++++------ .../solr/ui/views}/navigation/MainMenu.kt | 2 +- .../ui/views}/navigation/NavigationSideBar.kt | 28 +++++++++--------- .../apache/solr/ui/views}/root/RootContent.kt | 8 ++--- .../solr/ui/views}/theme/ColorFamily.kt | 2 +- .../org/apache/solr/ui/views}/theme/Colors.kt | 2 +- .../org/apache/solr/ui/views}/theme/Shapes.kt | 2 +- .../org/apache/solr/ui/views}/theme/Theme.kt | 2 +- .../apache/solr/ui/views}/theme/Typography.kt | 2 +- .../store/EnvironmentStoreProviderTest.kt | 4 +-- .../store/MockedEnvironmentStoreClient.kt | 6 ++-- .../solr/ui}/ui/components/SolrCardTest.kt | 2 +- .../ui/environment/EnvironmentContentTest.kt | 6 ++-- .../kotlin/org/apache/solr/ui}/Main.kt | 14 ++++----- .../kotlin/org/apache/solr/ui}/Utils.kt | 2 +- .../solr/ui}/preview/PreviewContainer.kt | 4 +-- .../navigation/PreviewNavigationSideBar.kt | 6 ++-- .../kotlin/org/apache/solr/ui}/Main.kt | 14 ++++----- .../src/wasmJsMain/resources/index.html | 0 .../src/wasmJsMain/resources/styles.css | 0 .../webpack.config.d/adjust-limits.js | 0 solr/webapp/build.gradle | 20 ++++++------- solr/webapp/web/index.html | 2 +- solr/webapp/web/js/angular/app.js | 4 +-- 79 files changed, 205 insertions(+), 205 deletions(-) rename solr/{compose-ui => ui}/README.md (95%) rename solr/{compose-ui => ui}/assets/logo.ico (100%) rename solr/{compose-ui => ui}/assets/logo.png (100%) rename solr/{compose-ui => ui}/build.gradle.kts (99%) rename solr/{compose-ui => ui}/gradle.lockfile (100%) rename solr/{compose-ui => ui}/karma.config.d/wasm/adjust-timeouts.js (100%) rename solr/{compose-ui => ui}/src/commonMain/composeResources/drawable/solr-logo-dark.svg (100%) rename solr/{compose-ui => ui}/src/commonMain/composeResources/drawable/solr-logo-light.svg (100%) rename solr/{compose-ui => ui}/src/commonMain/composeResources/values/strings.xml (100%) rename solr/{compose-ui/src/commonMain/kotlin/org/apache/solr/composeui => ui/src/commonMain/kotlin/org/apache/solr/ui}/components/environment/EnvironmentComponent.kt (82%) rename solr/{compose-ui/src/commonMain/kotlin/org/apache/solr/composeui => ui/src/commonMain/kotlin/org/apache/solr/ui}/components/environment/data/JavaPropertiesResponse.kt (95%) rename solr/{compose-ui/src/commonMain/kotlin/org/apache/solr/composeui => ui/src/commonMain/kotlin/org/apache/solr/ui}/components/environment/data/JavaProperty.kt (94%) rename solr/{compose-ui/src/commonMain/kotlin/org/apache/solr/composeui => ui/src/commonMain/kotlin/org/apache/solr/ui}/components/environment/data/JavaRuntimeInfo.kt (94%) rename solr/{compose-ui/src/commonMain/kotlin/org/apache/solr/composeui => ui/src/commonMain/kotlin/org/apache/solr/ui}/components/environment/data/Jmx.kt (94%) rename solr/{compose-ui/src/commonMain/kotlin/org/apache/solr/composeui => ui/src/commonMain/kotlin/org/apache/solr/ui}/components/environment/data/JvmData.kt (95%) rename solr/{compose-ui/src/commonMain/kotlin/org/apache/solr/composeui => ui/src/commonMain/kotlin/org/apache/solr/ui}/components/environment/data/JvmMemory.kt (94%) rename solr/{compose-ui/src/commonMain/kotlin/org/apache/solr/composeui => ui/src/commonMain/kotlin/org/apache/solr/ui}/components/environment/data/JvmMemoryRaw.kt (94%) rename solr/{compose-ui/src/commonMain/kotlin/org/apache/solr/composeui => ui/src/commonMain/kotlin/org/apache/solr/ui}/components/environment/data/SecurityConfig.kt (93%) rename solr/{compose-ui/src/commonMain/kotlin/org/apache/solr/composeui => ui/src/commonMain/kotlin/org/apache/solr/ui}/components/environment/data/SystemData.kt (95%) rename solr/{compose-ui/src/commonMain/kotlin/org/apache/solr/composeui => ui/src/commonMain/kotlin/org/apache/solr/ui}/components/environment/data/SystemInformation.kt (96%) rename solr/{compose-ui/src/commonMain/kotlin/org/apache/solr/composeui => ui/src/commonMain/kotlin/org/apache/solr/ui}/components/environment/data/SystemMode.kt (94%) rename solr/{compose-ui/src/commonMain/kotlin/org/apache/solr/composeui => ui/src/commonMain/kotlin/org/apache/solr/ui}/components/environment/data/Versions.kt (95%) rename solr/{compose-ui/src/commonMain/kotlin/org/apache/solr/composeui => ui/src/commonMain/kotlin/org/apache/solr/ui}/components/environment/integration/DefaultEnvironmentComponent.kt (82%) rename solr/{compose-ui/src/commonMain/kotlin/org/apache/solr/composeui => ui/src/commonMain/kotlin/org/apache/solr/ui}/components/environment/integration/HttpEnvironmentStoreClient.kt (86%) rename solr/{compose-ui/src/commonMain/kotlin/org/apache/solr/composeui => ui/src/commonMain/kotlin/org/apache/solr/ui}/components/environment/integration/Mappers.kt (82%) rename solr/{compose-ui/src/commonMain/kotlin/org/apache/solr/composeui => ui/src/commonMain/kotlin/org/apache/solr/ui}/components/environment/store/EnvironmentStore.kt (73%) rename solr/{compose-ui/src/commonMain/kotlin/org/apache/solr/composeui => ui/src/commonMain/kotlin/org/apache/solr/ui}/components/environment/store/EnvironmentStoreProvider.kt (93%) rename solr/{compose-ui/src/commonMain/kotlin/org/apache/solr/composeui => ui/src/commonMain/kotlin/org/apache/solr/ui}/components/logging/LoggingComponent.kt (94%) rename solr/{compose-ui/src/commonMain/kotlin/org/apache/solr/composeui => ui/src/commonMain/kotlin/org/apache/solr/ui}/components/logging/integration/DefaultLoggingComponent.kt (84%) rename solr/{compose-ui/src/commonMain/kotlin/org/apache/solr/composeui => ui/src/commonMain/kotlin/org/apache/solr/ui}/components/main/MainComponent.kt (90%) rename solr/{compose-ui/src/commonMain/kotlin/org/apache/solr/composeui => ui/src/commonMain/kotlin/org/apache/solr/ui}/components/main/integration/DefaultMainComponent.kt (92%) rename solr/{compose-ui/src/commonMain/kotlin/org/apache/solr/composeui => ui/src/commonMain/kotlin/org/apache/solr/ui}/components/main/integration/Mappers.kt (85%) rename solr/{compose-ui/src/commonMain/kotlin/org/apache/solr/composeui => ui/src/commonMain/kotlin/org/apache/solr/ui}/components/navigation/NavigationComponent.kt (95%) rename solr/{compose-ui/src/commonMain/kotlin/org/apache/solr/composeui => ui/src/commonMain/kotlin/org/apache/solr/ui}/components/root/RootComponent.kt (92%) rename solr/{compose-ui/src/commonMain/kotlin/org/apache/solr/composeui => ui/src/commonMain/kotlin/org/apache/solr/ui}/components/root/integration/SimpleRootComponent.kt (90%) rename solr/{compose-ui/src/commonMain/kotlin/org/apache/solr/composeui => ui/src/commonMain/kotlin/org/apache/solr/ui}/utils/AppComponentContext.kt (96%) rename solr/{compose-ui/src/commonMain/kotlin/org/apache/solr/composeui => ui/src/commonMain/kotlin/org/apache/solr/ui}/utils/CoroutineContextOwner.kt (96%) rename solr/{compose-ui/src/commonMain/kotlin/org/apache/solr/composeui => ui/src/commonMain/kotlin/org/apache/solr/ui}/utils/CoroutineScopeExt.kt (98%) rename solr/{compose-ui/src/commonMain/kotlin/org/apache/solr/composeui => ui/src/commonMain/kotlin/org/apache/solr/ui}/utils/DefaultAppComponentContext.kt (98%) rename solr/{compose-ui/src/commonMain/kotlin/org/apache/solr/composeui => ui/src/commonMain/kotlin/org/apache/solr/ui}/utils/HttpClientUtils.kt (97%) rename solr/{compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/ui => ui/src/commonMain/kotlin/org/apache/solr/ui/views}/components/SolrCard.kt (97%) rename solr/{compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/ui => ui/src/commonMain/kotlin/org/apache/solr/ui/views}/environment/CommandLineArgumentsCard.kt (94%) rename solr/{compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/ui => ui/src/commonMain/kotlin/org/apache/solr/ui/views}/environment/EnvironmentContent.kt (95%) rename solr/{compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/ui => ui/src/commonMain/kotlin/org/apache/solr/ui/views}/environment/JavaPropertiesCard.kt (93%) rename solr/{compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/ui => ui/src/commonMain/kotlin/org/apache/solr/ui/views}/environment/VersionsCard.kt (92%) rename solr/{compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/ui => ui/src/commonMain/kotlin/org/apache/solr/ui/views}/icons/SolrLogo.kt (84%) rename solr/{compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/ui => ui/src/commonMain/kotlin/org/apache/solr/ui/views}/logging/LoggingContent.kt (90%) rename solr/{compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/ui => ui/src/commonMain/kotlin/org/apache/solr/ui/views}/main/MainContent.kt (88%) rename solr/{compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/ui => ui/src/commonMain/kotlin/org/apache/solr/ui/views}/navigation/Footer.kt (89%) rename solr/{compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/ui => ui/src/commonMain/kotlin/org/apache/solr/ui/views}/navigation/MainMenu.kt (96%) rename solr/{compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/ui => ui/src/commonMain/kotlin/org/apache/solr/ui/views}/navigation/NavigationSideBar.kt (88%) rename solr/{compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/ui => ui/src/commonMain/kotlin/org/apache/solr/ui/views}/root/RootContent.kt (89%) rename solr/{compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/ui => ui/src/commonMain/kotlin/org/apache/solr/ui/views}/theme/ColorFamily.kt (96%) rename solr/{compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/ui => ui/src/commonMain/kotlin/org/apache/solr/ui/views}/theme/Colors.kt (99%) rename solr/{compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/ui => ui/src/commonMain/kotlin/org/apache/solr/ui/views}/theme/Shapes.kt (97%) rename solr/{compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/ui => ui/src/commonMain/kotlin/org/apache/solr/ui/views}/theme/Theme.kt (98%) rename solr/{compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/ui => ui/src/commonMain/kotlin/org/apache/solr/ui/views}/theme/Typography.kt (99%) rename solr/{compose-ui/src/commonTest/kotlin/org/apache/solr/composeui => ui/src/commonTest/kotlin/org/apache/solr/ui}/components/environment/store/EnvironmentStoreProviderTest.kt (96%) rename solr/{compose-ui/src/commonTest/kotlin/org/apache/solr/composeui => ui/src/commonTest/kotlin/org/apache/solr/ui}/components/environment/store/MockedEnvironmentStoreClient.kt (85%) rename solr/{compose-ui/src/commonTest/kotlin/org/apache/solr/composeui => ui/src/commonTest/kotlin/org/apache/solr/ui}/ui/components/SolrCardTest.kt (97%) rename solr/{compose-ui/src/commonTest/kotlin/org/apache/solr/composeui => ui/src/commonTest/kotlin/org/apache/solr/ui}/ui/environment/EnvironmentContentTest.kt (91%) rename solr/{compose-ui/src/desktopMain/kotlin/org/apache/solr/composeui => ui/src/desktopMain/kotlin/org/apache/solr/ui}/Main.kt (88%) rename solr/{compose-ui/src/desktopMain/kotlin/org/apache/solr/composeui => ui/src/desktopMain/kotlin/org/apache/solr/ui}/Utils.kt (97%) rename solr/{compose-ui/src/desktopMain/kotlin/org/apache/solr/composeui => ui/src/desktopMain/kotlin/org/apache/solr/ui}/preview/PreviewContainer.kt (93%) rename solr/{compose-ui/src/desktopMain/kotlin/org/apache/solr/composeui => ui/src/desktopMain/kotlin/org/apache/solr/ui}/preview/navigation/PreviewNavigationSideBar.kt (85%) rename solr/{compose-ui/src/wasmJsMain/kotlin/org/apache/solr/composeui => ui/src/wasmJsMain/kotlin/org/apache/solr/ui}/Main.kt (86%) rename solr/{compose-ui => ui}/src/wasmJsMain/resources/index.html (100%) rename solr/{compose-ui => ui}/src/wasmJsMain/resources/styles.css (100%) rename solr/{compose-ui => ui}/webpack.config.d/adjust-limits.js (100%) diff --git a/.github/labeler.yml b/.github/labeler.yml index 2e08d3d7649..11c43e84f84 100644 --- a/.github/labeler.yml +++ b/.github/labeler.yml @@ -96,7 +96,7 @@ admin-ui: - changed-files: - any-glob-to-any-file: - solr/webapp/** - - solr/compose-ui/** + - solr/ui/** # Add 'prometheus-exporter' label prometheus-exporter: diff --git a/dev-docs/ui/introduction.adoc b/dev-docs/ui/introduction.adoc index f7a830c3c00..906bb00b3ba 100644 --- a/dev-docs/ui/introduction.adoc +++ b/dev-docs/ui/introduction.adoc @@ -18,4 +18,4 @@ the documentation is covering the following topics for new and experienced devel == Notes All the references to files and directories in the UI documentation are from within -the `solr/compose-ui` module, if not otherwise stated. \ No newline at end of file +the `solr/ui` module, if not otherwise stated. \ No newline at end of file diff --git a/dev-docs/ui/module-structure.adoc b/dev-docs/ui/module-structure.adoc index 62a52f8c9d6..5b678e4a9a3 100644 --- a/dev-docs/ui/module-structure.adoc +++ b/dev-docs/ui/module-structure.adoc @@ -2,7 +2,7 @@ == Module Structure -The UI module `compose-ui` follows a quite simple structure. It is split in +The `ui` module follows a quite simple structure. It is split in - *components*, which covers the logic part of the frontend and therefore contains the interfaces and implementations of them, @@ -14,7 +14,7 @@ if not the same, structure and files. == Components (Logic) -The logical part of a simple component (`org/apache/solr/composeui/components`) usually consists of: +The logical part of a simple component (`org/apache/solr/ui/components`) usually consists of: - **The component interface** (`[ComponentName]Component.kt`), that defines the UI state and the interaction options, @@ -48,7 +48,7 @@ This structure is strongly inspired by Decompose's https://arkivanov.github.io/D == User Interface (UI) Similar to the logical part, the UI classes are also separated in components under -`org.apache.solr.composeui.ui`. +`org.apache.solr.ui.views`. Components may consist of one or multiple composables that make up a screen, section or element. The composables may also be reused, which is why they may be moved at some point diff --git a/dev-docs/ui/testing-and-deployment.adoc b/dev-docs/ui/testing-and-deployment.adoc index f966752395f..b06b998b93a 100644 --- a/dev-docs/ui/testing-and-deployment.adoc +++ b/dev-docs/ui/testing-and-deployment.adoc @@ -32,7 +32,7 @@ To launch the JVM client, you can use: [source,bash] ---- -./gradlew :solr:compose-ui:run +./gradlew :solr:ui:run ---- To run the app on the web, you can launch the web target with: @@ -40,7 +40,7 @@ To run the app on the web, you can launch the web target with: [source,bash] ---- # not recommended for the above reasons -./gradlew :solr:compose-ui:wasmJsBrowserRun +./gradlew :solr:ui:wasmJsBrowserRun ---- Build times may be a bit longer than with the standalone JVM build. @@ -48,7 +48,7 @@ Build times may be a bit longer than with the standalone JVM build. === Integration Tests The integration tests of the module focus on testing the implementation found in -`org.apache.solr.composeui.ui`. That includes all UI elements / composables. Integration tests +`org.apache.solr.ui.views`. That includes all UI elements / composables. Integration tests may test entire flows as well, but require a suitable testing environment. Since UI tests require a more complex and platform-specific testing environment, they are disabled @@ -57,7 +57,7 @@ UI tests and a suitable testing environment for them, we may run these tests in === Unit Tests -Unit tests test the implementation found in `org.apache.solr.compose.components`. That package +Unit tests test the implementation found in `org.apache.solr.ui.components`. That package includes the logical part of the new UI and does not have any constraints to the UI part. Therefore, they can be executed in the automation pipelines easily. @@ -66,11 +66,11 @@ components to confirm correct component state transitions with specific inputs. == Deployment -The `compose-ui` module is configured to build artifacts for `WebAssembly` and `JVM`. +The `ui` module is configured to build artifacts for `WebAssembly` and `JVM`. === Packaging -The module `compose-ui` can be built and packaged for two targets (wasmJs / JVM) with two +The module `ui` can be built and packaged for two targets (wasmJs / JVM) with two variants each, development and production. To package the JVM target for development and generate a distribution (DEB, MSI or DMG file), @@ -78,16 +78,16 @@ you can use: [source,bash] ---- -./gradlew :solr:compose-ui:packageDistributionForCurrentOS +./gradlew :solr:ui:packageDistributionForCurrentOS ---- -The distribution can be found at `solr/compose-ui/build/compose/binaries/main/[deb|msi|dmg]/`. +The distribution can be found at `solr/ui/build/compose/binaries/main/[deb|msi|dmg]/`. To build the JVM target for production, you can use: [source,bash] ---- -./gradlew :solr:compose-ui:packageReleaseDistributionForCurrentOS +./gradlew :solr:ui:packageReleaseDistributionForCurrentOS ---- Platform-specific gradle tasks exist as well, but you cannot build for a @@ -98,10 +98,10 @@ If the client machine has Java installed, you can also generate an UberJar: [source,bash] ---- # for development -./gradlew :solr:compose-ui:packageUberJarForCurrentOs +./gradlew :solr:ui:packageUberJarForCurrentOs # for production -./gradlew :solr:compose-ui:packageReleaseUberJarForCurrentOs +./gradlew :solr:ui:packageReleaseUberJarForCurrentOs ---- When building the entire Solr project, the wasmJs target is included in the build artifacts. @@ -116,7 +116,7 @@ To tell the build process to use the production variant instead, you have ot pas The WebAssembly (wasmJs) target is used to generate artifacts that can be hosted together with our current webapp. The `server` that hosts the webapp is configured to host the new UI -as a module that is available under the URL path `/solr/compose`. +as a module that is available under the URL path `/solr/ui`. For that, two configuration files are added, one for development (`jetty-new-ui-dev.xml`) and one for production (`jetty-new-ui.xml`). The module configuration for development is less strict, diff --git a/settings.gradle b/settings.gradle index 724ee74b610..cf4acf46a84 100644 --- a/settings.gradle +++ b/settings.gradle @@ -58,6 +58,7 @@ include "solr:modules:s3-repository" include "solr:modules:scripting" include "solr:modules:sql" include "solr:webapp" +include "solr:ui" include "solr:benchmark" include "solr:test-framework" include "solr:solr-ref-guide" @@ -67,7 +68,6 @@ include "solr:packaging" include "solr:distribution" include "solr:docker" include "solr:prometheus-exporter" -include "solr:compose-ui" // Configures development for joint Lucene/ Solr composite build. apply from: file('gradle/lucene-dev/lucene-dev-repo-composite.gradle') diff --git a/solr/server/etc/jetty-new-ui-dev.xml b/solr/server/etc/jetty-new-ui-dev.xml index 30dfa57c10a..e3e74434ccf 100644 --- a/solr/server/etc/jetty-new-ui-dev.xml +++ b/solr/server/etc/jetty-new-ui-dev.xml @@ -20,7 +20,7 @@ - + @@ -30,7 +30,7 @@ - /solr/compose/* + /solr/ui/* Content-Security-Policy default-src 'none'; base-uri 'none'; connect-src 'self'; form-action 'self'; font-src 'self'; frame-ancestors 'none'; img-src 'self' data:; media-src 'self'; style-src 'self' 'unsafe-inline'; script-src 'self' 'unsafe-eval'; worker-src 'self'; diff --git a/solr/server/etc/jetty-new-ui-prod.xml b/solr/server/etc/jetty-new-ui-prod.xml index 2a0218176dd..c73b1e43133 100644 --- a/solr/server/etc/jetty-new-ui-prod.xml +++ b/solr/server/etc/jetty-new-ui-prod.xml @@ -3,7 +3,7 @@ - + @@ -17,7 +17,7 @@ - /solr/compose/* + /solr/ui/* Content-Security-Policy default-src 'none'; base-uri 'none'; connect-src 'self'; form-action 'self'; font-src 'self'; frame-ancestors 'none'; img-src 'self' data:; media-src 'self'; style-src 'self' 'unsafe-inline'; script-src 'self' 'wasm-unsafe-eval'; worker-src 'self'; diff --git a/solr/compose-ui/README.md b/solr/ui/README.md similarity index 95% rename from solr/compose-ui/README.md rename to solr/ui/README.md index 38848c70dc0..a9ebef64d27 100644 --- a/solr/compose-ui/README.md +++ b/solr/ui/README.md @@ -36,7 +36,7 @@ The module is available for desktop / JVM targets and web (WebAssembly). > reflect the module's configuration requirements. Review the differences between your file and > `gradle/template.gradle.properties` and update accordingly. -To build and run the desktop client simply run `./gradlew :solr:compose-ui:run`. +To build and run the desktop client simply run `./gradlew :solr:ui:run`. Make sure that you have a Solr development instance running on `localhost:8983`, as the current implementation uses hardcoded values. @@ -48,7 +48,7 @@ you can build the project as usual (see [Quickstart](../../README.md#quickstart) Various references are included in the webapp for already migrated pages. > Note that the standalone WebAssembly app executed via -> `./gradlew :solr:compose-ui:wasmJsBrowserRun` runs on port `8080` and will run +> `./gradlew :solr:ui:wasmJsBrowserRun` runs on port `8080` and will run > into CORS exceptions. Therefore, the usage of it for development is > discouraged. > diff --git a/solr/compose-ui/assets/logo.ico b/solr/ui/assets/logo.ico similarity index 100% rename from solr/compose-ui/assets/logo.ico rename to solr/ui/assets/logo.ico diff --git a/solr/compose-ui/assets/logo.png b/solr/ui/assets/logo.png similarity index 100% rename from solr/compose-ui/assets/logo.png rename to solr/ui/assets/logo.png diff --git a/solr/compose-ui/build.gradle.kts b/solr/ui/build.gradle.kts similarity index 99% rename from solr/compose-ui/build.gradle.kts rename to solr/ui/build.gradle.kts index 30e1ed6972c..ef110a296a5 100644 --- a/solr/compose-ui/build.gradle.kts +++ b/solr/ui/build.gradle.kts @@ -138,7 +138,7 @@ configurations { compose.desktop { application { - mainClass = "org.apache.solr.composeui.MainKt" + mainClass = "org.apache.solr.ui.MainKt" nativeDistributions { targetFormats(TargetFormat.Dmg, TargetFormat.Msi, TargetFormat.Deb) diff --git a/solr/compose-ui/gradle.lockfile b/solr/ui/gradle.lockfile similarity index 100% rename from solr/compose-ui/gradle.lockfile rename to solr/ui/gradle.lockfile diff --git a/solr/compose-ui/karma.config.d/wasm/adjust-timeouts.js b/solr/ui/karma.config.d/wasm/adjust-timeouts.js similarity index 100% rename from solr/compose-ui/karma.config.d/wasm/adjust-timeouts.js rename to solr/ui/karma.config.d/wasm/adjust-timeouts.js diff --git a/solr/compose-ui/src/commonMain/composeResources/drawable/solr-logo-dark.svg b/solr/ui/src/commonMain/composeResources/drawable/solr-logo-dark.svg similarity index 100% rename from solr/compose-ui/src/commonMain/composeResources/drawable/solr-logo-dark.svg rename to solr/ui/src/commonMain/composeResources/drawable/solr-logo-dark.svg diff --git a/solr/compose-ui/src/commonMain/composeResources/drawable/solr-logo-light.svg b/solr/ui/src/commonMain/composeResources/drawable/solr-logo-light.svg similarity index 100% rename from solr/compose-ui/src/commonMain/composeResources/drawable/solr-logo-light.svg rename to solr/ui/src/commonMain/composeResources/drawable/solr-logo-light.svg diff --git a/solr/compose-ui/src/commonMain/composeResources/values/strings.xml b/solr/ui/src/commonMain/composeResources/values/strings.xml similarity index 100% rename from solr/compose-ui/src/commonMain/composeResources/values/strings.xml rename to solr/ui/src/commonMain/composeResources/values/strings.xml diff --git a/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/components/environment/EnvironmentComponent.kt b/solr/ui/src/commonMain/kotlin/org/apache/solr/ui/components/environment/EnvironmentComponent.kt similarity index 82% rename from solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/components/environment/EnvironmentComponent.kt rename to solr/ui/src/commonMain/kotlin/org/apache/solr/ui/components/environment/EnvironmentComponent.kt index addd5dd4d11..99d6ee0183d 100644 --- a/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/components/environment/EnvironmentComponent.kt +++ b/solr/ui/src/commonMain/kotlin/org/apache/solr/ui/components/environment/EnvironmentComponent.kt @@ -15,12 +15,12 @@ * limitations under the License. */ -package org.apache.solr.composeui.components.environment +package org.apache.solr.ui.components.environment import kotlinx.coroutines.flow.StateFlow -import org.apache.solr.composeui.components.environment.data.JavaProperty -import org.apache.solr.composeui.components.environment.data.JvmData -import org.apache.solr.composeui.components.environment.data.Versions +import org.apache.solr.ui.components.environment.data.JavaProperty +import org.apache.solr.ui.components.environment.data.JvmData +import org.apache.solr.ui.components.environment.data.Versions /** * Component interface that represents the environment section. diff --git a/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/components/environment/data/JavaPropertiesResponse.kt b/solr/ui/src/commonMain/kotlin/org/apache/solr/ui/components/environment/data/JavaPropertiesResponse.kt similarity index 95% rename from solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/components/environment/data/JavaPropertiesResponse.kt rename to solr/ui/src/commonMain/kotlin/org/apache/solr/ui/components/environment/data/JavaPropertiesResponse.kt index db128264920..a83b08bc773 100644 --- a/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/components/environment/data/JavaPropertiesResponse.kt +++ b/solr/ui/src/commonMain/kotlin/org/apache/solr/ui/components/environment/data/JavaPropertiesResponse.kt @@ -15,7 +15,7 @@ * limitations under the License. */ -package org.apache.solr.composeui.components.environment.data +package org.apache.solr.ui.components.environment.data import kotlinx.serialization.SerialName import kotlinx.serialization.Serializable diff --git a/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/components/environment/data/JavaProperty.kt b/solr/ui/src/commonMain/kotlin/org/apache/solr/ui/components/environment/data/JavaProperty.kt similarity index 94% rename from solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/components/environment/data/JavaProperty.kt rename to solr/ui/src/commonMain/kotlin/org/apache/solr/ui/components/environment/data/JavaProperty.kt index 0202d8e5f2c..1f349fa3d88 100644 --- a/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/components/environment/data/JavaProperty.kt +++ b/solr/ui/src/commonMain/kotlin/org/apache/solr/ui/components/environment/data/JavaProperty.kt @@ -15,7 +15,7 @@ * limitations under the License. */ -package org.apache.solr.composeui.components.environment.data +package org.apache.solr.ui.components.environment.data /** * Typealias of JavaProperty, which are simple key-value pairs. diff --git a/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/components/environment/data/JavaRuntimeInfo.kt b/solr/ui/src/commonMain/kotlin/org/apache/solr/ui/components/environment/data/JavaRuntimeInfo.kt similarity index 94% rename from solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/components/environment/data/JavaRuntimeInfo.kt rename to solr/ui/src/commonMain/kotlin/org/apache/solr/ui/components/environment/data/JavaRuntimeInfo.kt index 145a657c5af..2dcc1daa4a6 100644 --- a/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/components/environment/data/JavaRuntimeInfo.kt +++ b/solr/ui/src/commonMain/kotlin/org/apache/solr/ui/components/environment/data/JavaRuntimeInfo.kt @@ -15,7 +15,7 @@ * limitations under the License. */ -package org.apache.solr.composeui.components.environment.data +package org.apache.solr.ui.components.environment.data import kotlinx.serialization.Serializable diff --git a/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/components/environment/data/Jmx.kt b/solr/ui/src/commonMain/kotlin/org/apache/solr/ui/components/environment/data/Jmx.kt similarity index 94% rename from solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/components/environment/data/Jmx.kt rename to solr/ui/src/commonMain/kotlin/org/apache/solr/ui/components/environment/data/Jmx.kt index b81fae33aa9..7ee8e8b94f9 100644 --- a/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/components/environment/data/Jmx.kt +++ b/solr/ui/src/commonMain/kotlin/org/apache/solr/ui/components/environment/data/Jmx.kt @@ -15,7 +15,7 @@ * limitations under the License. */ -package org.apache.solr.composeui.components.environment.data +package org.apache.solr.ui.components.environment.data import kotlinx.serialization.Serializable diff --git a/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/components/environment/data/JvmData.kt b/solr/ui/src/commonMain/kotlin/org/apache/solr/ui/components/environment/data/JvmData.kt similarity index 95% rename from solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/components/environment/data/JvmData.kt rename to solr/ui/src/commonMain/kotlin/org/apache/solr/ui/components/environment/data/JvmData.kt index a4c70d7d22c..ebc89f2bcad 100644 --- a/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/components/environment/data/JvmData.kt +++ b/solr/ui/src/commonMain/kotlin/org/apache/solr/ui/components/environment/data/JvmData.kt @@ -15,7 +15,7 @@ * limitations under the License. */ -package org.apache.solr.composeui.components.environment.data +package org.apache.solr.ui.components.environment.data import kotlinx.serialization.Serializable diff --git a/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/components/environment/data/JvmMemory.kt b/solr/ui/src/commonMain/kotlin/org/apache/solr/ui/components/environment/data/JvmMemory.kt similarity index 94% rename from solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/components/environment/data/JvmMemory.kt rename to solr/ui/src/commonMain/kotlin/org/apache/solr/ui/components/environment/data/JvmMemory.kt index b2bb8b13064..4da6819d2e5 100644 --- a/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/components/environment/data/JvmMemory.kt +++ b/solr/ui/src/commonMain/kotlin/org/apache/solr/ui/components/environment/data/JvmMemory.kt @@ -15,7 +15,7 @@ * limitations under the License. */ -package org.apache.solr.composeui.components.environment.data +package org.apache.solr.ui.components.environment.data import kotlinx.serialization.Serializable diff --git a/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/components/environment/data/JvmMemoryRaw.kt b/solr/ui/src/commonMain/kotlin/org/apache/solr/ui/components/environment/data/JvmMemoryRaw.kt similarity index 94% rename from solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/components/environment/data/JvmMemoryRaw.kt rename to solr/ui/src/commonMain/kotlin/org/apache/solr/ui/components/environment/data/JvmMemoryRaw.kt index f8b0e9e6290..d739e1bafb9 100644 --- a/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/components/environment/data/JvmMemoryRaw.kt +++ b/solr/ui/src/commonMain/kotlin/org/apache/solr/ui/components/environment/data/JvmMemoryRaw.kt @@ -15,7 +15,7 @@ * limitations under the License. */ -package org.apache.solr.composeui.components.environment.data +package org.apache.solr.ui.components.environment.data import kotlinx.serialization.SerialName import kotlinx.serialization.Serializable diff --git a/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/components/environment/data/SecurityConfig.kt b/solr/ui/src/commonMain/kotlin/org/apache/solr/ui/components/environment/data/SecurityConfig.kt similarity index 93% rename from solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/components/environment/data/SecurityConfig.kt rename to solr/ui/src/commonMain/kotlin/org/apache/solr/ui/components/environment/data/SecurityConfig.kt index 39b86b74ea5..00871a8f080 100644 --- a/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/components/environment/data/SecurityConfig.kt +++ b/solr/ui/src/commonMain/kotlin/org/apache/solr/ui/components/environment/data/SecurityConfig.kt @@ -15,7 +15,7 @@ * limitations under the License. */ -package org.apache.solr.composeui.components.environment.data +package org.apache.solr.ui.components.environment.data import kotlinx.serialization.Serializable diff --git a/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/components/environment/data/SystemData.kt b/solr/ui/src/commonMain/kotlin/org/apache/solr/ui/components/environment/data/SystemData.kt similarity index 95% rename from solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/components/environment/data/SystemData.kt rename to solr/ui/src/commonMain/kotlin/org/apache/solr/ui/components/environment/data/SystemData.kt index 5576f872e87..674a2acdf3c 100644 --- a/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/components/environment/data/SystemData.kt +++ b/solr/ui/src/commonMain/kotlin/org/apache/solr/ui/components/environment/data/SystemData.kt @@ -15,7 +15,7 @@ * limitations under the License. */ -package org.apache.solr.composeui.components.environment.data +package org.apache.solr.ui.components.environment.data import kotlinx.serialization.SerialName import kotlinx.serialization.Serializable diff --git a/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/components/environment/data/SystemInformation.kt b/solr/ui/src/commonMain/kotlin/org/apache/solr/ui/components/environment/data/SystemInformation.kt similarity index 96% rename from solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/components/environment/data/SystemInformation.kt rename to solr/ui/src/commonMain/kotlin/org/apache/solr/ui/components/environment/data/SystemInformation.kt index 37a71bdaf76..905c750719d 100644 --- a/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/components/environment/data/SystemInformation.kt +++ b/solr/ui/src/commonMain/kotlin/org/apache/solr/ui/components/environment/data/SystemInformation.kt @@ -15,7 +15,7 @@ * limitations under the License. */ -package org.apache.solr.composeui.components.environment.data +package org.apache.solr.ui.components.environment.data import kotlinx.serialization.Serializable diff --git a/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/components/environment/data/SystemMode.kt b/solr/ui/src/commonMain/kotlin/org/apache/solr/ui/components/environment/data/SystemMode.kt similarity index 94% rename from solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/components/environment/data/SystemMode.kt rename to solr/ui/src/commonMain/kotlin/org/apache/solr/ui/components/environment/data/SystemMode.kt index dca74148045..aa854e95da7 100644 --- a/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/components/environment/data/SystemMode.kt +++ b/solr/ui/src/commonMain/kotlin/org/apache/solr/ui/components/environment/data/SystemMode.kt @@ -15,7 +15,7 @@ * limitations under the License. */ -package org.apache.solr.composeui.components.environment.data +package org.apache.solr.ui.components.environment.data import kotlinx.serialization.SerialName import kotlinx.serialization.Serializable diff --git a/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/components/environment/data/Versions.kt b/solr/ui/src/commonMain/kotlin/org/apache/solr/ui/components/environment/data/Versions.kt similarity index 95% rename from solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/components/environment/data/Versions.kt rename to solr/ui/src/commonMain/kotlin/org/apache/solr/ui/components/environment/data/Versions.kt index bc4a4c16c06..b06ab69cf31 100644 --- a/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/components/environment/data/Versions.kt +++ b/solr/ui/src/commonMain/kotlin/org/apache/solr/ui/components/environment/data/Versions.kt @@ -15,7 +15,7 @@ * limitations under the License. */ -package org.apache.solr.composeui.components.environment.data +package org.apache.solr.ui.components.environment.data import kotlinx.serialization.SerialName import kotlinx.serialization.Serializable diff --git a/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/components/environment/integration/DefaultEnvironmentComponent.kt b/solr/ui/src/commonMain/kotlin/org/apache/solr/ui/components/environment/integration/DefaultEnvironmentComponent.kt similarity index 82% rename from solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/components/environment/integration/DefaultEnvironmentComponent.kt rename to solr/ui/src/commonMain/kotlin/org/apache/solr/ui/components/environment/integration/DefaultEnvironmentComponent.kt index 151eca7d385..17456a43822 100644 --- a/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/components/environment/integration/DefaultEnvironmentComponent.kt +++ b/solr/ui/src/commonMain/kotlin/org/apache/solr/ui/components/environment/integration/DefaultEnvironmentComponent.kt @@ -15,18 +15,18 @@ * limitations under the License. */ -package org.apache.solr.composeui.components.environment.integration +package org.apache.solr.ui.components.environment.integration import com.arkivanov.mvikotlin.core.instancekeeper.getStore import com.arkivanov.mvikotlin.core.store.StoreFactory import com.arkivanov.mvikotlin.extensions.coroutines.stateFlow import io.ktor.client.HttpClient import kotlinx.coroutines.ExperimentalCoroutinesApi -import org.apache.solr.composeui.components.environment.EnvironmentComponent -import org.apache.solr.composeui.components.environment.store.EnvironmentStoreProvider -import org.apache.solr.composeui.utils.AppComponentContext -import org.apache.solr.composeui.utils.coroutineScope -import org.apache.solr.composeui.utils.map +import org.apache.solr.ui.components.environment.EnvironmentComponent +import org.apache.solr.ui.components.environment.store.EnvironmentStoreProvider +import org.apache.solr.ui.utils.AppComponentContext +import org.apache.solr.ui.utils.coroutineScope +import org.apache.solr.ui.utils.map /** * Default implementation of the [EnvironmentComponent]. diff --git a/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/components/environment/integration/HttpEnvironmentStoreClient.kt b/solr/ui/src/commonMain/kotlin/org/apache/solr/ui/components/environment/integration/HttpEnvironmentStoreClient.kt similarity index 86% rename from solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/components/environment/integration/HttpEnvironmentStoreClient.kt rename to solr/ui/src/commonMain/kotlin/org/apache/solr/ui/components/environment/integration/HttpEnvironmentStoreClient.kt index 758b1200cf8..1673c48c8ff 100644 --- a/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/components/environment/integration/HttpEnvironmentStoreClient.kt +++ b/solr/ui/src/commonMain/kotlin/org/apache/solr/ui/components/environment/integration/HttpEnvironmentStoreClient.kt @@ -15,16 +15,16 @@ * limitations under the License. */ -package org.apache.solr.composeui.components.environment.integration +package org.apache.solr.ui.components.environment.integration import io.ktor.client.HttpClient import io.ktor.client.call.body import io.ktor.client.request.get import io.ktor.http.isSuccess -import org.apache.solr.composeui.components.environment.data.JavaPropertiesResponse -import org.apache.solr.composeui.components.environment.data.JavaProperty -import org.apache.solr.composeui.components.environment.data.SystemData -import org.apache.solr.composeui.components.environment.store.EnvironmentStoreProvider +import org.apache.solr.ui.components.environment.data.JavaPropertiesResponse +import org.apache.solr.ui.components.environment.data.JavaProperty +import org.apache.solr.ui.components.environment.data.SystemData +import org.apache.solr.ui.components.environment.store.EnvironmentStoreProvider /** * Client implementation of the [EnvironmentStoreProvider.Client] that makes use diff --git a/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/components/environment/integration/Mappers.kt b/solr/ui/src/commonMain/kotlin/org/apache/solr/ui/components/environment/integration/Mappers.kt similarity index 82% rename from solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/components/environment/integration/Mappers.kt rename to solr/ui/src/commonMain/kotlin/org/apache/solr/ui/components/environment/integration/Mappers.kt index 78e9f7b0114..3a8f89a7264 100644 --- a/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/components/environment/integration/Mappers.kt +++ b/solr/ui/src/commonMain/kotlin/org/apache/solr/ui/components/environment/integration/Mappers.kt @@ -15,10 +15,10 @@ * limitations under the License. */ -package org.apache.solr.composeui.components.environment.integration +package org.apache.solr.ui.components.environment.integration -import org.apache.solr.composeui.components.environment.EnvironmentComponent -import org.apache.solr.composeui.components.environment.store.EnvironmentStore +import org.apache.solr.ui.components.environment.EnvironmentComponent +import org.apache.solr.ui.components.environment.store.EnvironmentStore internal val environmentStateToModel: (EnvironmentStore.State) -> EnvironmentComponent.Model = { EnvironmentComponent.Model( diff --git a/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/components/environment/store/EnvironmentStore.kt b/solr/ui/src/commonMain/kotlin/org/apache/solr/ui/components/environment/store/EnvironmentStore.kt similarity index 73% rename from solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/components/environment/store/EnvironmentStore.kt rename to solr/ui/src/commonMain/kotlin/org/apache/solr/ui/components/environment/store/EnvironmentStore.kt index 633bb4ef47f..4c6ae252d6b 100644 --- a/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/components/environment/store/EnvironmentStore.kt +++ b/solr/ui/src/commonMain/kotlin/org/apache/solr/ui/components/environment/store/EnvironmentStore.kt @@ -15,17 +15,17 @@ * limitations under the License. */ -package org.apache.solr.composeui.components.environment.store +package org.apache.solr.ui.components.environment.store import com.arkivanov.mvikotlin.core.store.Store -import org.apache.solr.composeui.components.environment.data.JavaProperty -import org.apache.solr.composeui.components.environment.data.JvmData -import org.apache.solr.composeui.components.environment.data.SecurityConfig -import org.apache.solr.composeui.components.environment.data.SystemInformation -import org.apache.solr.composeui.components.environment.data.SystemMode -import org.apache.solr.composeui.components.environment.data.Versions -import org.apache.solr.composeui.components.environment.store.EnvironmentStore.Intent -import org.apache.solr.composeui.components.environment.store.EnvironmentStore.State +import org.apache.solr.ui.components.environment.data.JavaProperty +import org.apache.solr.ui.components.environment.data.JvmData +import org.apache.solr.ui.components.environment.data.SecurityConfig +import org.apache.solr.ui.components.environment.data.SystemInformation +import org.apache.solr.ui.components.environment.data.SystemMode +import org.apache.solr.ui.components.environment.data.Versions +import org.apache.solr.ui.components.environment.store.EnvironmentStore.Intent +import org.apache.solr.ui.components.environment.store.EnvironmentStore.State /** * State store interface of the environment. diff --git a/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/components/environment/store/EnvironmentStoreProvider.kt b/solr/ui/src/commonMain/kotlin/org/apache/solr/ui/components/environment/store/EnvironmentStoreProvider.kt similarity index 93% rename from solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/components/environment/store/EnvironmentStoreProvider.kt rename to solr/ui/src/commonMain/kotlin/org/apache/solr/ui/components/environment/store/EnvironmentStoreProvider.kt index 22c9ff99270..fea0f1fcf73 100644 --- a/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/components/environment/store/EnvironmentStoreProvider.kt +++ b/solr/ui/src/commonMain/kotlin/org/apache/solr/ui/components/environment/store/EnvironmentStoreProvider.kt @@ -15,7 +15,7 @@ * limitations under the License. */ -package org.apache.solr.composeui.components.environment.store +package org.apache.solr.ui.components.environment.store import com.arkivanov.mvikotlin.core.store.Reducer import com.arkivanov.mvikotlin.core.store.SimpleBootstrapper @@ -25,10 +25,10 @@ import com.arkivanov.mvikotlin.extensions.coroutines.CoroutineExecutor import kotlin.coroutines.CoroutineContext import kotlinx.coroutines.launch import kotlinx.coroutines.withContext -import org.apache.solr.composeui.components.environment.data.JavaProperty -import org.apache.solr.composeui.components.environment.data.SystemData -import org.apache.solr.composeui.components.environment.store.EnvironmentStore.Intent -import org.apache.solr.composeui.components.environment.store.EnvironmentStore.State +import org.apache.solr.ui.components.environment.data.JavaProperty +import org.apache.solr.ui.components.environment.data.SystemData +import org.apache.solr.ui.components.environment.store.EnvironmentStore.Intent +import org.apache.solr.ui.components.environment.store.EnvironmentStore.State /** * Store provider that [provide]s instances of [EnvironmentStore]. diff --git a/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/components/logging/LoggingComponent.kt b/solr/ui/src/commonMain/kotlin/org/apache/solr/ui/components/logging/LoggingComponent.kt similarity index 94% rename from solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/components/logging/LoggingComponent.kt rename to solr/ui/src/commonMain/kotlin/org/apache/solr/ui/components/logging/LoggingComponent.kt index b1073b58aa8..6e074228a74 100644 --- a/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/components/logging/LoggingComponent.kt +++ b/solr/ui/src/commonMain/kotlin/org/apache/solr/ui/components/logging/LoggingComponent.kt @@ -15,6 +15,6 @@ * limitations under the License. */ -package org.apache.solr.composeui.components.logging +package org.apache.solr.ui.components.logging interface LoggingComponent diff --git a/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/components/logging/integration/DefaultLoggingComponent.kt b/solr/ui/src/commonMain/kotlin/org/apache/solr/ui/components/logging/integration/DefaultLoggingComponent.kt similarity index 84% rename from solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/components/logging/integration/DefaultLoggingComponent.kt rename to solr/ui/src/commonMain/kotlin/org/apache/solr/ui/components/logging/integration/DefaultLoggingComponent.kt index 572d228e7bb..3e7f381f8a2 100644 --- a/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/components/logging/integration/DefaultLoggingComponent.kt +++ b/solr/ui/src/commonMain/kotlin/org/apache/solr/ui/components/logging/integration/DefaultLoggingComponent.kt @@ -15,11 +15,11 @@ * limitations under the License. */ -package org.apache.solr.composeui.components.logging.integration +package org.apache.solr.ui.components.logging.integration import com.arkivanov.mvikotlin.core.store.StoreFactory -import org.apache.solr.composeui.components.logging.LoggingComponent -import org.apache.solr.composeui.utils.AppComponentContext +import org.apache.solr.ui.components.logging.LoggingComponent +import org.apache.solr.ui.utils.AppComponentContext class DefaultLoggingComponent( componentContext: AppComponentContext, diff --git a/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/components/main/MainComponent.kt b/solr/ui/src/commonMain/kotlin/org/apache/solr/ui/components/main/MainComponent.kt similarity index 90% rename from solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/components/main/MainComponent.kt rename to solr/ui/src/commonMain/kotlin/org/apache/solr/ui/components/main/MainComponent.kt index e27e682b36c..3be4f9ef9cd 100644 --- a/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/components/main/MainComponent.kt +++ b/solr/ui/src/commonMain/kotlin/org/apache/solr/ui/components/main/MainComponent.kt @@ -15,14 +15,14 @@ * limitations under the License. */ -package org.apache.solr.composeui.components.main +package org.apache.solr.ui.components.main import com.arkivanov.decompose.router.stack.ChildStack import com.arkivanov.decompose.value.Value -import org.apache.solr.composeui.components.environment.EnvironmentComponent -import org.apache.solr.composeui.components.logging.LoggingComponent -import org.apache.solr.composeui.components.navigation.NavigationComponent -import org.apache.solr.composeui.ui.navigation.MainMenu +import org.apache.solr.ui.components.environment.EnvironmentComponent +import org.apache.solr.ui.components.logging.LoggingComponent +import org.apache.solr.ui.components.navigation.NavigationComponent +import org.apache.solr.ui.views.navigation.MainMenu /** * Main component of the application that is used as base for users with access. diff --git a/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/components/main/integration/DefaultMainComponent.kt b/solr/ui/src/commonMain/kotlin/org/apache/solr/ui/components/main/integration/DefaultMainComponent.kt similarity index 92% rename from solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/components/main/integration/DefaultMainComponent.kt rename to solr/ui/src/commonMain/kotlin/org/apache/solr/ui/components/main/integration/DefaultMainComponent.kt index 5e55fb8583c..f7100c8a5a1 100644 --- a/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/components/main/integration/DefaultMainComponent.kt +++ b/solr/ui/src/commonMain/kotlin/org/apache/solr/ui/components/main/integration/DefaultMainComponent.kt @@ -15,7 +15,7 @@ * limitations under the License. */ -package org.apache.solr.composeui.components.main.integration +package org.apache.solr.ui.components.main.integration import com.arkivanov.decompose.router.stack.ChildStack import com.arkivanov.decompose.router.stack.StackNavigation @@ -25,14 +25,14 @@ import com.arkivanov.decompose.value.Value import com.arkivanov.mvikotlin.core.store.StoreFactory import io.ktor.client.HttpClient import kotlinx.serialization.Serializable -import org.apache.solr.composeui.components.environment.EnvironmentComponent -import org.apache.solr.composeui.components.environment.integration.DefaultEnvironmentComponent -import org.apache.solr.composeui.components.logging.LoggingComponent -import org.apache.solr.composeui.components.logging.integration.DefaultLoggingComponent -import org.apache.solr.composeui.components.main.MainComponent -import org.apache.solr.composeui.components.main.MainComponent.Child -import org.apache.solr.composeui.ui.navigation.MainMenu -import org.apache.solr.composeui.utils.AppComponentContext +import org.apache.solr.ui.components.environment.EnvironmentComponent +import org.apache.solr.ui.components.environment.integration.DefaultEnvironmentComponent +import org.apache.solr.ui.components.logging.LoggingComponent +import org.apache.solr.ui.components.logging.integration.DefaultLoggingComponent +import org.apache.solr.ui.components.main.MainComponent +import org.apache.solr.ui.components.main.MainComponent.Child +import org.apache.solr.ui.views.navigation.MainMenu +import org.apache.solr.ui.utils.AppComponentContext class DefaultMainComponent internal constructor( componentContext: AppComponentContext, diff --git a/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/components/main/integration/Mappers.kt b/solr/ui/src/commonMain/kotlin/org/apache/solr/ui/components/main/integration/Mappers.kt similarity index 85% rename from solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/components/main/integration/Mappers.kt rename to solr/ui/src/commonMain/kotlin/org/apache/solr/ui/components/main/integration/Mappers.kt index fe02c36381d..19557f36d01 100644 --- a/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/components/main/integration/Mappers.kt +++ b/solr/ui/src/commonMain/kotlin/org/apache/solr/ui/components/main/integration/Mappers.kt @@ -15,10 +15,10 @@ * limitations under the License. */ -package org.apache.solr.composeui.components.main.integration +package org.apache.solr.ui.components.main.integration -import org.apache.solr.composeui.components.main.MainComponent -import org.apache.solr.composeui.ui.navigation.MainMenu +import org.apache.solr.ui.components.main.MainComponent +import org.apache.solr.ui.views.navigation.MainMenu val MainComponent.Child.asMainMenu: MainMenu get() = when (this) { diff --git a/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/components/navigation/NavigationComponent.kt b/solr/ui/src/commonMain/kotlin/org/apache/solr/ui/components/navigation/NavigationComponent.kt similarity index 95% rename from solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/components/navigation/NavigationComponent.kt rename to solr/ui/src/commonMain/kotlin/org/apache/solr/ui/components/navigation/NavigationComponent.kt index e00173fd960..1ecdb1bfe20 100644 --- a/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/components/navigation/NavigationComponent.kt +++ b/solr/ui/src/commonMain/kotlin/org/apache/solr/ui/components/navigation/NavigationComponent.kt @@ -15,7 +15,7 @@ * limitations under the License. */ -package org.apache.solr.composeui.components.navigation +package org.apache.solr.ui.components.navigation /** * Interface that provides the basic functionality for any navigation component. Navigation diff --git a/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/components/root/RootComponent.kt b/solr/ui/src/commonMain/kotlin/org/apache/solr/ui/components/root/RootComponent.kt similarity index 92% rename from solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/components/root/RootComponent.kt rename to solr/ui/src/commonMain/kotlin/org/apache/solr/ui/components/root/RootComponent.kt index 6628f93b7d6..bd0c89f1842 100644 --- a/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/components/root/RootComponent.kt +++ b/solr/ui/src/commonMain/kotlin/org/apache/solr/ui/components/root/RootComponent.kt @@ -15,11 +15,11 @@ * limitations under the License. */ -package org.apache.solr.composeui.components.root +package org.apache.solr.ui.components.root import com.arkivanov.decompose.router.stack.ChildStack import com.arkivanov.decompose.value.Value -import org.apache.solr.composeui.components.main.MainComponent +import org.apache.solr.ui.components.main.MainComponent /** * Root component used by each target as an entry point to the application. diff --git a/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/components/root/integration/SimpleRootComponent.kt b/solr/ui/src/commonMain/kotlin/org/apache/solr/ui/components/root/integration/SimpleRootComponent.kt similarity index 90% rename from solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/components/root/integration/SimpleRootComponent.kt rename to solr/ui/src/commonMain/kotlin/org/apache/solr/ui/components/root/integration/SimpleRootComponent.kt index a58888f92cf..4789db8c611 100644 --- a/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/components/root/integration/SimpleRootComponent.kt +++ b/solr/ui/src/commonMain/kotlin/org/apache/solr/ui/components/root/integration/SimpleRootComponent.kt @@ -15,7 +15,7 @@ * limitations under the License. */ -package org.apache.solr.composeui.components.root.integration +package org.apache.solr.ui.components.root.integration import com.arkivanov.decompose.router.stack.ChildStack import com.arkivanov.decompose.router.stack.StackNavigation @@ -24,10 +24,10 @@ import com.arkivanov.decompose.value.Value import com.arkivanov.mvikotlin.core.store.StoreFactory import io.ktor.client.HttpClient import kotlinx.serialization.Serializable -import org.apache.solr.composeui.components.main.MainComponent -import org.apache.solr.composeui.components.main.integration.DefaultMainComponent -import org.apache.solr.composeui.components.root.RootComponent -import org.apache.solr.composeui.utils.AppComponentContext +import org.apache.solr.ui.components.main.MainComponent +import org.apache.solr.ui.components.main.integration.DefaultMainComponent +import org.apache.solr.ui.components.root.RootComponent +import org.apache.solr.ui.utils.AppComponentContext /** * A simple root component implementation that does not check the user's access level and redirects diff --git a/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/utils/AppComponentContext.kt b/solr/ui/src/commonMain/kotlin/org/apache/solr/ui/utils/AppComponentContext.kt similarity index 96% rename from solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/utils/AppComponentContext.kt rename to solr/ui/src/commonMain/kotlin/org/apache/solr/ui/utils/AppComponentContext.kt index 19efd6c8364..e477ab745c7 100644 --- a/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/utils/AppComponentContext.kt +++ b/solr/ui/src/commonMain/kotlin/org/apache/solr/ui/utils/AppComponentContext.kt @@ -15,7 +15,7 @@ * limitations under the License. */ -package org.apache.solr.composeui.utils +package org.apache.solr.ui.utils import com.arkivanov.decompose.GenericComponentContext diff --git a/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/utils/CoroutineContextOwner.kt b/solr/ui/src/commonMain/kotlin/org/apache/solr/ui/utils/CoroutineContextOwner.kt similarity index 96% rename from solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/utils/CoroutineContextOwner.kt rename to solr/ui/src/commonMain/kotlin/org/apache/solr/ui/utils/CoroutineContextOwner.kt index a39de3dfcaf..d39edc9d809 100644 --- a/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/utils/CoroutineContextOwner.kt +++ b/solr/ui/src/commonMain/kotlin/org/apache/solr/ui/utils/CoroutineContextOwner.kt @@ -15,7 +15,7 @@ * limitations under the License. */ -package org.apache.solr.composeui.utils +package org.apache.solr.ui.utils import kotlin.coroutines.CoroutineContext diff --git a/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/utils/CoroutineScopeExt.kt b/solr/ui/src/commonMain/kotlin/org/apache/solr/ui/utils/CoroutineScopeExt.kt similarity index 98% rename from solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/utils/CoroutineScopeExt.kt rename to solr/ui/src/commonMain/kotlin/org/apache/solr/ui/utils/CoroutineScopeExt.kt index d744cb612f7..ed9f8d1a15a 100644 --- a/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/utils/CoroutineScopeExt.kt +++ b/solr/ui/src/commonMain/kotlin/org/apache/solr/ui/utils/CoroutineScopeExt.kt @@ -15,7 +15,7 @@ * limitations under the License. */ -package org.apache.solr.composeui.utils +package org.apache.solr.ui.utils import com.arkivanov.essenty.lifecycle.Lifecycle import com.arkivanov.essenty.lifecycle.LifecycleOwner diff --git a/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/utils/DefaultAppComponentContext.kt b/solr/ui/src/commonMain/kotlin/org/apache/solr/ui/utils/DefaultAppComponentContext.kt similarity index 98% rename from solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/utils/DefaultAppComponentContext.kt rename to solr/ui/src/commonMain/kotlin/org/apache/solr/ui/utils/DefaultAppComponentContext.kt index 4fea772bc68..e648bf68045 100644 --- a/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/utils/DefaultAppComponentContext.kt +++ b/solr/ui/src/commonMain/kotlin/org/apache/solr/ui/utils/DefaultAppComponentContext.kt @@ -15,7 +15,7 @@ * limitations under the License. */ -package org.apache.solr.composeui.utils +package org.apache.solr.ui.utils import com.arkivanov.decompose.ComponentContext import com.arkivanov.decompose.ComponentContextFactory diff --git a/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/utils/HttpClientUtils.kt b/solr/ui/src/commonMain/kotlin/org/apache/solr/ui/utils/HttpClientUtils.kt similarity index 97% rename from solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/utils/HttpClientUtils.kt rename to solr/ui/src/commonMain/kotlin/org/apache/solr/ui/utils/HttpClientUtils.kt index a615afa436f..3e894a5f938 100644 --- a/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/utils/HttpClientUtils.kt +++ b/solr/ui/src/commonMain/kotlin/org/apache/solr/ui/utils/HttpClientUtils.kt @@ -15,7 +15,7 @@ * limitations under the License. */ -package org.apache.solr.composeui.utils +package org.apache.solr.ui.utils import io.ktor.client.HttpClient import io.ktor.client.plugins.contentnegotiation.ContentNegotiation diff --git a/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/ui/components/SolrCard.kt b/solr/ui/src/commonMain/kotlin/org/apache/solr/ui/views/components/SolrCard.kt similarity index 97% rename from solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/ui/components/SolrCard.kt rename to solr/ui/src/commonMain/kotlin/org/apache/solr/ui/views/components/SolrCard.kt index 63c0134220e..545296d01e3 100644 --- a/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/ui/components/SolrCard.kt +++ b/solr/ui/src/commonMain/kotlin/org/apache/solr/ui/views/components/SolrCard.kt @@ -15,7 +15,7 @@ * limitations under the License. */ -package org.apache.solr.composeui.ui.components +package org.apache.solr.ui.views.components import androidx.compose.foundation.BorderStroke import androidx.compose.foundation.background diff --git a/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/ui/environment/CommandLineArgumentsCard.kt b/solr/ui/src/commonMain/kotlin/org/apache/solr/ui/views/environment/CommandLineArgumentsCard.kt similarity index 94% rename from solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/ui/environment/CommandLineArgumentsCard.kt rename to solr/ui/src/commonMain/kotlin/org/apache/solr/ui/views/environment/CommandLineArgumentsCard.kt index af46e35b797..2e02e38b694 100644 --- a/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/ui/environment/CommandLineArgumentsCard.kt +++ b/solr/ui/src/commonMain/kotlin/org/apache/solr/ui/views/environment/CommandLineArgumentsCard.kt @@ -15,7 +15,7 @@ * limitations under the License. */ -package org.apache.solr.composeui.ui.environment +package org.apache.solr.ui.views.environment import androidx.compose.foundation.BorderStroke import androidx.compose.foundation.background @@ -30,8 +30,8 @@ import androidx.compose.material3.surfaceColorAtElevation import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import androidx.compose.ui.unit.dp -import org.apache.solr.composeui.ui.components.SolrCard -import org.apache.solr.composeui.ui.theme.SolrTheme +import org.apache.solr.ui.views.components.SolrCard +import org.apache.solr.ui.views.theme.SolrTheme /** * A card that displays the provided command line arguments in a list. diff --git a/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/ui/environment/EnvironmentContent.kt b/solr/ui/src/commonMain/kotlin/org/apache/solr/ui/views/environment/EnvironmentContent.kt similarity index 95% rename from solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/ui/environment/EnvironmentContent.kt rename to solr/ui/src/commonMain/kotlin/org/apache/solr/ui/views/environment/EnvironmentContent.kt index 0bbba80b686..2dc20f808eb 100644 --- a/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/ui/environment/EnvironmentContent.kt +++ b/solr/ui/src/commonMain/kotlin/org/apache/solr/ui/views/environment/EnvironmentContent.kt @@ -15,7 +15,7 @@ * limitations under the License. */ -package org.apache.solr.composeui.ui.environment +package org.apache.solr.ui.views.environment import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.ExperimentalLayoutApi @@ -27,7 +27,7 @@ import androidx.compose.runtime.getValue import androidx.compose.ui.Modifier import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.dp -import org.apache.solr.composeui.components.environment.EnvironmentComponent +import org.apache.solr.ui.components.environment.EnvironmentComponent /** * Composable for loading the environment section. diff --git a/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/ui/environment/JavaPropertiesCard.kt b/solr/ui/src/commonMain/kotlin/org/apache/solr/ui/views/environment/JavaPropertiesCard.kt similarity index 93% rename from solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/ui/environment/JavaPropertiesCard.kt rename to solr/ui/src/commonMain/kotlin/org/apache/solr/ui/views/environment/JavaPropertiesCard.kt index b6b64f4fa29..a6de782cd73 100644 --- a/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/ui/environment/JavaPropertiesCard.kt +++ b/solr/ui/src/commonMain/kotlin/org/apache/solr/ui/views/environment/JavaPropertiesCard.kt @@ -15,7 +15,7 @@ * limitations under the License. */ -package org.apache.solr.composeui.ui.environment +package org.apache.solr.ui.views.environment import androidx.compose.foundation.BorderStroke import androidx.compose.foundation.background @@ -31,9 +31,9 @@ import androidx.compose.material3.surfaceColorAtElevation import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import androidx.compose.ui.unit.dp -import org.apache.solr.composeui.components.environment.data.JavaProperty -import org.apache.solr.composeui.ui.components.SolrCard -import org.apache.solr.composeui.ui.theme.SolrTheme +import org.apache.solr.ui.components.environment.data.JavaProperty +import org.apache.solr.ui.views.components.SolrCard +import org.apache.solr.ui.views.theme.SolrTheme /** * Composable card that displays the provided java properties. diff --git a/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/ui/environment/VersionsCard.kt b/solr/ui/src/commonMain/kotlin/org/apache/solr/ui/views/environment/VersionsCard.kt similarity index 92% rename from solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/ui/environment/VersionsCard.kt rename to solr/ui/src/commonMain/kotlin/org/apache/solr/ui/views/environment/VersionsCard.kt index 601394064b5..cec7a52dcc0 100644 --- a/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/ui/environment/VersionsCard.kt +++ b/solr/ui/src/commonMain/kotlin/org/apache/solr/ui/views/environment/VersionsCard.kt @@ -15,7 +15,7 @@ * limitations under the License. */ -package org.apache.solr.composeui.ui.environment +package org.apache.solr.ui.views.environment import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Row @@ -27,9 +27,9 @@ import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.unit.dp -import org.apache.solr.composeui.components.environment.data.JvmData -import org.apache.solr.composeui.components.environment.data.Versions -import org.apache.solr.composeui.ui.components.SolrCard +import org.apache.solr.ui.components.environment.data.JvmData +import org.apache.solr.ui.components.environment.data.Versions +import org.apache.solr.ui.views.components.SolrCard /** * Composable card that displays system values related to versions. diff --git a/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/ui/icons/SolrLogo.kt b/solr/ui/src/commonMain/kotlin/org/apache/solr/ui/views/icons/SolrLogo.kt similarity index 84% rename from solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/ui/icons/SolrLogo.kt rename to solr/ui/src/commonMain/kotlin/org/apache/solr/ui/views/icons/SolrLogo.kt index 06b6af2da7c..a2a540d0e46 100644 --- a/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/ui/icons/SolrLogo.kt +++ b/solr/ui/src/commonMain/kotlin/org/apache/solr/ui/views/icons/SolrLogo.kt @@ -15,16 +15,16 @@ * limitations under the License. */ -package org.apache.solr.composeui.ui.icons +package org.apache.solr.ui.views.icons import androidx.compose.foundation.Image import androidx.compose.foundation.isSystemInDarkTheme import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier -import org.apache.solr.compose_ui.generated.resources.Res -import org.apache.solr.compose_ui.generated.resources.cd_solr_logo -import org.apache.solr.compose_ui.generated.resources.solr_logo_dark -import org.apache.solr.compose_ui.generated.resources.solr_logo_light +import org.apache.solr.ui.generated.resources.Res +import org.apache.solr.ui.generated.resources.cd_solr_logo +import org.apache.solr.ui.generated.resources.solr_logo_dark +import org.apache.solr.ui.generated.resources.solr_logo_light import org.jetbrains.compose.resources.painterResource import org.jetbrains.compose.resources.stringResource diff --git a/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/ui/logging/LoggingContent.kt b/solr/ui/src/commonMain/kotlin/org/apache/solr/ui/views/logging/LoggingContent.kt similarity index 90% rename from solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/ui/logging/LoggingContent.kt rename to solr/ui/src/commonMain/kotlin/org/apache/solr/ui/views/logging/LoggingContent.kt index 0706ff8674f..30cf6e2691a 100644 --- a/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/ui/logging/LoggingContent.kt +++ b/solr/ui/src/commonMain/kotlin/org/apache/solr/ui/views/logging/LoggingContent.kt @@ -15,12 +15,12 @@ * limitations under the License. */ -package org.apache.solr.composeui.ui.logging +package org.apache.solr.ui.views.logging import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier -import org.apache.solr.composeui.components.logging.LoggingComponent +import org.apache.solr.ui.components.logging.LoggingComponent @Composable fun LoggingContent( diff --git a/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/ui/main/MainContent.kt b/solr/ui/src/commonMain/kotlin/org/apache/solr/ui/views/main/MainContent.kt similarity index 88% rename from solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/ui/main/MainContent.kt rename to solr/ui/src/commonMain/kotlin/org/apache/solr/ui/views/main/MainContent.kt index bb9f373bc8a..f0796ff4701 100644 --- a/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/ui/main/MainContent.kt +++ b/solr/ui/src/commonMain/kotlin/org/apache/solr/ui/views/main/MainContent.kt @@ -15,7 +15,7 @@ * limitations under the License. */ -package org.apache.solr.composeui.ui.main +package org.apache.solr.ui.views.main import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.fillMaxHeight @@ -30,11 +30,11 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.unit.dp import com.arkivanov.decompose.extensions.compose.stack.Children import com.arkivanov.decompose.extensions.compose.subscribeAsState -import org.apache.solr.composeui.components.main.MainComponent -import org.apache.solr.composeui.components.main.integration.asMainMenu -import org.apache.solr.composeui.ui.environment.EnvironmentContent -import org.apache.solr.composeui.ui.logging.LoggingContent -import org.apache.solr.composeui.ui.navigation.NavigationSideBar +import org.apache.solr.ui.components.main.MainComponent +import org.apache.solr.ui.components.main.integration.asMainMenu +import org.apache.solr.ui.views.environment.EnvironmentContent +import org.apache.solr.ui.views.logging.LoggingContent +import org.apache.solr.ui.views.navigation.NavigationSideBar /** * The composable used for users that have already authenticated. diff --git a/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/ui/navigation/Footer.kt b/solr/ui/src/commonMain/kotlin/org/apache/solr/ui/views/navigation/Footer.kt similarity index 89% rename from solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/ui/navigation/Footer.kt rename to solr/ui/src/commonMain/kotlin/org/apache/solr/ui/views/navigation/Footer.kt index bcaf6cfe6fa..a3333cb228f 100644 --- a/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/ui/navigation/Footer.kt +++ b/solr/ui/src/commonMain/kotlin/org/apache/solr/ui/views/navigation/Footer.kt @@ -15,7 +15,7 @@ * limitations under the License. */ -package org.apache.solr.composeui.ui.navigation +package org.apache.solr.ui.views.navigation import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Arrangement @@ -46,14 +46,14 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.vector.ImageVector import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.dp -import org.apache.solr.compose_ui.generated.resources.Res -import org.apache.solr.compose_ui.generated.resources.community -import org.apache.solr.compose_ui.generated.resources.documentation -import org.apache.solr.compose_ui.generated.resources.irc -import org.apache.solr.compose_ui.generated.resources.issue_tracker -import org.apache.solr.compose_ui.generated.resources.slack -import org.apache.solr.compose_ui.generated.resources.solr_query_syntax -import org.apache.solr.compose_ui.generated.resources.support +import org.apache.solr.ui.generated.resources.Res +import org.apache.solr.ui.generated.resources.community +import org.apache.solr.ui.generated.resources.documentation +import org.apache.solr.ui.generated.resources.irc +import org.apache.solr.ui.generated.resources.issue_tracker +import org.apache.solr.ui.generated.resources.slack +import org.apache.solr.ui.generated.resources.solr_query_syntax +import org.apache.solr.ui.generated.resources.support import org.jetbrains.compose.resources.StringResource import org.jetbrains.compose.resources.stringResource diff --git a/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/ui/navigation/MainMenu.kt b/solr/ui/src/commonMain/kotlin/org/apache/solr/ui/views/navigation/MainMenu.kt similarity index 96% rename from solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/ui/navigation/MainMenu.kt rename to solr/ui/src/commonMain/kotlin/org/apache/solr/ui/views/navigation/MainMenu.kt index 704790a23fa..91a11d2161a 100644 --- a/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/ui/navigation/MainMenu.kt +++ b/solr/ui/src/commonMain/kotlin/org/apache/solr/ui/views/navigation/MainMenu.kt @@ -15,7 +15,7 @@ * limitations under the License. */ -package org.apache.solr.composeui.ui.navigation +package org.apache.solr.ui.views.navigation /** * An enum class that holds all the menu items of the main navigation. diff --git a/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/ui/navigation/NavigationSideBar.kt b/solr/ui/src/commonMain/kotlin/org/apache/solr/ui/views/navigation/NavigationSideBar.kt similarity index 88% rename from solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/ui/navigation/NavigationSideBar.kt rename to solr/ui/src/commonMain/kotlin/org/apache/solr/ui/views/navigation/NavigationSideBar.kt index c244199d576..a51e859296e 100644 --- a/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/ui/navigation/NavigationSideBar.kt +++ b/solr/ui/src/commonMain/kotlin/org/apache/solr/ui/views/navigation/NavigationSideBar.kt @@ -15,7 +15,7 @@ * limitations under the License. */ -package org.apache.solr.composeui.ui.navigation +package org.apache.solr.ui.views.navigation import androidx.compose.foundation.background import androidx.compose.foundation.layout.Arrangement @@ -49,19 +49,19 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.vector.ImageVector import androidx.compose.ui.unit.dp -import org.apache.solr.compose_ui.generated.resources.Res -import org.apache.solr.compose_ui.generated.resources.logout -import org.apache.solr.compose_ui.generated.resources.nav_cluster -import org.apache.solr.compose_ui.generated.resources.nav_collections -import org.apache.solr.compose_ui.generated.resources.nav_configsets -import org.apache.solr.compose_ui.generated.resources.nav_dashboard -import org.apache.solr.compose_ui.generated.resources.nav_environment -import org.apache.solr.compose_ui.generated.resources.nav_logging -import org.apache.solr.compose_ui.generated.resources.nav_metrics -import org.apache.solr.compose_ui.generated.resources.nav_queries_and_operations -import org.apache.solr.compose_ui.generated.resources.nav_security -import org.apache.solr.compose_ui.generated.resources.nav_thread_dump -import org.apache.solr.composeui.ui.icons.SolrLogo +import org.apache.solr.ui.generated.resources.Res +import org.apache.solr.ui.generated.resources.logout +import org.apache.solr.ui.generated.resources.nav_cluster +import org.apache.solr.ui.generated.resources.nav_collections +import org.apache.solr.ui.generated.resources.nav_configsets +import org.apache.solr.ui.generated.resources.nav_dashboard +import org.apache.solr.ui.generated.resources.nav_environment +import org.apache.solr.ui.generated.resources.nav_logging +import org.apache.solr.ui.generated.resources.nav_metrics +import org.apache.solr.ui.generated.resources.nav_queries_and_operations +import org.apache.solr.ui.generated.resources.nav_security +import org.apache.solr.ui.generated.resources.nav_thread_dump +import org.apache.solr.ui.views.icons.SolrLogo import org.jetbrains.compose.resources.stringResource /** diff --git a/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/ui/root/RootContent.kt b/solr/ui/src/commonMain/kotlin/org/apache/solr/ui/views/root/RootContent.kt similarity index 89% rename from solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/ui/root/RootContent.kt rename to solr/ui/src/commonMain/kotlin/org/apache/solr/ui/views/root/RootContent.kt index 1fc6c7ff5d6..b30c4d5a267 100644 --- a/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/ui/root/RootContent.kt +++ b/solr/ui/src/commonMain/kotlin/org/apache/solr/ui/views/root/RootContent.kt @@ -15,7 +15,7 @@ * limitations under the License. */ -package org.apache.solr.composeui.ui.root +package org.apache.solr.ui.views.root import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.fillMaxSize @@ -23,9 +23,9 @@ import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import com.arkivanov.decompose.extensions.compose.stack.Children -import org.apache.solr.composeui.components.root.RootComponent -import org.apache.solr.composeui.ui.main.MainContent -import org.apache.solr.composeui.ui.navigation.Footer +import org.apache.solr.ui.components.root.RootComponent +import org.apache.solr.ui.views.main.MainContent +import org.apache.solr.ui.views.navigation.Footer /** * The root composable of the Compose application. This function is used as the shared entry diff --git a/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/ui/theme/ColorFamily.kt b/solr/ui/src/commonMain/kotlin/org/apache/solr/ui/views/theme/ColorFamily.kt similarity index 96% rename from solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/ui/theme/ColorFamily.kt rename to solr/ui/src/commonMain/kotlin/org/apache/solr/ui/views/theme/ColorFamily.kt index 1d67d153a29..49a29431f90 100644 --- a/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/ui/theme/ColorFamily.kt +++ b/solr/ui/src/commonMain/kotlin/org/apache/solr/ui/views/theme/ColorFamily.kt @@ -15,7 +15,7 @@ * limitations under the License. */ -package org.apache.solr.composeui.ui.theme +package org.apache.solr.ui.views.theme import androidx.compose.runtime.Immutable import androidx.compose.ui.graphics.Color diff --git a/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/ui/theme/Colors.kt b/solr/ui/src/commonMain/kotlin/org/apache/solr/ui/views/theme/Colors.kt similarity index 99% rename from solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/ui/theme/Colors.kt rename to solr/ui/src/commonMain/kotlin/org/apache/solr/ui/views/theme/Colors.kt index 19c866bae12..af76f577884 100644 --- a/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/ui/theme/Colors.kt +++ b/solr/ui/src/commonMain/kotlin/org/apache/solr/ui/views/theme/Colors.kt @@ -15,7 +15,7 @@ * limitations under the License. */ -package org.apache.solr.composeui.ui.theme +package org.apache.solr.ui.views.theme import androidx.compose.material3.ColorScheme import androidx.compose.material3.darkColorScheme diff --git a/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/ui/theme/Shapes.kt b/solr/ui/src/commonMain/kotlin/org/apache/solr/ui/views/theme/Shapes.kt similarity index 97% rename from solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/ui/theme/Shapes.kt rename to solr/ui/src/commonMain/kotlin/org/apache/solr/ui/views/theme/Shapes.kt index 2fe628b2ce0..0f6557739bf 100644 --- a/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/ui/theme/Shapes.kt +++ b/solr/ui/src/commonMain/kotlin/org/apache/solr/ui/views/theme/Shapes.kt @@ -15,7 +15,7 @@ * limitations under the License. */ -package org.apache.solr.composeui.ui.theme +package org.apache.solr.ui.views.theme import androidx.compose.foundation.shape.CutCornerShape import androidx.compose.material3.Shapes diff --git a/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/ui/theme/Theme.kt b/solr/ui/src/commonMain/kotlin/org/apache/solr/ui/views/theme/Theme.kt similarity index 98% rename from solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/ui/theme/Theme.kt rename to solr/ui/src/commonMain/kotlin/org/apache/solr/ui/views/theme/Theme.kt index 751190f0468..04c5fa9804a 100644 --- a/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/ui/theme/Theme.kt +++ b/solr/ui/src/commonMain/kotlin/org/apache/solr/ui/views/theme/Theme.kt @@ -15,7 +15,7 @@ * limitations under the License. */ -package org.apache.solr.composeui.ui.theme +package org.apache.solr.ui.views.theme import androidx.compose.foundation.isSystemInDarkTheme import androidx.compose.material3.MaterialTheme diff --git a/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/ui/theme/Typography.kt b/solr/ui/src/commonMain/kotlin/org/apache/solr/ui/views/theme/Typography.kt similarity index 99% rename from solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/ui/theme/Typography.kt rename to solr/ui/src/commonMain/kotlin/org/apache/solr/ui/views/theme/Typography.kt index 8c49b80c270..a1bccf0127b 100644 --- a/solr/compose-ui/src/commonMain/kotlin/org/apache/solr/composeui/ui/theme/Typography.kt +++ b/solr/ui/src/commonMain/kotlin/org/apache/solr/ui/views/theme/Typography.kt @@ -15,7 +15,7 @@ * limitations under the License. */ -package org.apache.solr.composeui.ui.theme +package org.apache.solr.ui.views.theme import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Typography diff --git a/solr/compose-ui/src/commonTest/kotlin/org/apache/solr/composeui/components/environment/store/EnvironmentStoreProviderTest.kt b/solr/ui/src/commonTest/kotlin/org/apache/solr/ui/components/environment/store/EnvironmentStoreProviderTest.kt similarity index 96% rename from solr/compose-ui/src/commonTest/kotlin/org/apache/solr/composeui/components/environment/store/EnvironmentStoreProviderTest.kt rename to solr/ui/src/commonTest/kotlin/org/apache/solr/ui/components/environment/store/EnvironmentStoreProviderTest.kt index ffa8b5a7f43..45fa54180c2 100644 --- a/solr/compose-ui/src/commonTest/kotlin/org/apache/solr/composeui/components/environment/store/EnvironmentStoreProviderTest.kt +++ b/solr/ui/src/commonTest/kotlin/org/apache/solr/ui/components/environment/store/EnvironmentStoreProviderTest.kt @@ -15,7 +15,7 @@ * limitations under the License. */ -package org.apache.solr.composeui.components.environment.store +package org.apache.solr.ui.components.environment.store import com.arkivanov.mvikotlin.extensions.coroutines.stateFlow import com.arkivanov.mvikotlin.main.store.DefaultStoreFactory @@ -24,7 +24,7 @@ import kotlin.time.Duration.Companion.seconds import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.flow.first import kotlinx.coroutines.test.runTest -import org.apache.solr.composeui.components.environment.data.SystemData +import org.apache.solr.ui.components.environment.data.SystemData @OptIn(ExperimentalCoroutinesApi::class) class EnvironmentStoreProviderTest { diff --git a/solr/compose-ui/src/commonTest/kotlin/org/apache/solr/composeui/components/environment/store/MockedEnvironmentStoreClient.kt b/solr/ui/src/commonTest/kotlin/org/apache/solr/ui/components/environment/store/MockedEnvironmentStoreClient.kt similarity index 85% rename from solr/compose-ui/src/commonTest/kotlin/org/apache/solr/composeui/components/environment/store/MockedEnvironmentStoreClient.kt rename to solr/ui/src/commonTest/kotlin/org/apache/solr/ui/components/environment/store/MockedEnvironmentStoreClient.kt index a9014cd2cc0..5f21a885c8f 100644 --- a/solr/compose-ui/src/commonTest/kotlin/org/apache/solr/composeui/components/environment/store/MockedEnvironmentStoreClient.kt +++ b/solr/ui/src/commonTest/kotlin/org/apache/solr/ui/components/environment/store/MockedEnvironmentStoreClient.kt @@ -15,10 +15,10 @@ * limitations under the License. */ -package org.apache.solr.composeui.components.environment.store +package org.apache.solr.ui.components.environment.store -import org.apache.solr.composeui.components.environment.data.JavaProperty -import org.apache.solr.composeui.components.environment.data.SystemData +import org.apache.solr.ui.components.environment.data.JavaProperty +import org.apache.solr.ui.components.environment.data.SystemData class MockedEnvironmentStoreClient( private val onGetSystemData: () -> Result, diff --git a/solr/compose-ui/src/commonTest/kotlin/org/apache/solr/composeui/ui/components/SolrCardTest.kt b/solr/ui/src/commonTest/kotlin/org/apache/solr/ui/ui/components/SolrCardTest.kt similarity index 97% rename from solr/compose-ui/src/commonTest/kotlin/org/apache/solr/composeui/ui/components/SolrCardTest.kt rename to solr/ui/src/commonTest/kotlin/org/apache/solr/ui/ui/components/SolrCardTest.kt index baca0c6abb2..044496cfb78 100644 --- a/solr/compose-ui/src/commonTest/kotlin/org/apache/solr/composeui/ui/components/SolrCardTest.kt +++ b/solr/ui/src/commonTest/kotlin/org/apache/solr/ui/ui/components/SolrCardTest.kt @@ -15,7 +15,7 @@ * limitations under the License. */ -package org.apache.solr.composeui.ui.components +package org.apache.solr.ui.views.components import androidx.compose.material3.Text import androidx.compose.ui.Modifier diff --git a/solr/compose-ui/src/commonTest/kotlin/org/apache/solr/composeui/ui/environment/EnvironmentContentTest.kt b/solr/ui/src/commonTest/kotlin/org/apache/solr/ui/ui/environment/EnvironmentContentTest.kt similarity index 91% rename from solr/compose-ui/src/commonTest/kotlin/org/apache/solr/composeui/ui/environment/EnvironmentContentTest.kt rename to solr/ui/src/commonTest/kotlin/org/apache/solr/ui/ui/environment/EnvironmentContentTest.kt index 58afa8cece9..8a017113c50 100644 --- a/solr/compose-ui/src/commonTest/kotlin/org/apache/solr/composeui/ui/environment/EnvironmentContentTest.kt +++ b/solr/ui/src/commonTest/kotlin/org/apache/solr/ui/ui/environment/EnvironmentContentTest.kt @@ -15,7 +15,7 @@ * limitations under the License. */ -package org.apache.solr.composeui.ui.environment +package org.apache.solr.ui.views.environment import androidx.compose.ui.test.ExperimentalTestApi import androidx.compose.ui.test.onNodeWithText @@ -23,8 +23,8 @@ import androidx.compose.ui.test.runComposeUiTest import kotlin.test.Test import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.StateFlow -import org.apache.solr.composeui.components.environment.EnvironmentComponent -import org.apache.solr.composeui.components.environment.data.Versions +import org.apache.solr.ui.components.environment.EnvironmentComponent +import org.apache.solr.ui.components.environment.data.Versions class EnvironmentContentTest { diff --git a/solr/compose-ui/src/desktopMain/kotlin/org/apache/solr/composeui/Main.kt b/solr/ui/src/desktopMain/kotlin/org/apache/solr/ui/Main.kt similarity index 88% rename from solr/compose-ui/src/desktopMain/kotlin/org/apache/solr/composeui/Main.kt rename to solr/ui/src/desktopMain/kotlin/org/apache/solr/ui/Main.kt index dc1d2382d63..fa8449bd325 100644 --- a/solr/compose-ui/src/desktopMain/kotlin/org/apache/solr/composeui/Main.kt +++ b/solr/ui/src/desktopMain/kotlin/org/apache/solr/ui/Main.kt @@ -15,7 +15,7 @@ * limitations under the License. */ -package org.apache.solr.composeui +package org.apache.solr.ui import androidx.compose.foundation.isSystemInDarkTheme import androidx.compose.foundation.layout.fillMaxSize @@ -31,12 +31,12 @@ import com.arkivanov.mvikotlin.core.utils.setMainThreadId import com.arkivanov.mvikotlin.main.store.DefaultStoreFactory import java.awt.Dimension import kotlinx.coroutines.Dispatchers -import org.apache.solr.composeui.components.root.RootComponent -import org.apache.solr.composeui.components.root.integration.SimpleRootComponent -import org.apache.solr.composeui.ui.root.RootContent -import org.apache.solr.composeui.ui.theme.SolrTheme -import org.apache.solr.composeui.utils.DefaultAppComponentContext -import org.apache.solr.composeui.utils.getDefaultClient +import org.apache.solr.ui.components.root.RootComponent +import org.apache.solr.ui.components.root.integration.SimpleRootComponent +import org.apache.solr.ui.views.root.RootContent +import org.apache.solr.ui.views.theme.SolrTheme +import org.apache.solr.ui.utils.DefaultAppComponentContext +import org.apache.solr.ui.utils.getDefaultClient /** * Entry point of the Compose application for all JVM-based (desktop) targets. diff --git a/solr/compose-ui/src/desktopMain/kotlin/org/apache/solr/composeui/Utils.kt b/solr/ui/src/desktopMain/kotlin/org/apache/solr/ui/Utils.kt similarity index 97% rename from solr/compose-ui/src/desktopMain/kotlin/org/apache/solr/composeui/Utils.kt rename to solr/ui/src/desktopMain/kotlin/org/apache/solr/ui/Utils.kt index 4f351f201bf..5e8d1193f32 100644 --- a/solr/compose-ui/src/desktopMain/kotlin/org/apache/solr/composeui/Utils.kt +++ b/solr/ui/src/desktopMain/kotlin/org/apache/solr/ui/Utils.kt @@ -15,7 +15,7 @@ * limitations under the License. */ -package org.apache.solr.composeui +package org.apache.solr.ui import javax.swing.SwingUtilities diff --git a/solr/compose-ui/src/desktopMain/kotlin/org/apache/solr/composeui/preview/PreviewContainer.kt b/solr/ui/src/desktopMain/kotlin/org/apache/solr/ui/preview/PreviewContainer.kt similarity index 93% rename from solr/compose-ui/src/desktopMain/kotlin/org/apache/solr/composeui/preview/PreviewContainer.kt rename to solr/ui/src/desktopMain/kotlin/org/apache/solr/ui/preview/PreviewContainer.kt index 36266ec2871..ff54a61c919 100644 --- a/solr/compose-ui/src/desktopMain/kotlin/org/apache/solr/composeui/preview/PreviewContainer.kt +++ b/solr/ui/src/desktopMain/kotlin/org/apache/solr/ui/preview/PreviewContainer.kt @@ -15,7 +15,7 @@ * limitations under the License. */ -package org.apache.solr.composeui.preview +package org.apache.solr.ui.preview import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.padding @@ -23,7 +23,7 @@ import androidx.compose.material3.Surface import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import androidx.compose.ui.unit.dp -import org.apache.solr.composeui.ui.theme.SolrTheme +import org.apache.solr.ui.views.theme.SolrTheme /** * This preview container can be used for applying the basic app theme on existing components. diff --git a/solr/compose-ui/src/desktopMain/kotlin/org/apache/solr/composeui/preview/navigation/PreviewNavigationSideBar.kt b/solr/ui/src/desktopMain/kotlin/org/apache/solr/ui/preview/navigation/PreviewNavigationSideBar.kt similarity index 85% rename from solr/compose-ui/src/desktopMain/kotlin/org/apache/solr/composeui/preview/navigation/PreviewNavigationSideBar.kt rename to solr/ui/src/desktopMain/kotlin/org/apache/solr/ui/preview/navigation/PreviewNavigationSideBar.kt index 24084f0379a..d3a00fc9ebe 100644 --- a/solr/compose-ui/src/desktopMain/kotlin/org/apache/solr/composeui/preview/navigation/PreviewNavigationSideBar.kt +++ b/solr/ui/src/desktopMain/kotlin/org/apache/solr/ui/preview/navigation/PreviewNavigationSideBar.kt @@ -15,12 +15,12 @@ * limitations under the License. */ -package org.apache.solr.composeui.preview.navigation +package org.apache.solr.ui.preview.navigation import androidx.compose.desktop.ui.tooling.preview.Preview import androidx.compose.runtime.Composable -import org.apache.solr.composeui.preview.PreviewContainer -import org.apache.solr.composeui.ui.navigation.NavigationSideBar +import org.apache.solr.ui.preview.PreviewContainer +import org.apache.solr.ui.views.navigation.NavigationSideBar @Preview @Composable diff --git a/solr/compose-ui/src/wasmJsMain/kotlin/org/apache/solr/composeui/Main.kt b/solr/ui/src/wasmJsMain/kotlin/org/apache/solr/ui/Main.kt similarity index 86% rename from solr/compose-ui/src/wasmJsMain/kotlin/org/apache/solr/composeui/Main.kt rename to solr/ui/src/wasmJsMain/kotlin/org/apache/solr/ui/Main.kt index 8c537707f3d..2bb836c657e 100644 --- a/solr/compose-ui/src/wasmJsMain/kotlin/org/apache/solr/composeui/Main.kt +++ b/solr/ui/src/wasmJsMain/kotlin/org/apache/solr/ui/Main.kt @@ -15,7 +15,7 @@ * limitations under the License. */ -package org.apache.solr.composeui +package org.apache.solr.ui import androidx.compose.foundation.isSystemInDarkTheme import androidx.compose.foundation.layout.fillMaxSize @@ -30,12 +30,12 @@ import io.ktor.http.Url import kotlinx.browser.document import kotlinx.browser.window import kotlinx.coroutines.Dispatchers -import org.apache.solr.composeui.components.root.RootComponent -import org.apache.solr.composeui.components.root.integration.SimpleRootComponent -import org.apache.solr.composeui.ui.root.RootContent -import org.apache.solr.composeui.ui.theme.SolrTheme -import org.apache.solr.composeui.utils.DefaultAppComponentContext -import org.apache.solr.composeui.utils.getDefaultClient +import org.apache.solr.ui.components.root.RootComponent +import org.apache.solr.ui.components.root.integration.SimpleRootComponent +import org.apache.solr.ui.views.root.RootContent +import org.apache.solr.ui.views.theme.SolrTheme +import org.apache.solr.ui.utils.DefaultAppComponentContext +import org.apache.solr.ui.utils.getDefaultClient /** * Entry point of the Compose application for all wasmJs (browser) targets. diff --git a/solr/compose-ui/src/wasmJsMain/resources/index.html b/solr/ui/src/wasmJsMain/resources/index.html similarity index 100% rename from solr/compose-ui/src/wasmJsMain/resources/index.html rename to solr/ui/src/wasmJsMain/resources/index.html diff --git a/solr/compose-ui/src/wasmJsMain/resources/styles.css b/solr/ui/src/wasmJsMain/resources/styles.css similarity index 100% rename from solr/compose-ui/src/wasmJsMain/resources/styles.css rename to solr/ui/src/wasmJsMain/resources/styles.css diff --git a/solr/compose-ui/webpack.config.d/adjust-limits.js b/solr/ui/webpack.config.d/adjust-limits.js similarity index 100% rename from solr/compose-ui/webpack.config.d/adjust-limits.js rename to solr/ui/webpack.config.d/adjust-limits.js diff --git a/solr/webapp/build.gradle b/solr/webapp/build.gradle index 1da248f9cbe..b4d6b3df56b 100644 --- a/solr/webapp/build.gradle +++ b/solr/webapp/build.gradle @@ -94,22 +94,22 @@ task downloadBrowserify(type: NpmTask) { outputs.dir("${nodeProjectDir}/node_modules/browserify") } -tasks.register("generateComposeUiDevFiles") { +tasks.register("generateUiDevFiles") { description = "Generate new UI for development and add files to outputs for later referencing." group = "build" // Development files are larger in size but have shorter compile times. - dependsOn project(":solr:compose-ui").tasks.wasmJsBrowserDevelopmentExecutableDistribution - outputs.dir(project(":solr:compose-ui").file("build/dist/wasmJs/developmentExecutable/")) + dependsOn project(":solr:ui").tasks.wasmJsBrowserDevelopmentExecutableDistribution + outputs.dir(project(":solr:ui").file("build/dist/wasmJs/developmentExecutable/")) } -tasks.register("generateComposeUiProdFiles") { +tasks.register("generateUiProdFiles") { description = "Generate new UI for production and add files to outputs for later referencing" group = "build" // Production files are smaller in size but have longer compile times. - dependsOn project(":solr:compose-ui").tasks.wasmJsBrowserDistribution - outputs.dir(project(":solr:compose-ui").file("build/dist/wasmJs/productionExecutable/")) + dependsOn project(":solr:ui").tasks.wasmJsBrowserDistribution + outputs.dir(project(":solr:ui").file("build/dist/wasmJs/productionExecutable/")) } task generateJsClientBundle(type: NpxTask) { @@ -160,12 +160,12 @@ war { // Include new Admin UI files in webapp // By default, we always build dev that does not optimize generated files for release to reduce build times. if (rootProject.ext.development) { - from (tasks.generateComposeUiDevFiles) { - into "compose" + from (tasks.generateUiDevFiles) { + into "ui" } } else { - from (tasks.generateComposeUiProdFiles) { - into "compose" + from (tasks.generateUiProdFiles) { + into "ui" } } } diff --git a/solr/webapp/web/index.html b/solr/webapp/web/index.html index 29ec87ac764..7e692e0efcd 100644 --- a/solr/webapp/web/index.html +++ b/solr/webapp/web/index.html @@ -194,7 +194,7 @@

    Connection recovered...

  • Thread Dump

  • -
  • Open New UI

  • +
  • Open New UI

diff --git a/solr/webapp/web/js/angular/app.js b/solr/webapp/web/js/angular/app.js index 57814595145..abdd53f0c59 100644 --- a/solr/webapp/web/js/angular/app.js +++ b/solr/webapp/web/js/angular/app.js @@ -67,8 +67,8 @@ solrAdminApp.config([ templateUrl: 'partials/index.html', controller: 'IndexController' }). - when('/compose', { - redirectTo: 'compose/index.html' + when('/ui', { + redirectTo: 'ui/index.html' }). when('/unknown', { templateUrl: 'partials/unknown.html',