Initial commit
This commit is contained in:
commit
2550140811
94 files changed
+10844
No files matched your search
+41
@@ -0,0 +1,41 @@
|
||||
HELP.md
|
||||
.gradle
|
||||
build/
|
||||
!gradle/wrapper/gradle-wrapper.jar
|
||||
!**/src/main/**/build/
|
||||
!**/src/test/**/build/
|
||||
|
||||
### STS ###
|
||||
.apt_generated
|
||||
.classpath
|
||||
.factorypath
|
||||
.project
|
||||
.settings
|
||||
.springBeans
|
||||
.sts4-cache
|
||||
bin/
|
||||
!**/src/main/**/bin/
|
||||
!**/src/test/**/bin/
|
||||
|
||||
### IntelliJ IDEA ###
|
||||
.idea
|
||||
*.iws
|
||||
*.iml
|
||||
*.ipr
|
||||
out/
|
||||
!**/src/main/**/out/
|
||||
!**/src/test/**/out/
|
||||
|
||||
### NetBeans ###
|
||||
/nbproject/private/
|
||||
/nbbuild/
|
||||
/dist/
|
||||
/nbdist/
|
||||
/.nb-gradle/
|
||||
|
||||
### VS Code ###
|
||||
.vscode/
|
||||
|
||||
### Kotlin ###
|
||||
.kotlin
|
||||
.env*
|
||||
@@ -0,0 +1,67 @@
|
||||
plugins {
|
||||
id("org.springframework.boot") version "3.3.0"
|
||||
id("io.spring.dependency-management") version "1.1.5"
|
||||
kotlin("plugin.jpa") version "1.9.24"
|
||||
kotlin("jvm") version "1.9.24"
|
||||
kotlin("plugin.spring") version "1.9.24"
|
||||
kotlin("plugin.allopen") version "1.9.22"
|
||||
}
|
||||
|
||||
group = "at.eisibaer"
|
||||
version = "0.0.1-SNAPSHOT"
|
||||
|
||||
java {
|
||||
toolchain {
|
||||
languageVersion = JavaLanguageVersion.of(21)
|
||||
}
|
||||
}
|
||||
|
||||
configurations {
|
||||
compileOnly {
|
||||
extendsFrom(configurations.annotationProcessor.get())
|
||||
}
|
||||
}
|
||||
|
||||
repositories {
|
||||
mavenCentral()
|
||||
}
|
||||
|
||||
val jjwtVersion: String = "0.12.6";
|
||||
val bcVersion: String = "1.78.1";
|
||||
|
||||
dependencies {
|
||||
implementation("org.springframework.boot:spring-boot-starter-data-jpa")
|
||||
implementation("org.springframework.boot:spring-boot-starter-security")
|
||||
implementation("org.springframework.boot:spring-boot-starter-web")
|
||||
implementation("org.springframework.boot:spring-boot-starter-websocket")
|
||||
implementation("com.fasterxml.jackson.module:jackson-module-kotlin")
|
||||
implementation("org.jetbrains.kotlin:kotlin-reflect")
|
||||
implementation("io.jsonwebtoken:jjwt-api:$jjwtVersion")
|
||||
implementation("org.bouncycastle:bcprov-jdk18on:$bcVersion")
|
||||
compileOnly("org.projectlombok:lombok")
|
||||
developmentOnly("org.springframework.boot:spring-boot-devtools")
|
||||
runtimeOnly("org.postgresql:postgresql")
|
||||
runtimeOnly("io.jsonwebtoken:jjwt-impl:$jjwtVersion")
|
||||
runtimeOnly("io.jsonwebtoken:jjwt-jackson:$jjwtVersion")
|
||||
annotationProcessor("org.projectlombok:lombok")
|
||||
testImplementation("org.springframework.boot:spring-boot-starter-test")
|
||||
testImplementation("org.jetbrains.kotlin:kotlin-test-junit5")
|
||||
testImplementation("org.springframework.security:spring-security-test")
|
||||
testRuntimeOnly("org.junit.platform:junit-platform-launcher")
|
||||
}
|
||||
|
||||
kotlin {
|
||||
compilerOptions {
|
||||
freeCompilerArgs.addAll("-Xjsr305=strict")
|
||||
}
|
||||
}
|
||||
|
||||
tasks.withType<Test> {
|
||||
useJUnitPlatform()
|
||||
}
|
||||
|
||||
allOpen {
|
||||
annotation("jakarta.persistence.Entity")
|
||||
annotation("jakarta.persistence.Embeddable")
|
||||
annotation("jakarta.persistence.MappedSuperclass")
|
||||
}
|
||||
Vendored
BIN
Binary file not shown.
+7
@@ -0,0 +1,7 @@
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.8-bin.zip
|
||||
networkTimeout=10000
|
||||
validateDistributionUrl=true
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
@@ -0,0 +1,249 @@
|
||||
#!/bin/sh
|
||||
|
||||
#
|
||||
# Copyright © 2015-2021 the original authors.
|
||||
#
|
||||
# Licensed 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
|
||||
#
|
||||
# https://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.
|
||||
#
|
||||
|
||||
##############################################################################
|
||||
#
|
||||
# Gradle start up script for POSIX generated by Gradle.
|
||||
#
|
||||
# Important for running:
|
||||
#
|
||||
# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is
|
||||
# noncompliant, but you have some other compliant shell such as ksh or
|
||||
# bash, then to run this script, type that shell name before the whole
|
||||
# command line, like:
|
||||
#
|
||||
# ksh Gradle
|
||||
#
|
||||
# Busybox and similar reduced shells will NOT work, because this script
|
||||
# requires all of these POSIX shell features:
|
||||
# * functions;
|
||||
# * expansions «$var», «${var}», «${var:-default}», «${var+SET}»,
|
||||
# «${var#prefix}», «${var%suffix}», and «$( cmd )»;
|
||||
# * compound commands having a testable exit status, especially «case»;
|
||||
# * various built-in commands including «command», «set», and «ulimit».
|
||||
#
|
||||
# Important for patching:
|
||||
#
|
||||
# (2) This script targets any POSIX shell, so it avoids extensions provided
|
||||
# by Bash, Ksh, etc; in particular arrays are avoided.
|
||||
#
|
||||
# The "traditional" practice of packing multiple parameters into a
|
||||
# space-separated string is a well documented source of bugs and security
|
||||
# problems, so this is (mostly) avoided, by progressively accumulating
|
||||
# options in "$@", and eventually passing that to Java.
|
||||
#
|
||||
# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS,
|
||||
# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly;
|
||||
# see the in-line comments for details.
|
||||
#
|
||||
# There are tweaks for specific operating systems such as AIX, CygWin,
|
||||
# Darwin, MinGW, and NonStop.
|
||||
#
|
||||
# (3) This script is generated from the Groovy template
|
||||
# https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
|
||||
# within the Gradle project.
|
||||
#
|
||||
# You can find Gradle at https://github.com/gradle/gradle/.
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
# Attempt to set APP_HOME
|
||||
|
||||
# Resolve links: $0 may be a link
|
||||
app_path=$0
|
||||
|
||||
# Need this for daisy-chained symlinks.
|
||||
while
|
||||
APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path
|
||||
[ -h "$app_path" ]
|
||||
do
|
||||
ls=$( ls -ld "$app_path" )
|
||||
link=${ls#*' -> '}
|
||||
case $link in #(
|
||||
/*) app_path=$link ;; #(
|
||||
*) app_path=$APP_HOME$link ;;
|
||||
esac
|
||||
done
|
||||
|
||||
# This is normally unused
|
||||
# shellcheck disable=SC2034
|
||||
APP_BASE_NAME=${0##*/}
|
||||
# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036)
|
||||
APP_HOME=$( cd "${APP_HOME:-./}" > /dev/null && pwd -P ) || exit
|
||||
|
||||
# Use the maximum available, or set MAX_FD != -1 to use that value.
|
||||
MAX_FD=maximum
|
||||
|
||||
warn () {
|
||||
echo "$*"
|
||||
} >&2
|
||||
|
||||
die () {
|
||||
echo
|
||||
echo "$*"
|
||||
echo
|
||||
exit 1
|
||||
} >&2
|
||||
|
||||
# OS specific support (must be 'true' or 'false').
|
||||
cygwin=false
|
||||
msys=false
|
||||
darwin=false
|
||||
nonstop=false
|
||||
case "$( uname )" in #(
|
||||
CYGWIN* ) cygwin=true ;; #(
|
||||
Darwin* ) darwin=true ;; #(
|
||||
MSYS* | MINGW* ) msys=true ;; #(
|
||||
NONSTOP* ) nonstop=true ;;
|
||||
esac
|
||||
|
||||
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
|
||||
|
||||
|
||||
# Determine the Java command to use to start the JVM.
|
||||
if [ -n "$JAVA_HOME" ] ; then
|
||||
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
|
||||
# IBM's JDK on AIX uses strange locations for the executables
|
||||
JAVACMD=$JAVA_HOME/jre/sh/java
|
||||
else
|
||||
JAVACMD=$JAVA_HOME/bin/java
|
||||
fi
|
||||
if [ ! -x "$JAVACMD" ] ; then
|
||||
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
|
||||
|
||||
Please set the JAVA_HOME variable in your environment to match the
|
||||
location of your Java installation."
|
||||
fi
|
||||
else
|
||||
JAVACMD=java
|
||||
if ! command -v java >/dev/null 2>&1
|
||||
then
|
||||
die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||
|
||||
Please set the JAVA_HOME variable in your environment to match the
|
||||
location of your Java installation."
|
||||
fi
|
||||
fi
|
||||
|
||||
# Increase the maximum file descriptors if we can.
|
||||
if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
|
||||
case $MAX_FD in #(
|
||||
max*)
|
||||
# In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked.
|
||||
# shellcheck disable=SC2039,SC3045
|
||||
MAX_FD=$( ulimit -H -n ) ||
|
||||
warn "Could not query maximum file descriptor limit"
|
||||
esac
|
||||
case $MAX_FD in #(
|
||||
'' | soft) :;; #(
|
||||
*)
|
||||
# In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked.
|
||||
# shellcheck disable=SC2039,SC3045
|
||||
ulimit -n "$MAX_FD" ||
|
||||
warn "Could not set maximum file descriptor limit to $MAX_FD"
|
||||
esac
|
||||
fi
|
||||
|
||||
# Collect all arguments for the java command, stacking in reverse order:
|
||||
# * args from the command line
|
||||
# * the main class name
|
||||
# * -classpath
|
||||
# * -D...appname settings
|
||||
# * --module-path (only if needed)
|
||||
# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables.
|
||||
|
||||
# For Cygwin or MSYS, switch paths to Windows format before running java
|
||||
if "$cygwin" || "$msys" ; then
|
||||
APP_HOME=$( cygpath --path --mixed "$APP_HOME" )
|
||||
CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" )
|
||||
|
||||
JAVACMD=$( cygpath --unix "$JAVACMD" )
|
||||
|
||||
# Now convert the arguments - kludge to limit ourselves to /bin/sh
|
||||
for arg do
|
||||
if
|
||||
case $arg in #(
|
||||
-*) false ;; # don't mess with options #(
|
||||
/?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath
|
||||
[ -e "$t" ] ;; #(
|
||||
*) false ;;
|
||||
esac
|
||||
then
|
||||
arg=$( cygpath --path --ignore --mixed "$arg" )
|
||||
fi
|
||||
# Roll the args list around exactly as many times as the number of
|
||||
# args, so each arg winds up back in the position where it started, but
|
||||
# possibly modified.
|
||||
#
|
||||
# NB: a `for` loop captures its iteration list before it begins, so
|
||||
# changing the positional parameters here affects neither the number of
|
||||
# iterations, nor the values presented in `arg`.
|
||||
shift # remove old arg
|
||||
set -- "$@" "$arg" # push replacement arg
|
||||
done
|
||||
fi
|
||||
|
||||
|
||||
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
|
||||
|
||||
# Collect all arguments for the java command:
|
||||
# * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments,
|
||||
# and any embedded shellness will be escaped.
|
||||
# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be
|
||||
# treated as '${Hostname}' itself on the command line.
|
||||
|
||||
set -- \
|
||||
"-Dorg.gradle.appname=$APP_BASE_NAME" \
|
||||
-classpath "$CLASSPATH" \
|
||||
org.gradle.wrapper.GradleWrapperMain \
|
||||
"$@"
|
||||
|
||||
# Stop when "xargs" is not available.
|
||||
if ! command -v xargs >/dev/null 2>&1
|
||||
then
|
||||
die "xargs is not available"
|
||||
fi
|
||||
|
||||
# Use "xargs" to parse quoted args.
|
||||
#
|
||||
# With -n1 it outputs one arg per line, with the quotes and backslashes removed.
|
||||
#
|
||||
# In Bash we could simply go:
|
||||
#
|
||||
# readarray ARGS < <( xargs -n1 <<<"$var" ) &&
|
||||
# set -- "${ARGS[@]}" "$@"
|
||||
#
|
||||
# but POSIX shell has neither arrays nor command substitution, so instead we
|
||||
# post-process each arg (as a line of input to sed) to backslash-escape any
|
||||
# character that might be a shell metacharacter, then use eval to reverse
|
||||
# that process (while maintaining the separation between arguments), and wrap
|
||||
# the whole thing up as a single "set" statement.
|
||||
#
|
||||
# This will of course break if any of these variables contains a newline or
|
||||
# an unmatched quote.
|
||||
#
|
||||
|
||||
eval "set -- $(
|
||||
printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" |
|
||||
xargs -n1 |
|
||||
sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' |
|
||||
tr '\n' ' '
|
||||
)" '"$@"'
|
||||
|
||||
exec "$JAVACMD" "$@"
|
||||
Vendored
+92
@@ -0,0 +1,92 @@
|
||||
@rem
|
||||
@rem Copyright 2015 the original author or authors.
|
||||
@rem
|
||||
@rem Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@rem you may not use this file except in compliance with the License.
|
||||
@rem You may obtain a copy of the License at
|
||||
@rem
|
||||
@rem https://www.apache.org/licenses/LICENSE-2.0
|
||||
@rem
|
||||
@rem Unless required by applicable law or agreed to in writing, software
|
||||
@rem distributed under the License is distributed on an "AS IS" BASIS,
|
||||
@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
@rem See the License for the specific language governing permissions and
|
||||
@rem limitations under the License.
|
||||
@rem
|
||||
|
||||
@if "%DEBUG%"=="" @echo off
|
||||
@rem ##########################################################################
|
||||
@rem
|
||||
@rem Gradle startup script for Windows
|
||||
@rem
|
||||
@rem ##########################################################################
|
||||
|
||||
@rem Set local scope for the variables with windows NT shell
|
||||
if "%OS%"=="Windows_NT" setlocal
|
||||
|
||||
set DIRNAME=%~dp0
|
||||
if "%DIRNAME%"=="" set DIRNAME=.
|
||||
@rem This is normally unused
|
||||
set APP_BASE_NAME=%~n0
|
||||
set APP_HOME=%DIRNAME%
|
||||
|
||||
@rem Resolve any "." and ".." in APP_HOME to make it shorter.
|
||||
for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
|
||||
|
||||
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||
set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
|
||||
|
||||
@rem Find java.exe
|
||||
if defined JAVA_HOME goto findJavaFromJavaHome
|
||||
|
||||
set JAVA_EXE=java.exe
|
||||
%JAVA_EXE% -version >NUL 2>&1
|
||||
if %ERRORLEVEL% equ 0 goto execute
|
||||
|
||||
echo. 1>&2
|
||||
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2
|
||||
echo. 1>&2
|
||||
echo Please set the JAVA_HOME variable in your environment to match the 1>&2
|
||||
echo location of your Java installation. 1>&2
|
||||
|
||||
goto fail
|
||||
|
||||
:findJavaFromJavaHome
|
||||
set JAVA_HOME=%JAVA_HOME:"=%
|
||||
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
|
||||
|
||||
if exist "%JAVA_EXE%" goto execute
|
||||
|
||||
echo. 1>&2
|
||||
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2
|
||||
echo. 1>&2
|
||||
echo Please set the JAVA_HOME variable in your environment to match the 1>&2
|
||||
echo location of your Java installation. 1>&2
|
||||
|
||||
goto fail
|
||||
|
||||
:execute
|
||||
@rem Setup the command line
|
||||
|
||||
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
|
||||
|
||||
|
||||
@rem Execute Gradle
|
||||
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
|
||||
|
||||
:end
|
||||
@rem End local scope for the variables with windows NT shell
|
||||
if %ERRORLEVEL% equ 0 goto mainEnd
|
||||
|
||||
:fail
|
||||
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
|
||||
rem the _cmd.exe /c_ return code!
|
||||
set EXIT_CODE=%ERRORLEVEL%
|
||||
if %EXIT_CODE% equ 0 set EXIT_CODE=1
|
||||
if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE%
|
||||
exit /b %EXIT_CODE%
|
||||
|
||||
:mainEnd
|
||||
if "%OS%"=="Windows_NT" endlocal
|
||||
|
||||
:omega
|
||||
@@ -0,0 +1 @@
|
||||
rootProject.name = "jeobeardy"
|
||||
@@ -0,0 +1,13 @@
|
||||
package at.eisibaer.jbear2
|
||||
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication
|
||||
import org.springframework.boot.context.properties.ConfigurationPropertiesScan
|
||||
import org.springframework.boot.runApplication
|
||||
|
||||
@SpringBootApplication
|
||||
@ConfigurationPropertiesScan(basePackages = ["at.eisibaer.jbear2.config"])
|
||||
class JeobeardyApplication
|
||||
|
||||
fun main(args: Array<String>) {
|
||||
runApplication<JeobeardyApplication>(*args)
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
package at.eisibaer.jbear2.config
|
||||
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties
|
||||
|
||||
@ConfigurationProperties("application")
|
||||
data class ApplicationProperties(
|
||||
val corsAllowedOrigins: List<String>,
|
||||
val corsAllowedMethods: List<String>,
|
||||
val jwtCookieName: String,
|
||||
val jwtExpirationMs: Long,
|
||||
val jwtSecret: String,
|
||||
)
|
||||
@@ -0,0 +1,51 @@
|
||||
package at.eisibaer.jbear2.config
|
||||
|
||||
import jakarta.servlet.http.HttpServletRequest
|
||||
import org.springframework.context.annotation.Configuration
|
||||
import org.springframework.core.io.Resource
|
||||
import org.springframework.lang.Nullable
|
||||
import org.springframework.web.servlet.config.annotation.CorsRegistry
|
||||
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry
|
||||
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer
|
||||
import org.springframework.web.servlet.resource.PathResourceResolver
|
||||
import org.springframework.web.servlet.resource.ResourceResolverChain
|
||||
|
||||
@Configuration
|
||||
class SpringConfiguration(
|
||||
private val applicationProperties: ApplicationProperties
|
||||
) : WebMvcConfigurer {
|
||||
|
||||
override fun addResourceHandlers(registry: ResourceHandlerRegistry) {
|
||||
this.serveDirectory(registry, "/", "classpath:/static/")
|
||||
}
|
||||
|
||||
private fun serveDirectory(registry: ResourceHandlerRegistry, endpoint: String, location: String){
|
||||
val endpointPatterns: Array<String>;
|
||||
if (endpoint.endsWith("/") ){
|
||||
endpointPatterns = arrayOf(endpoint.substring(0, endpoint.length - 1), endpoint, "$endpoint**")
|
||||
} else {
|
||||
endpointPatterns = arrayOf(endpoint, "$endpoint/", "$endpoint/**")
|
||||
}
|
||||
registry
|
||||
.addResourceHandler(*endpointPatterns)
|
||||
.addResourceLocations( if( location.endsWith("/") ) location else "$location/")
|
||||
.resourceChain(true)
|
||||
.addResolver(object : PathResourceResolver(){
|
||||
override fun resolveResource( @Nullable request: HttpServletRequest?, requestPath: String, locations: MutableList<out Resource>, chain: ResourceResolverChain ): Resource? {
|
||||
val resource: Resource? = super.resolveResource(request, requestPath, locations, chain);
|
||||
if( resource != null ){
|
||||
return resource;
|
||||
}
|
||||
return super.resolveResource(request, "/index.html", locations, chain);
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
override fun addCorsMappings(registry: CorsRegistry) {
|
||||
registry
|
||||
.addMapping("/api/**")
|
||||
.allowedOrigins(*applicationProperties.corsAllowedOrigins.map { it }.toTypedArray())
|
||||
.allowedMethods(*applicationProperties.corsAllowedMethods.map { it }.toTypedArray())
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
package at.eisibaer.jbear2.config
|
||||
|
||||
import org.springframework.context.annotation.Configuration
|
||||
import org.springframework.messaging.simp.config.MessageBrokerRegistry
|
||||
import org.springframework.web.socket.config.annotation.EnableWebSocketMessageBroker
|
||||
import org.springframework.web.socket.config.annotation.StompEndpointRegistry
|
||||
import org.springframework.web.socket.config.annotation.WebSocketMessageBrokerConfigurer
|
||||
|
||||
@Configuration
|
||||
@EnableWebSocketMessageBroker
|
||||
class WebSocketConfig : WebSocketMessageBrokerConfigurer {
|
||||
|
||||
override fun configureMessageBroker(registry: MessageBrokerRegistry) {
|
||||
registry.enableSimpleBroker("/game");
|
||||
registry.setApplicationDestinationPrefixes("/app");
|
||||
}
|
||||
|
||||
override fun registerStompEndpoints(registry: StompEndpointRegistry) {
|
||||
registry.addEndpoint("/websocket")
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
package at.eisibaer.jbear2.dto.auth
|
||||
|
||||
data class LoginDto(
|
||||
val username: String,
|
||||
val password: String,
|
||||
)
|
||||
@@ -0,0 +1,6 @@
|
||||
package at.eisibaer.jbear2.dto.auth
|
||||
|
||||
data class LoginResponseDto(
|
||||
val username: String,
|
||||
val profilePicture: String,
|
||||
)
|
||||
@@ -0,0 +1,11 @@
|
||||
package at.eisibaer.jbear2.dto.message
|
||||
|
||||
import lombok.AllArgsConstructor
|
||||
|
||||
@AllArgsConstructor
|
||||
data class GenericMessage (
|
||||
|
||||
var name: String? = "",
|
||||
|
||||
var content: String? = "",
|
||||
)
|
||||
@@ -0,0 +1,87 @@
|
||||
package at.eisibaer.jbear2.endpoint
|
||||
|
||||
import at.eisibaer.jbear2.dto.auth.LoginDto
|
||||
import at.eisibaer.jbear2.dto.auth.LoginResponseDto
|
||||
import at.eisibaer.jbear2.model.Board
|
||||
import at.eisibaer.jbear2.model.User
|
||||
import at.eisibaer.jbear2.repository.UserRepository
|
||||
import at.eisibaer.jbear2.security.jwt.JwtUtils
|
||||
import at.eisibaer.jbear2.security.userdetail.UserDetailsImpl
|
||||
import org.slf4j.Logger
|
||||
import org.slf4j.LoggerFactory
|
||||
import org.springframework.http.HttpHeaders
|
||||
import org.springframework.http.ResponseCookie
|
||||
import org.springframework.http.ResponseEntity
|
||||
import org.springframework.security.authentication.AuthenticationManager
|
||||
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken
|
||||
import org.springframework.security.core.context.SecurityContextHolder
|
||||
import org.springframework.security.crypto.password.PasswordEncoder
|
||||
import org.springframework.stereotype.Controller
|
||||
import org.springframework.web.bind.annotation.PostMapping
|
||||
import org.springframework.web.bind.annotation.RequestBody
|
||||
import org.springframework.web.bind.annotation.RequestMapping
|
||||
|
||||
@Controller
|
||||
@RequestMapping("/api/auth")
|
||||
class AuthEndpoint(
|
||||
val authenticationManager: AuthenticationManager,
|
||||
val userRepository: UserRepository,
|
||||
val encoder: PasswordEncoder,
|
||||
val jwtUtils: JwtUtils,
|
||||
) {
|
||||
|
||||
private val log: Logger = LoggerFactory.getLogger(AuthEndpoint::class.java);
|
||||
|
||||
val strResponseSuccess: String = "Sending back success response";
|
||||
|
||||
@PostMapping("/signup")
|
||||
fun signupUser(@RequestBody loginDto: LoginDto): ResponseEntity<String>{
|
||||
log.info("Endpoint singupUser called");
|
||||
log.debug("signup Request with username: {}", loginDto.username);
|
||||
if( userRepository.existsByUsername(loginDto.username)){
|
||||
log.info("Username was already taken");
|
||||
ResponseEntity.badRequest().body("Username already taken");
|
||||
}
|
||||
|
||||
val user = User(loginDto.username, encoder.encode( loginDto.password), ArrayList(), null, null );
|
||||
|
||||
userRepository.save(user);
|
||||
|
||||
log.info(strResponseSuccess);
|
||||
return ResponseEntity.ok().body("User registered successfully");
|
||||
}
|
||||
|
||||
@PostMapping("/login")
|
||||
fun loginUser(@RequestBody loginDto: LoginDto): ResponseEntity<LoginResponseDto>{
|
||||
log.info("Endpoint loginUser called");
|
||||
log.debug("login Request with username: {}", loginDto.username);
|
||||
val authentication = authenticationManager.authenticate(
|
||||
UsernamePasswordAuthenticationToken(
|
||||
loginDto.username,
|
||||
loginDto.password
|
||||
)
|
||||
)
|
||||
|
||||
SecurityContextHolder.getContext().authentication = authentication;
|
||||
|
||||
val userDetails: UserDetailsImpl = authentication.principal as UserDetailsImpl;
|
||||
|
||||
val jwtCookie = jwtUtils.generateJwtCookie(userDetails);
|
||||
|
||||
log.info(strResponseSuccess);
|
||||
return ResponseEntity.ok()
|
||||
.header( HttpHeaders.SET_COOKIE, jwtCookie.toString() )
|
||||
.body( LoginResponseDto(userDetails.username, userDetails.getProfilePictureFilename()))
|
||||
}
|
||||
|
||||
@PostMapping("signout")
|
||||
fun logoutUser(): ResponseEntity<String>{
|
||||
log.info("Endpoint logoutUser called");
|
||||
val cookie: ResponseCookie = jwtUtils.getCleanJwtCookie();
|
||||
|
||||
log.info(strResponseSuccess);
|
||||
return ResponseEntity.ok()
|
||||
.header(HttpHeaders.SET_COOKIE, cookie.toString())
|
||||
.body("Logged out");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
package at.eisibaer.jbear2.endpoint
|
||||
|
||||
import org.springframework.stereotype.Controller
|
||||
import org.springframework.web.bind.annotation.RequestMapping
|
||||
|
||||
@Controller
|
||||
@RequestMapping("/api/board")
|
||||
class BoardEndpoint {
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
package at.eisibaer.jbear2.endpoint
|
||||
|
||||
import org.springframework.messaging.handler.annotation.MessageMapping
|
||||
import org.springframework.messaging.handler.annotation.SendTo
|
||||
|
||||
import at.eisibaer.jbear2.dto.message.GenericMessage
|
||||
import org.springframework.web.bind.annotation.RequestMapping
|
||||
import org.springframework.web.bind.annotation.RestController
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/api/game")
|
||||
class GameEndpoint {
|
||||
|
||||
@MessageMapping("/player/join")
|
||||
@SendTo("/player/joined")
|
||||
fun playerJoining(playerJoiningMessage: GenericMessage): GenericMessage{
|
||||
return playerJoiningMessage.copy(playerJoiningMessage.name, "Joined");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
package at.eisibaer.jbear2.endpoint
|
||||
|
||||
import org.slf4j.Logger
|
||||
import org.slf4j.LoggerFactory
|
||||
import org.springframework.http.ResponseEntity
|
||||
import org.springframework.web.bind.annotation.GetMapping
|
||||
import org.springframework.web.bind.annotation.PathVariable
|
||||
import org.springframework.web.bind.annotation.RequestMapping
|
||||
import org.springframework.web.bind.annotation.RequestParam
|
||||
import org.springframework.web.bind.annotation.RestController
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/api/user")
|
||||
class UserEndpoint {
|
||||
|
||||
val log: Logger = LoggerFactory.getLogger(UserEndpoint::class.java);
|
||||
|
||||
@GetMapping("/test/{pathVar}")
|
||||
fun testEndpoint(@PathVariable pathVar: String, @RequestParam param1: String): ResponseEntity<String>{
|
||||
log.info("test Endpoint!");
|
||||
return ResponseEntity.ok(param1);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
package at.eisibaer.jbear2.model
|
||||
|
||||
import jakarta.persistence.*
|
||||
|
||||
@Entity
|
||||
@Table(name = "answers", indexes = [
|
||||
Index(name = "fk_board_entry_to_answer", columnList = "fk_board_entry")
|
||||
])
|
||||
data class Answer(
|
||||
|
||||
@Column(name = "text", nullable = false, unique = false)
|
||||
val text: String,
|
||||
|
||||
@OneToOne
|
||||
@JoinColumn(name = "fk_image_file", referencedColumnName = "id")
|
||||
val image: ImageFile?,
|
||||
|
||||
@OneToOne
|
||||
@JoinColumn(name="fk_board_entry", referencedColumnName = "id")
|
||||
val boardEntry: BoardEntry?,
|
||||
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "sequenceGenerator")
|
||||
val id: Long? = null,
|
||||
)
|
||||
@@ -0,0 +1,24 @@
|
||||
package at.eisibaer.jbear2.model
|
||||
|
||||
import jakarta.persistence.*
|
||||
|
||||
@Entity
|
||||
@Table(name = "boards", indexes = [
|
||||
Index(name = "fk_owner_of_board", columnList = "fk_owned_by")
|
||||
])
|
||||
data class Board(
|
||||
|
||||
@OneToMany(mappedBy = "board")
|
||||
val categories: List<Category>,
|
||||
|
||||
@Column(name = "board_name", nullable = false, unique = false)
|
||||
val boardName: String,
|
||||
|
||||
@ManyToOne
|
||||
@JoinColumn(name="fk_owned_by", referencedColumnName = "id")
|
||||
val owner: User,
|
||||
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "sequenceGenerator")
|
||||
val id: Long? = null,
|
||||
)
|
||||
@@ -0,0 +1,27 @@
|
||||
package at.eisibaer.jbear2.model
|
||||
|
||||
import jakarta.persistence.*
|
||||
|
||||
@Entity
|
||||
@Table(name = "board_entries", indexes = [
|
||||
Index(name = "fk_category_to_board_entry", columnList = "fk_category")
|
||||
])
|
||||
data class BoardEntry(
|
||||
|
||||
@Column(name = "name", nullable = false, unique = false)
|
||||
val name: String,
|
||||
|
||||
@OneToMany(mappedBy = "boardEntry")
|
||||
val questions: List<Question>,
|
||||
|
||||
@OneToOne
|
||||
val answer: Answer,
|
||||
|
||||
@ManyToOne
|
||||
@JoinColumn(name = "fk_category", referencedColumnName = "id")
|
||||
val category: Category?,
|
||||
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "sequenceGenerator")
|
||||
val id: Long? = null,
|
||||
)
|
||||
@@ -0,0 +1,27 @@
|
||||
package at.eisibaer.jbear2.model
|
||||
|
||||
import jakarta.persistence.*
|
||||
|
||||
@Entity
|
||||
@Table(name = "categories", indexes = [
|
||||
Index(name = "fk_category_to_board", columnList = "fk_board")
|
||||
])
|
||||
data class Category (
|
||||
|
||||
@Column(name = "name", nullable = false, unique = false)
|
||||
val name: String,
|
||||
|
||||
@Column(name = "description", nullable = false, unique = false)
|
||||
val description: String,
|
||||
|
||||
@OneToMany(mappedBy = "category")
|
||||
val boardEntries: List<BoardEntry>,
|
||||
|
||||
@ManyToOne
|
||||
@JoinColumn(name = "fk_board", referencedColumnName = "id")
|
||||
val board: Board,
|
||||
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "sequenceGenerator")
|
||||
val id: Long? = null,
|
||||
)
|
||||
@@ -0,0 +1,51 @@
|
||||
package at.eisibaer.jbear2.model
|
||||
|
||||
import jakarta.persistence.*
|
||||
import org.springframework.data.annotation.CreatedDate
|
||||
import java.time.Instant
|
||||
|
||||
@Entity
|
||||
@Table(name = "games", indexes = [
|
||||
Index(name = "fk_board_to_game", columnList = "fk_board"),
|
||||
Index(name = "fk_host_to_game", columnList = "fk_host_user"),
|
||||
Index(name = "fk_choosing_player_to_game", columnList = "fk_player_currently_choosing")
|
||||
])
|
||||
data class Game(
|
||||
|
||||
@Column(name = "invite_code", nullable = false, unique = true)
|
||||
val inviteCode: String,
|
||||
|
||||
@ManyToOne
|
||||
@JoinColumn(name = "fk_board", referencedColumnName = "id")
|
||||
val board: Board,
|
||||
|
||||
@OneToOne
|
||||
@JoinColumn(name="fk_host_user", referencedColumnName = "id")
|
||||
val host: User,
|
||||
|
||||
@OneToMany(mappedBy = "currentGame")
|
||||
val players: List<Player>,
|
||||
|
||||
@OneToOne
|
||||
@JoinColumn(name="fk_player_currently_choosing", referencedColumnName = "id")
|
||||
val currentlyChoosingPlayer: Player,
|
||||
|
||||
@ManyToMany
|
||||
@JoinTable(
|
||||
name = "answered_board_entries_in_games",
|
||||
joinColumns = [JoinColumn(name = "fk_game")],
|
||||
inverseJoinColumns = [JoinColumn(name = "fk_board_entry")]
|
||||
)
|
||||
val alreadyAnsweredEntries: List<BoardEntry>,
|
||||
|
||||
@Column(name = "accepting_answers", nullable = false, unique = false)
|
||||
val acceptingAnswers: Boolean? = false,
|
||||
|
||||
@CreatedDate
|
||||
@Column(name = "created_timestamp", nullable = false, unique = false)
|
||||
val createdTimestamp: Instant,
|
||||
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "sequenceGenerator")
|
||||
val id: Long? = null,
|
||||
)
|
||||
@@ -0,0 +1,34 @@
|
||||
package at.eisibaer.jbear2.model
|
||||
|
||||
import jakarta.persistence.*
|
||||
import java.util.UUID
|
||||
|
||||
@Entity
|
||||
@Table(name = "image_files", indexes = [
|
||||
Index(name = "fk_owner_to_image_file", columnList = "fk_owned_by")
|
||||
])
|
||||
data class ImageFile (
|
||||
|
||||
@Column(name = "uuid", nullable = false, unique = true)
|
||||
val uuid: UUID,
|
||||
|
||||
@Column(name = "filename", nullable = false, unique = false)
|
||||
val filename: String,
|
||||
|
||||
@Column(name = "hash", nullable = false, unique = false)
|
||||
val hash: String,
|
||||
|
||||
@ManyToOne
|
||||
@JoinColumn(name="fk_owned_by", referencedColumnName = "id")
|
||||
val owner: User,
|
||||
|
||||
@OneToOne
|
||||
val question: Question?,
|
||||
|
||||
@OneToOne
|
||||
val answer: Answer?,
|
||||
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "sequenceGenerator")
|
||||
val id: Long? = null,
|
||||
)
|
||||
@@ -0,0 +1,28 @@
|
||||
package at.eisibaer.jbear2.model
|
||||
|
||||
import jakarta.persistence.*
|
||||
|
||||
@Entity
|
||||
@Table(name = "players", indexes = [
|
||||
Index(name = "fk_current_game_to_player", columnList = "fk_current_game"),
|
||||
Index(name = "fk_name_to_player", columnList = "name"),
|
||||
])
|
||||
data class Player(
|
||||
|
||||
@Column(name = "name", nullable = false, unique = false)
|
||||
val name: String,
|
||||
|
||||
@ManyToOne
|
||||
@JoinColumn(name = "fk_current_game", referencedColumnName = "id")
|
||||
val currentGame: Game,
|
||||
|
||||
@Column(name = "is_allowed_to_answer", nullable = false, unique = false)
|
||||
val allowedToAnswer: Boolean? = false,
|
||||
|
||||
@Column(name = "points", nullable = false, unique = false)
|
||||
val points: Int? = 0,
|
||||
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "sequenceGenerator")
|
||||
val id: Long? = null,
|
||||
)
|
||||
@@ -0,0 +1,31 @@
|
||||
package at.eisibaer.jbear2.model
|
||||
|
||||
import jakarta.persistence.*
|
||||
|
||||
@Entity
|
||||
@Table(name = "questions", indexes = [
|
||||
Index(name = "fk_board_entry_to_question", columnList = "fk_board_entry"),
|
||||
Index(name = "fk_image_file_to_question", columnList = "fk_image"),
|
||||
Index(name = "fk_question_type_to_question", columnList = "fk_question_type"),
|
||||
])
|
||||
data class Question(
|
||||
|
||||
@Column(name = "text", nullable = false, unique = false)
|
||||
val text: String,
|
||||
|
||||
@ManyToOne
|
||||
@JoinColumn(name = "fk_question_type", referencedColumnName = "id")
|
||||
val questionType: QuestionType,
|
||||
|
||||
@OneToOne
|
||||
@JoinColumn(name = "fk_image", referencedColumnName = "id")
|
||||
val image: ImageFile?,
|
||||
|
||||
@ManyToOne
|
||||
@JoinColumn(name = "fk_board_entry", referencedColumnName = "id")
|
||||
val boardEntry: BoardEntry?,
|
||||
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "sequenceGenerator")
|
||||
val id: Long? = null,
|
||||
)
|
||||
@@ -0,0 +1,21 @@
|
||||
package at.eisibaer.jbear2.model
|
||||
|
||||
import jakarta.persistence.*
|
||||
|
||||
@Entity
|
||||
@Table(name = "question_types")
|
||||
data class QuestionType(
|
||||
|
||||
@Column(name = "title", nullable = false, unique = true)
|
||||
val title: String,
|
||||
|
||||
@Column(name = "description", nullable = false, unique = true)
|
||||
val description: String,
|
||||
|
||||
@Column(name = "active", nullable = false, unique = false)
|
||||
val active: Boolean,
|
||||
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "sequenceGenerator")
|
||||
val id: Long? = null,
|
||||
)
|
||||
@@ -0,0 +1,28 @@
|
||||
package at.eisibaer.jbear2.model
|
||||
|
||||
import jakarta.persistence.*
|
||||
|
||||
@Entity
|
||||
@Table(name = "users", indexes = [
|
||||
Index(name = "fk_profile_picture_to_user", columnList = "fk_profile_picture"),
|
||||
Index(name = "username_to_user", columnList = "username"),
|
||||
])
|
||||
data class User(
|
||||
|
||||
@Column(name = "username", nullable = false, unique = true)
|
||||
var username: String,
|
||||
|
||||
@Column(name = "password", nullable = false, unique = false)
|
||||
var password: String,
|
||||
|
||||
@OneToMany(mappedBy = "owner")
|
||||
val boards: List<Board>,
|
||||
|
||||
@OneToOne
|
||||
@JoinColumn(name = "fk_profile_picture", referencedColumnName = "id")
|
||||
var profilePicture: ImageFile?,
|
||||
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "sequenceGenerator")
|
||||
val id: Long? = null,
|
||||
)
|
||||
@@ -0,0 +1,14 @@
|
||||
package at.eisibaer.jbear2.repository
|
||||
|
||||
import at.eisibaer.jbear2.model.User
|
||||
import org.springframework.data.jpa.repository.JpaRepository
|
||||
import org.springframework.stereotype.Repository
|
||||
import java.util.*
|
||||
|
||||
@Repository
|
||||
interface UserRepository : JpaRepository<User, Long> {
|
||||
|
||||
fun findUserByUsername(username: String): Optional<User>;
|
||||
|
||||
fun existsByUsername(username: String): Boolean;
|
||||
}
|
||||
@@ -0,0 +1,126 @@
|
||||
package at.eisibaer.jbear2.security
|
||||
|
||||
import at.eisibaer.jbear2.security.jwt.AuthTokenFilter
|
||||
import jakarta.servlet.FilterChain
|
||||
import jakarta.servlet.ServletException
|
||||
import jakarta.servlet.http.HttpServletRequest
|
||||
import jakarta.servlet.http.HttpServletResponse
|
||||
import org.slf4j.Logger
|
||||
import org.slf4j.LoggerFactory
|
||||
import org.springframework.context.annotation.Bean
|
||||
import org.springframework.context.annotation.Configuration
|
||||
import org.springframework.security.authentication.AuthenticationManager
|
||||
import org.springframework.security.authentication.dao.DaoAuthenticationProvider
|
||||
import org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration
|
||||
import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity
|
||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity
|
||||
import org.springframework.security.config.annotation.web.configurers.SessionManagementConfigurer
|
||||
import org.springframework.security.config.http.SessionCreationPolicy
|
||||
import org.springframework.security.core.userdetails.UserDetailsService
|
||||
import org.springframework.security.crypto.argon2.Argon2PasswordEncoder
|
||||
import org.springframework.security.crypto.password.PasswordEncoder
|
||||
import org.springframework.security.web.SecurityFilterChain
|
||||
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter
|
||||
import org.springframework.security.web.authentication.www.BasicAuthenticationFilter
|
||||
import org.springframework.security.web.csrf.*
|
||||
import org.springframework.util.StringUtils
|
||||
import org.springframework.web.filter.OncePerRequestFilter
|
||||
import java.io.IOException
|
||||
import java.util.function.Supplier
|
||||
|
||||
@Configuration
|
||||
@EnableMethodSecurity
|
||||
class SecurityConfiguration(
|
||||
private val userDetailService: UserDetailsService,
|
||||
private val unauthorizedHandler: AuthTokenFilter,
|
||||
) {
|
||||
|
||||
final val log: Logger = LoggerFactory.getLogger(SecurityConfiguration::class.java);
|
||||
|
||||
@Bean
|
||||
fun securityFilterChain(httpSecurity: HttpSecurity): SecurityFilterChain {
|
||||
return httpSecurity
|
||||
.csrf { config ->
|
||||
config
|
||||
.csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse())
|
||||
.csrfTokenRequestHandler(SpaCsrfTokenRequestHandler())
|
||||
}
|
||||
.addFilterAfter(CsrfCookieFilter(), BasicAuthenticationFilter::class.java)
|
||||
.authorizeHttpRequests { config ->
|
||||
config
|
||||
.requestMatchers("/api/auth/*").permitAll()
|
||||
.requestMatchers("/api/**").authenticated()
|
||||
.requestMatchers("/profile").authenticated()
|
||||
.requestMatchers("/**").permitAll()
|
||||
}
|
||||
.sessionManagement { config: SessionManagementConfigurer<HttpSecurity?> ->
|
||||
config.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
|
||||
}
|
||||
.authenticationProvider(authenticationProvider())
|
||||
.addFilterBefore(unauthorizedHandler, UsernamePasswordAuthenticationFilter::class.java)
|
||||
.build()
|
||||
}
|
||||
|
||||
class SpaCsrfTokenRequestHandler : CsrfTokenRequestAttributeHandler() {
|
||||
private val delegate: CsrfTokenRequestHandler = XorCsrfTokenRequestAttributeHandler()
|
||||
|
||||
override fun handle(request: HttpServletRequest, response: HttpServletResponse, csrfToken: Supplier<CsrfToken>) {
|
||||
/*
|
||||
* Always use XorCsrfTokenRequestAttributeHandler to provide BREACH protection of
|
||||
* the CsrfToken when it is rendered in the response body.
|
||||
*/
|
||||
delegate.handle(request, response, csrfToken)
|
||||
}
|
||||
|
||||
override fun resolveCsrfTokenValue(request: HttpServletRequest, csrfToken: CsrfToken): String? {
|
||||
/*
|
||||
* If the request contains a request header, use CsrfTokenRequestAttributeHandler
|
||||
* to resolve the CsrfToken. This applies when a single-page application includes
|
||||
* the header value automatically, which was obtained via a cookie containing the
|
||||
* raw CsrfToken.
|
||||
*/
|
||||
return if (StringUtils.hasText(request.getHeader(csrfToken.headerName))) {
|
||||
super.resolveCsrfTokenValue(request, csrfToken)
|
||||
} else {
|
||||
/*
|
||||
* In all other cases (e.g. if the request contains a request parameter), use
|
||||
* XorCsrfTokenRequestAttributeHandler to resolve the CsrfToken. This applies
|
||||
* when a server-side rendered form includes the _csrf request parameter as a
|
||||
* hidden input.
|
||||
*/
|
||||
delegate.resolveCsrfTokenValue(request, csrfToken)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class CsrfCookieFilter : OncePerRequestFilter() {
|
||||
|
||||
@Throws(ServletException::class, IOException::class)
|
||||
override fun doFilterInternal(request: HttpServletRequest, response: HttpServletResponse, filterChain: FilterChain) {
|
||||
val csrfToken = request.getAttribute("_csrf") as CsrfToken
|
||||
// Render the token value to a cookie by causing the deferred token to be loaded
|
||||
csrfToken.token
|
||||
filterChain.doFilter(request, response)
|
||||
}
|
||||
}
|
||||
|
||||
@Bean
|
||||
fun passwordEncoder() : PasswordEncoder {
|
||||
return Argon2PasswordEncoder.defaultsForSpringSecurity_v5_8();
|
||||
}
|
||||
|
||||
@Bean
|
||||
fun authenticationProvider(): DaoAuthenticationProvider{
|
||||
val authProvider: DaoAuthenticationProvider = DaoAuthenticationProvider()
|
||||
|
||||
authProvider.setUserDetailsService(userDetailService)
|
||||
authProvider.setPasswordEncoder(passwordEncoder());
|
||||
|
||||
return authProvider;
|
||||
}
|
||||
|
||||
@Bean
|
||||
fun authenticationManager(authConfig: AuthenticationConfiguration): AuthenticationManager{
|
||||
return authConfig.authenticationManager;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
package at.eisibaer.jbear2.security.jwt
|
||||
|
||||
import jakarta.servlet.http.HttpServletRequest
|
||||
import jakarta.servlet.http.HttpServletResponse
|
||||
import org.slf4j.Logger
|
||||
import org.slf4j.LoggerFactory
|
||||
import org.springframework.security.core.AuthenticationException
|
||||
import org.springframework.security.web.AuthenticationEntryPoint
|
||||
|
||||
class AuthEntryPointJwt: AuthenticationEntryPoint {
|
||||
|
||||
val log: Logger = LoggerFactory.getLogger(AuthEntryPointJwt::class.java);
|
||||
|
||||
override fun commence(
|
||||
request: HttpServletRequest?,
|
||||
response: HttpServletResponse?,
|
||||
authException: AuthenticationException?
|
||||
) {
|
||||
log.error("Unauthorized error: {}", authException?.message);
|
||||
response?.sendError(HttpServletResponse.SC_UNAUTHORIZED, "Error: Unauthorized");
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
package at.eisibaer.jbear2.security.jwt
|
||||
|
||||
import jakarta.servlet.FilterChain
|
||||
import jakarta.servlet.http.HttpServletRequest
|
||||
import jakarta.servlet.http.HttpServletResponse
|
||||
import org.slf4j.Logger
|
||||
import org.slf4j.LoggerFactory
|
||||
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken
|
||||
import org.springframework.security.core.context.SecurityContextHolder
|
||||
import org.springframework.security.core.userdetails.UserDetails
|
||||
import org.springframework.security.core.userdetails.UserDetailsService
|
||||
import org.springframework.security.web.authentication.WebAuthenticationDetailsSource
|
||||
import org.springframework.stereotype.Component
|
||||
import org.springframework.web.filter.OncePerRequestFilter
|
||||
|
||||
@Component
|
||||
class AuthTokenFilter(
|
||||
private var jwtUtils: JwtUtils?,
|
||||
private var userDetailService: UserDetailsService?,
|
||||
): OncePerRequestFilter() {
|
||||
|
||||
val log: Logger = LoggerFactory.getLogger(AuthTokenFilter::class.java);
|
||||
|
||||
override fun doFilterInternal(
|
||||
request: HttpServletRequest,
|
||||
response: HttpServletResponse,
|
||||
filterChain: FilterChain
|
||||
) {
|
||||
try{
|
||||
val jwt: String? = parseJwt(request);
|
||||
if( jwt != null && jwtUtils!!.validateJwt(jwt) ){
|
||||
val username: String = jwtUtils!!.getUserNameFromJwt(jwt);
|
||||
|
||||
val userDetails: UserDetails = userDetailService!!.loadUserByUsername( username );
|
||||
|
||||
val authentication = UsernamePasswordAuthenticationToken(userDetails, null, userDetails.authorities);
|
||||
authentication.details = WebAuthenticationDetailsSource().buildDetails(request);
|
||||
|
||||
SecurityContextHolder.getContext().authentication = authentication;
|
||||
}
|
||||
} catch ( e: Exception ){
|
||||
log.error("Cannot set user authentication", e);
|
||||
}
|
||||
filterChain.doFilter(request, response);
|
||||
}
|
||||
|
||||
private fun parseJwt(request: HttpServletRequest): String?{
|
||||
return jwtUtils!!.getJwtFromCookies(request);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
package at.eisibaer.jbear2.security.jwt
|
||||
|
||||
import at.eisibaer.jbear2.config.ApplicationProperties
|
||||
import at.eisibaer.jbear2.security.userdetail.UserDetailsImpl
|
||||
import io.jsonwebtoken.JwtException
|
||||
import io.jsonwebtoken.Jwts
|
||||
import io.jsonwebtoken.UnsupportedJwtException
|
||||
import io.jsonwebtoken.io.Decoders
|
||||
import io.jsonwebtoken.security.Keys
|
||||
import jakarta.servlet.http.HttpServletRequest
|
||||
import org.slf4j.Logger
|
||||
import org.slf4j.LoggerFactory
|
||||
import org.springframework.http.ResponseCookie
|
||||
import org.springframework.stereotype.Component
|
||||
import org.springframework.web.util.WebUtils
|
||||
import java.util.Date
|
||||
import javax.crypto.SecretKey
|
||||
|
||||
@Component
|
||||
class JwtUtils(
|
||||
private val applicationProperties: ApplicationProperties
|
||||
) {
|
||||
|
||||
private val log: Logger = LoggerFactory.getLogger(JwtUtils::class.java);
|
||||
|
||||
fun getJwtFromCookies(request: HttpServletRequest): String?{
|
||||
return WebUtils.getCookie(request, applicationProperties.jwtCookieName)?.value;
|
||||
}
|
||||
|
||||
fun generateJwtCookie(userPrincipal: UserDetailsImpl): ResponseCookie{
|
||||
val jwt: String = generateTokenFromUsername(userPrincipal.username)
|
||||
return ResponseCookie.from(applicationProperties.jwtCookieName, jwt)
|
||||
.path("/api")
|
||||
.maxAge(applicationProperties.jwtExpirationMs/1000)
|
||||
.httpOnly(true)
|
||||
.build();
|
||||
}
|
||||
|
||||
fun getCleanJwtCookie(): ResponseCookie {
|
||||
return ResponseCookie.from(applicationProperties.jwtCookieName, "")
|
||||
.path("/api")
|
||||
.build();
|
||||
}
|
||||
|
||||
fun getUserNameFromJwt(token: String): String{
|
||||
return Jwts.parser().verifyWith(key()).build().parseSignedClaims(token).payload.subject;
|
||||
}
|
||||
|
||||
fun key(): SecretKey{
|
||||
return Keys.hmacShaKeyFor(Decoders.BASE64.decode(applicationProperties.jwtSecret));
|
||||
}
|
||||
|
||||
fun generateTokenFromUsername(username: String): String{
|
||||
return Jwts.builder()
|
||||
.subject(username)
|
||||
.issuedAt(Date())
|
||||
.expiration(Date(Date().time + applicationProperties.jwtExpirationMs))
|
||||
.signWith(key())
|
||||
.compact();
|
||||
}
|
||||
|
||||
fun validateJwt(authToken: String): Boolean{
|
||||
try {
|
||||
Jwts.parser().verifyWith(key()).build().parseSignedClaims(authToken);
|
||||
return true;
|
||||
} catch (e: UnsupportedJwtException) {
|
||||
log.error("UnsupportedJwtException {}", e.message);
|
||||
} catch (e: IllegalArgumentException) {
|
||||
log.error("IllegalArgumentException {}", e.message);
|
||||
} catch (e: JwtException) {
|
||||
log.error("JwtException {}", e.message);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
package at.eisibaer.jbear2.security.userdetail
|
||||
|
||||
import at.eisibaer.jbear2.repository.UserRepository
|
||||
import at.eisibaer.jbear2.model.User
|
||||
import lombok.AllArgsConstructor
|
||||
import lombok.NoArgsConstructor
|
||||
import org.springframework.security.core.userdetails.UserDetailsService
|
||||
import org.springframework.security.core.userdetails.UsernameNotFoundException
|
||||
import org.springframework.stereotype.Component
|
||||
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
@Component
|
||||
class UserDetailServiceImpl(
|
||||
val userRepository: UserRepository,
|
||||
): UserDetailsService {
|
||||
|
||||
override fun loadUserByUsername(username: String?): UserDetailsImpl {
|
||||
val user: User = userRepository.findUserByUsername( username ?: "" ).orElseThrow { UsernameNotFoundException("User not found by username \"$username\"") }
|
||||
|
||||
return UserDetailsImpl(
|
||||
user.id!!,
|
||||
user.username,
|
||||
user.password,
|
||||
user.profilePicture?.filename,
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
package at.eisibaer.jbear2.security.userdetail
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnore
|
||||
import lombok.Data
|
||||
import org.springframework.security.core.GrantedAuthority
|
||||
import org.springframework.security.core.userdetails.UserDetails
|
||||
import java.util.Collections
|
||||
|
||||
@Data
|
||||
class UserDetailsImpl(
|
||||
private val id: Long,
|
||||
private val username: String,
|
||||
@JsonIgnore
|
||||
private val password: String,
|
||||
private val profilePictureFilename: String?,
|
||||
): UserDetails {
|
||||
|
||||
override fun getAuthorities(): MutableCollection<out GrantedAuthority> {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
override fun getPassword(): String {
|
||||
return password;
|
||||
}
|
||||
|
||||
override fun getUsername(): String {
|
||||
return username;
|
||||
}
|
||||
|
||||
fun getProfilePictureFilename(): String {
|
||||
return profilePictureFilename ?: "";
|
||||
}
|
||||
|
||||
fun getId(): Long{
|
||||
return id;
|
||||
}
|
||||
|
||||
override fun isAccountNonExpired(): Boolean {
|
||||
return true
|
||||
}
|
||||
|
||||
override fun isAccountNonLocked(): Boolean {
|
||||
return true
|
||||
}
|
||||
|
||||
override fun isCredentialsNonExpired(): Boolean {
|
||||
return true
|
||||
}
|
||||
|
||||
override fun isEnabled(): Boolean {
|
||||
return true
|
||||
}
|
||||
|
||||
override fun equals(other: Any?): Boolean {
|
||||
if (this === other) return true
|
||||
if (javaClass != other?.javaClass) return false
|
||||
|
||||
other as UserDetailsImpl
|
||||
|
||||
return id == other.id
|
||||
}
|
||||
|
||||
override fun hashCode(): Int {
|
||||
return id.hashCode()
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
logging:
|
||||
level:
|
||||
org:
|
||||
springframework:
|
||||
security: "DEBUG"
|
||||
spring:
|
||||
datasource:
|
||||
url: jdbc:postgresql://localhost:5499/jeobeardy?currentSchema=jeobeardy-app
|
||||
username: ${PG_USER}
|
||||
password: ${PG_PASSWORD}
|
||||
|
||||
application:
|
||||
cors-allowed-origins: [ "http://localhost:5173/" ]
|
||||
@@ -0,0 +1,8 @@
|
||||
spring:
|
||||
datasource:
|
||||
url: jdbc:postgresql://localhost:5499/jeobeardy?currentSchema=jeobeardy-app
|
||||
username: ${PG_USER}
|
||||
password: ${PG_PASSWORD}
|
||||
|
||||
application:
|
||||
cors-allowed-origins: []
|
||||
@@ -0,0 +1,23 @@
|
||||
spring:
|
||||
application:
|
||||
name: "jeobeardy"
|
||||
jpa:
|
||||
show-sql: true
|
||||
hibernate:
|
||||
auto-ddl: create
|
||||
generate-ddl: true
|
||||
properties:
|
||||
hibernate:
|
||||
dialect: org.hibernate.dialect.PostgreSQLDialect
|
||||
default-schema: jeobeardy-app
|
||||
open-in-view: false
|
||||
|
||||
server:
|
||||
address: localhost
|
||||
port: 8008
|
||||
|
||||
application:
|
||||
cors-allowed-methods: ["GET", "POST", "DELETE", "OPTIONS"]
|
||||
jwt-cookie-name: "user_jwt"
|
||||
jwt-expiration-ms: 86400000 #1000 * 60 * 60 * 24 = 1 day
|
||||
jwt-secret: ${JWT_SECRET}
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 128 KiB |
@@ -0,0 +1,5 @@
|
||||
@charset "UTF-8";.home-player-join-row[data-v-6c838f03]{background-image:url(/assets/OldInGameBlurredRotated-Bc8vmN0_.jpeg);background-repeat:no-repeat;background-size:cover}.preserve-breaks{white-space:preserve-breaks}h6,.h6,h5,.h5,h4,.h4,h3,.h3,h2,.h2,h1,.h1{margin-top:0;margin-bottom:.5rem;font-weight:500;line-height:1.2;color:var(--bs-heading-color)}.container,.container-fluid,.container-xxl,.container-xl,.container-lg,.container-md,.container-sm{--bs-gutter-x: 1.5rem;--bs-gutter-y: 0;width:100%;padding-right:calc(var(--bs-gutter-x) * .5);padding-left:calc(var(--bs-gutter-x) * .5);margin-right:auto;margin-left:auto}@media (min-width: 576px){.container-sm,.container{max-width:540px}}@media (min-width: 768px){.container-md,.container-sm,.container{max-width:720px}}@media (min-width: 992px){.container-lg,.container-md,.container-sm,.container{max-width:960px}}@media (min-width: 1200px){.container-xl,.container-lg,.container-md,.container-sm,.container{max-width:1140px}}@media (min-width: 1400px){.container-xxl,.container-xl,.container-lg,.container-md,.container-sm,.container{max-width:1320px}}.form-select{--bs-form-select-bg-img: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3e%3cpath fill='none' stroke='%23343a40' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='m2 5 6 6 6-6'/%3e%3c/svg%3e");display:block;width:100%;padding:.375rem 2.25rem .375rem .75rem;font-size:1rem;font-weight:400;line-height:1.5;color:var(--bs-body-color);-webkit-appearance:none;-moz-appearance:none;appearance:none;background-color:var(--bs-body-bg);background-image:var(--bs-form-select-bg-img),var(--bs-form-select-bg-icon, none);background-repeat:no-repeat;background-position:right .75rem center;background-size:16px 12px;border:var(--bs-border-width) solid var(--bs-border-color);border-radius:var(--bs-border-radius);transition:border-color .15s ease-in-out,box-shadow .15s ease-in-out}[data-bs-theme=dark] .form-select{--bs-form-select-bg-img: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3e%3cpath fill='none' stroke='%23dee2e6' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='m2 5 6 6 6-6'/%3e%3c/svg%3e")}.form-check-input:checked[type=checkbox]{--bs-form-check-bg-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20'%3e%3cpath fill='none' stroke='%23fff' stroke-linecap='round' stroke-linejoin='round' stroke-width='3' d='m6 10 3 3 6-6'/%3e%3c/svg%3e")}.form-check-input:checked[type=radio]{--bs-form-check-bg-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3e%3ccircle r='2' fill='%23fff'/%3e%3c/svg%3e")}.form-check-input[type=checkbox]:indeterminate{background-color:#e86a92;border-color:#e86a92;--bs-form-check-bg-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20'%3e%3cpath fill='none' stroke='%23fff' stroke-linecap='round' stroke-linejoin='round' stroke-width='3' d='M6 10h8'/%3e%3c/svg%3e")}.form-switch .form-check-input{--bs-form-switch-bg: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3e%3ccircle r='3' fill='rgba%280, 0, 0, 0.25%29'/%3e%3c/svg%3e");width:2em;margin-left:-2.5em;background-image:var(--bs-form-switch-bg);background-position:left center;border-radius:2em;transition:background-position .15s ease-in-out}.form-switch .form-check-input:focus{--bs-form-switch-bg: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3e%3ccircle r='3' fill='%23f4b5c9'/%3e%3c/svg%3e")}.form-switch .form-check-input:checked{background-position:right center;--bs-form-switch-bg: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3e%3ccircle r='3' fill='%23fff'/%3e%3c/svg%3e")}[data-bs-theme=dark] .form-switch .form-check-input:not(:checked):not(:focus){--bs-form-switch-bg: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3e%3ccircle r='3' fill='rgba%28255, 255, 255, 0.25%29'/%3e%3c/svg%3e")}.was-validated .form-control:valid,.form-control.is-valid{border-color:var(--bs-form-valid-border-color);padding-right:calc(1.5em + .75rem);background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3e%3cpath fill='%23198754' d='M2.3 6.73.6 4.53c-.4-1.04.46-1.4 1.1-.8l1.1 1.4 3.4-3.8c.6-.63 1.6-.27 1.2.7l-4 4.6c-.43.5-.8.4-1.1.1z'/%3e%3c/svg%3e");background-repeat:no-repeat;background-position:right calc(.375em + .1875rem) center;background-size:calc(.75em + .375rem) calc(.75em + .375rem)}.was-validated .form-select:valid:not([multiple]):not([size]),.was-validated .form-select:valid:not([multiple])[size="1"],.form-select.is-valid:not([multiple]):not([size]),.form-select.is-valid:not([multiple])[size="1"]{--bs-form-select-bg-icon: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3e%3cpath fill='%23198754' dLine truncated
|
||||
* Bootstrap v5.3.3 (https://getbootstrap.com/)
|
||||
* Copyright 2011-2024 The Bootstrap Authors
|
||||
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
|
||||
*/:root,[data-bs-theme=light]{--bs-blue: #0d6efd;--bs-indigo: #6610f2;--bs-purple: #6f42c1;--bs-pink: #d63384;--bs-red: #dc3545;--bs-orange: #fd7e14;--bs-yellow: #ffc107;--bs-green: #198754;--bs-teal: #20c997;--bs-cyan: #0dcaf0;--bs-black: #000;--bs-white: #fff;--bs-gray: #6c757d;--bs-gray-dark: #343a40;--bs-gray-100: #f8f9fa;--bs-gray-200: #e9ecef;--bs-gray-300: #dee2e6;--bs-gray-400: #ced4da;--bs-gray-500: #adb5bd;--bs-gray-600: #6c757d;--bs-gray-700: #495057;--bs-gray-800: #343a40;--bs-gray-900: #212529;--bs-primary: #e86a92;--bs-secondary: #3e92cc;--bs-success: #198754;--bs-info: #0dcaf0;--bs-warning: #ffc107;--bs-danger: #dc3545;--bs-light: #edf2f4;--bs-dark: #2b2d42;--bs-gray: #adb5bd;--bs-dark-accented: #252638;--bs-rich-black: #2d3543;--bs-primary-rgb: 232, 106, 146;--bs-secondary-rgb: 62, 146, 204;--bs-success-rgb: 25, 135, 84;--bs-info-rgb: 13, 202, 240;--bs-warning-rgb: 255, 193, 7;--bs-danger-rgb: 220, 53, 69;--bs-light-rgb: 237, 242, 244;--bs-dark-rgb: 43, 45, 66;--bs-gray-rgb: 173, 181, 189;--bs-dark-accented-rgb: 37, 38, 56;--bs-rich-black-rgb: 45, 53, 67;--bs-primary-text-emphasis: #5d2a3a;--bs-secondary-text-emphasis: #193a52;--bs-success-text-emphasis: #0a3622;--bs-info-text-emphasis: #055160;--bs-warning-text-emphasis: #664d03;--bs-danger-text-emphasis: #58151c;--bs-light-text-emphasis: #495057;--bs-dark-text-emphasis: #495057;--bs-primary-bg-subtle: #fae1e9;--bs-secondary-bg-subtle: #d8e9f5;--bs-success-bg-subtle: #d1e7dd;--bs-info-bg-subtle: #cff4fc;--bs-warning-bg-subtle: #fff3cd;--bs-danger-bg-subtle: #f8d7da;--bs-light-bg-subtle: #fcfcfd;--bs-dark-bg-subtle: #ced4da;--bs-primary-border-subtle: #f6c3d3;--bs-secondary-border-subtle: #b2d3eb;--bs-success-border-subtle: #a3cfbb;--bs-info-border-subtle: #9eeaf9;--bs-warning-border-subtle: #ffe69c;--bs-danger-border-subtle: #f1aeb5;--bs-light-border-subtle: #e9ecef;--bs-dark-border-subtle: #adb5bd;--bs-white-rgb: 255, 255, 255;--bs-black-rgb: 0, 0, 0;--bs-font-sans-serif: system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", "Noto Sans", "Liberation Sans", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";--bs-font-monospace: SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;--bs-gradient: linear-gradient(180deg, rgba(255, 255, 255, .15), rgba(255, 255, 255, 0));--bs-body-font-family: var(--bs-font-sans-serif);--bs-body-font-size: 1rem;--bs-body-font-weight: 400;--bs-body-line-height: 1.5;--bs-body-color: #212529;--bs-body-color-rgb: 33, 37, 41;--bs-body-bg: #edf2f4;--bs-body-bg-rgb: 237, 242, 244;--bs-emphasis-color: #000;--bs-emphasis-color-rgb: 0, 0, 0;--bs-secondary-color: rgba(33, 37, 41, .75);--bs-secondary-color-rgb: 33, 37, 41;--bs-secondary-bg: #d5dadc;--bs-secondary-bg-rgb: 213, 218, 220;--bs-tertiary-color: rgba(33, 37, 41, .5);--bs-tertiary-color-rgb: 33, 37, 41;--bs-tertiary-bg: #f8f9fa;--bs-tertiary-bg-rgb: 248, 249, 250;--bs-heading-color: inherit;--bs-link-color: #e86a92;--bs-link-color-rgb: 232, 106, 146;--bs-link-decoration: underline;--bs-link-hover-color: #ba5575;--bs-link-hover-color-rgb: 186, 85, 117;--bs-code-color: #d63384;--bs-highlight-color: #212529;--bs-highlight-bg: #fff3cd;--bs-border-width: 1px;--bs-border-style: solid;--bs-border-color: #dee2e6;--bs-border-color-translucent: rgba(0, 0, 0, .175);--bs-border-radius: .375rem;--bs-border-radius-sm: .25rem;--bs-border-radius-lg: .5rem;--bs-border-radius-xl: 1rem;--bs-border-radius-xxl: 2rem;--bs-border-radius-2xl: var(--bs-border-radius-xxl);--bs-border-radius-pill: 50rem;--bs-box-shadow: 0 .5rem 1rem rgba(0, 0, 0, .15);--bs-box-shadow-sm: 0 .125rem .25rem rgba(0, 0, 0, .075);--bs-box-shadow-lg: 0 1rem 3rem rgba(0, 0, 0, .175);--bs-box-shadow-inset: inset 0 1px 2px rgba(0, 0, 0, .075);--bs-focus-ring-width: .25rem;--bs-focus-ring-opacity: .25;--bs-focus-ring-color: rgba(232, 106, 146, .25);--bs-form-valid-color: #198754;--bs-form-valid-border-color: #198754;--bs-form-invalid-color: #dc3545;--bs-form-invalid-border-color: #dc3545}[data-bs-theme=dark]{color-scheme:dark;--bs-body-color: #dee2e6;--bs-body-color-rgb: 222, 226, 230;--bs-body-bg: #2b2d42;--bs-body-bg-rgb: 43, 45, 66;--bs-emphasis-color: #fff;--bs-emphasis-color-rgb: 255, 255, 255;--bs-secondary-color: rgba(222, 226, 230, .75);--bs-secondary-color-rgb: 222, 226, 230;--bs-secondary-bg: #252638;--bs-secondary-bg-rgb: 37, 38, 56;--bs-tertiary-color: rgba(222, 226, 230, .5);--bs-tertiary-color-rgb: 222, 226, 230;--bs-tertiary-bg: #2b3035;--bs-tertiary-bg-rgb: 43, 48, 53;--bs-primary-text-emphasis: #f1a6be;--bs-secondary-text-emphasis: #8bbee0;--bs-success-text-emphasis: #75b798;--bs-info-text-emphasis: #6edff6;--bs-warning-text-emphasis: #ffda6a;--bs-danger-text-emphasis: #ea868f;--bs-light-text-emphasis: #f8f9fa;--bs-dark-text-emphasis: #dee2e6;--bs-primary-bg-subtle: #2e151d;--bs-secondary-bg-subtle: #0c1d29;--bs-success-bg-subtle: #051b11;--bs-info-bg-subtle: #032830;--bs-warning-bg-subtle: #332701;--bs-danger-bg-Line truncated
|
||||
@@ -0,0 +1,813 @@
|
||||
(function(){const t=document.createElement("link").relList;if(t&&t.supports&&t.supports("modulepreload"))return;for(const s of document.querySelectorAll('link[rel="modulepreload"]'))r(s);new MutationObserver(s=>{for(const i of s)if(i.type==="childList")for(const o of i.addedNodes)o.tagName==="LINK"&&o.rel==="modulepreload"&&r(o)}).observe(document,{childList:!0,subtree:!0});function n(s){const i={};return s.integrity&&(i.integrity=s.integrity),s.referrerPolicy&&(i.referrerPolicy=s.referrerPolicy),s.crossOrigin==="use-credentials"?i.credentials="include":s.crossOrigin==="anonymous"?i.credentials="omit":i.credentials="same-origin",i}function r(s){if(s.ep)return;s.ep=!0;const i=n(s);fetch(s.href,i)}})();/**
|
||||
* @vue/shared v3.4.29
|
||||
* (c) 2018-present Yuxi (Evan) You and Vue contributors
|
||||
* @license MIT
|
||||
**//*! #__NO_SIDE_EFFECTS__ */function Fl(e,t){const n=new Set(e.split(","));return r=>n.has(r)}const ke={},Mr=[],Ct=()=>{},h_=()=>!1,go=e=>e.charCodeAt(0)===111&&e.charCodeAt(1)===110&&(e.charCodeAt(2)>122||e.charCodeAt(2)<97),jl=e=>e.startsWith("onUpdate:"),Ze=Object.assign,Ul=(e,t)=>{const n=e.indexOf(t);n>-1&&e.splice(n,1)},p_=Object.prototype.hasOwnProperty,we=(e,t)=>p_.call(e,t),ce=Array.isArray,Fr=e=>_o(e)==="[object Map]",mm=e=>_o(e)==="[object Set]",he=e=>typeof e=="function",Ge=e=>typeof e=="string",br=e=>typeof e=="symbol",Fe=e=>e!==null&&typeof e=="object",hm=e=>(Fe(e)||he(e))&&he(e.then)&&he(e.catch),pm=Object.prototype.toString,_o=e=>pm.call(e),g_=e=>_o(e).slice(8,-1),gm=e=>_o(e)==="[object Object]",Hl=e=>Ge(e)&&e!=="NaN"&&e[0]!=="-"&&""+parseInt(e,10)===e,Es=Fl(",key,ref,ref_for,ref_key,onVnodeBeforeMount,onVnodeMounted,onVnodeBeforeUpdate,onVnodeUpdated,onVnodeBeforeUnmount,onVnodeUnmounted"),vo=e=>{const t=Object.create(null);return n=>t[n]||(t[n]=e(n))},__=/-(\w)/g,Xt=vo(e=>e.replace(__,(t,n)=>n?n.toUpperCase():"")),v_=/\B([A-Z])/g,rs=vo(e=>e.replace(v_,"-$1").toLowerCase()),bo=vo(e=>e.charAt(0).toUpperCase()+e.slice(1)),Qo=vo(e=>e?`on${bo(e)}`:""),Rn=(e,t)=>!Object.is(e,t),Di=(e,...t)=>{for(let n=0;n<e.length;n++)e[n](...t)},_m=(e,t,n,r=!1)=>{Object.defineProperty(e,t,{configurable:!0,enumerable:!1,writable:r,value:n})},Fa=e=>{const t=parseFloat(e);return isNaN(t)?e:t};let tu;const vm=()=>tu||(tu=typeof globalThis<"u"?globalThis:typeof self<"u"?self:typeof window<"u"?window:typeof global<"u"?global:{});function Zn(e){if(ce(e)){const t={};for(let n=0;n<e.length;n++){const r=e[n],s=Ge(r)?w_(r):Zn(r);if(s)for(const i in s)t[i]=s[i]}return t}else if(Ge(e)||Fe(e))return e}const b_=/;(?![^(]*\))/g,y_=/:([^]+)/,E_=/\/\*[^]*?\*\//g;function w_(e){const t={};return e.replace(E_,"").split(b_).forEach(n=>{if(n){const r=n.split(y_);r.length>1&&(t[r[0].trim()]=r[1].trim())}}),t}function Nt(e){let t="";if(Ge(e))t=e;else if(ce(e))for(let n=0;n<e.length;n++){const r=Nt(e[n]);r&&(t+=r+" ")}else if(Fe(e))for(const n in e)e[n]&&(t+=n+" ");return t.trim()}const A_="itemscope,allowfullscreen,formnovalidate,ismap,nomodule,novalidate,readonly",T_=Fl(A_);function bm(e){return!!e||e===""}const ue=e=>Ge(e)?e:e==null?"":ce(e)||Fe(e)&&(e.toString===pm||!he(e.toString))?JSON.stringify(e,ym,2):String(e),ym=(e,t)=>t&&t.__v_isRef?ym(e,t.value):Fr(t)?{[`Map(${t.size})`]:[...t.entries()].reduce((n,[r,s],i)=>(n[Zo(r,i)+" =>"]=s,n),{})}:mm(t)?{[`Set(${t.size})`]:[...t.values()].map(n=>Zo(n))}:br(t)?Zo(t):Fe(t)&&!ce(t)&&!gm(t)?String(t):t,Zo=(e,t="")=>{var n;return br(e)?`Symbol(${(n=e.description)!=null?n:t})`:e};/**
|
||||
* @vue/reactivity v3.4.29
|
||||
* (c) 2018-present Yuxi (Evan) You and Vue contributors
|
||||
* @license MIT
|
||||
**/let yt;class Em{constructor(t=!1){this.detached=t,this._active=!0,this.effects=[],this.cleanups=[],this.parent=yt,!t&&yt&&(this.index=(yt.scopes||(yt.scopes=[])).push(this)-1)}get active(){return this._active}run(t){if(this._active){const n=yt;try{return yt=this,t()}finally{yt=n}}}on(){yt=this}off(){yt=this.parent}stop(t){if(this._active){let n,r;for(n=0,r=this.effects.length;n<r;n++)this.effects[n].stop();for(n=0,r=this.cleanups.length;n<r;n++)this.cleanups[n]();if(this.scopes)for(n=0,r=this.scopes.length;n<r;n++)this.scopes[n].stop(!0);if(!this.detached&&this.parent&&!t){const s=this.parent.scopes.pop();s&&s!==this&&(this.parent.scopes[this.index]=s,s.index=this.index)}this.parent=void 0,this._active=!1}}}function Vl(e){return new Em(e)}function O_(e,t=yt){t&&t.active&&t.effects.push(e)}function wm(){return yt}function S_(e){yt&&yt.cleanups.push(e)}let ar;class Bl{constructor(t,n,r,s){this.fn=t,this.trigger=n,this.scheduler=r,this.active=!0,this.deps=[],this._dirtyLevel=5,this._trackId=0,this._runnings=0,this._shouldSchedule=!1,this._depsLength=0,O_(this,s)}get dirty(){if(this._dirtyLevel===2)return!1;if(this._dirtyLevel===3||this._dirtyLevel===4){this._dirtyLevel=1,Un();for(let t=0;t<this._depsLength;t++){const n=this.deps[t];if(n.computed){if(n.computed.effect._dirtyLevel===2)return!0;if(C_(n.computed),this._dirtyLevel>=5)break}}this._dirtyLevel===1&&(this._dirtyLevel=0),Hn()}return this._dirtyLevel>=5}set dirty(t){this._dirtyLevel=t?5:0}run(){if(this._dirtyLevel=0,!this.active)return this.fn();let t=Ln,n=ar;try{return Ln=!0,ar=this,this._runnings++,nu(this),this.fn()}finally{ru(this),this._runnings--,ar=n,Ln=t}}stop(){this.active&&(nu(this),ru(this),this.onStop&&this.onStop(),this.active=!1)}}function C_(e){return e.value}function nu(e){e._trackId++,e._depsLength=0}function ru(e){if(e.deps.length>e._depsLength){for(let t=e._depsLength;t<e.deps.length;t++)Am(e.deps[t],e);e.deps.length=e._depsLength}}function Am(e,t){const n=e.get(t);n!==void 0&&t._trackId!==n&&(e.delete(t),e.size===0&&e.cleanup())}let Ln=!0,ja=0;const Tm=[];function Un(){Tm.push(Ln),Ln=!1}function Hn(){const e=Tm.pop();Ln=e===void 0?!0:e}function Wl(){ja++}function Yl(){for(ja--;!ja&&Ua.length;)Ua.shift()()}function Om(e,t,n){if(t.get(e)!==e._trackId){t.set(e,e._trackId);const r=e.deps[e._depsLength];r!==t?(r&&Am(r,e),e.deps[e._depsLength++]=t):e._depsLength++}}const Ua=[];function Sm(e,t,n){Wl();for(const r of e.keys()){if(!e.computed&&r.computed&&e.get(r)===r._trackId&&r._runnings>0){r._dirtyLevel=2;continue}let s;r._dirtyLevel<t&&(s??(s=e.get(r)===r._trackId))&&(r._shouldSchedule||(r._shouldSchedule=r._dirtyLevel===0),r.computed&&r._dirtyLevel===2&&(r._shouldSchedule=!0),r._dirtyLevel=t),r._shouldSchedule&&(s??(s=e.get(r)===r._trackId))&&(r.trigger(),(!r._runnings||r.allowRecurse)&&r._dirtyLevel!==3&&(r._shouldSchedule=!1,r.scheduler&&Ua.push(r.scheduler)))}Yl()}const Cm=(e,t)=>{const n=new Map;return n.cleanup=e,n.computed=t,n},Xi=new WeakMap,lr=Symbol(""),Ha=Symbol("");function _t(e,t,n){if(Ln&&ar){let r=Xi.get(e);r||Xi.set(e,r=new Map);let s=r.get(n);s||r.set(n,s=Cm(()=>r.delete(n))),Om(ar,s)}}function on(e,t,n,r,s,i){const o=Xi.get(e);if(!o)return;let a=[];if(t==="clear")a=[...o.values()];else if(n==="length"&&ce(e)){const l=Number(r);o.forEach((u,c)=>{(c==="length"||!br(c)&&c>=l)&&a.push(u)})}else switch(n!==void 0&&a.push(o.get(n)),t){case"add":ce(e)?Hl(n)&&a.push(o.get("length")):(a.push(o.get(lr)),Fr(e)&&a.push(o.get(Ha)));break;case"delete":ce(e)||(a.push(o.get(lr)),Fr(e)&&a.push(o.get(Ha)));break;case"set":Fr(e)&&a.push(o.get(lr));break}Wl();for(const l of a)l&&Sm(l,5);Yl()}function N_(e,t){const n=Xi.get(e);return n&&n.get(t)}const L_=Fl("__proto__,__v_isRef,__isVue"),Nm=new Set(Object.getOwnPropertyNames(Symbol).filter(e=>e!=="arguments"&&e!=="caller").map(e=>Symbol[e]).filter(br)),su=I_();function I_(){const e={};return["includes","indexOf","lastIndexOf"].forEach(t=>{e[t]=function(...n){const r=Ae(this);for(let i=0,o=this.length;i<o;i++)_t(r,"get",i+"");const s=r[t](...n);return s===-1||s===!1?r[t](...n.map(Ae)):s}}),["push","pop","shift","unshift","splice"].forEach(t=>{e[t]=function(...n){Un(),Wl();const r=Ae(this)[t].apply(this,n);return Yl(),Hn(),r}}),e}function P_(e){br(e)||(e=String(e));const t=Ae(this);return _t(t,"has",e),t.hasOwnProperty(e)}class Lm{constructor(t=!1,n=!1){this._isReadonly=t,this._isShallow=n}get(t,n,r){const s=this._isReadonly,i=this._isShallow;if(n==="__v_isReactive")return!s;if(n==="__v_isReadonly")return s;if(n==="__v_isShallow")return i;if(n==="__v_raw")return r===(s?i?W_:xm:i?Rm:Pm).get(t)||Object.getPrototypeOf(t)===Object.getPrototypeOf(r)?t:void 0;const o=ce(t);if(!s){if(o&&we(su,n))return Reflect.get(su,n,r);if(n==="hasOwnProperty")return P_}const a=Reflect.get(t,n,r);return(br(n)?Nm.has(n):L_(n))||(s||_t(t,"get",n),i)?a:He(a)?o&&Hl(n)?a:a.value:Fe(a)?s?$m(a):Vn(a):a}}class Im extends Lm{constructor(t=!1){super(!1,t)}set(t,n,r,s){let i=t[n];if(!this._isShallow){const l=Vr(i);if(!Ji(rLine truncated
|
||||
* @vue/runtime-core v3.4.29
|
||||
* (c) 2018-present Yuxi (Evan) You and Vue contributors
|
||||
* @license MIT
|
||||
**/function Pn(e,t,n,r){try{return r?e(...r):e()}catch(s){Eo(s,t,n)}}function Mt(e,t,n,r){if(he(e)){const s=Pn(e,t,n,r);return s&&hm(s)&&s.catch(i=>{Eo(i,t,n)}),s}if(ce(e)){const s=[];for(let i=0;i<e.length;i++)s.push(Mt(e[i],t,n,r));return s}}function Eo(e,t,n,r=!0){const s=t?t.vnode:null;if(t){let i=t.parent;const o=t.proxy,a=`https://vuejs.org/error-reference/#runtime-${n}`;for(;i;){const u=i.ec;if(u){for(let c=0;c<u.length;c++)if(u[c](e,o,a)===!1)return}i=i.parent}const l=t.appContext.config.errorHandler;if(l){Un(),Pn(l,null,10,[e,o,a]),Hn();return}}Z_(e,n,s,r)}function Z_(e,t,n,r=!0){console.error(e)}let Ds=!1,Va=!1;const rt=[];let Yt=0;const jr=[];let An=null,Qn=0;const Hm=Promise.resolve();let Ql=null;function Ms(e){const t=Ql||Hm;return e?t.then(this?e.bind(this):e):t}function ev(e){let t=Yt+1,n=rt.length;for(;t<n;){const r=t+n>>>1,s=rt[r],i=Fs(s);i<e||i===e&&s.pre?t=r+1:n=r}return t}function Zl(e){(!rt.length||!rt.includes(e,Ds&&e.allowRecurse?Yt+1:Yt))&&(e.id==null?rt.push(e):rt.splice(ev(e.id),0,e),Vm())}function Vm(){!Ds&&!Va&&(Va=!0,Ql=Hm.then(Wm))}function tv(e){const t=rt.indexOf(e);t>Yt&&rt.splice(t,1)}function nv(e){ce(e)?jr.push(...e):(!An||!An.includes(e,e.allowRecurse?Qn+1:Qn))&&jr.push(e),Vm()}function cu(e,t,n=Ds?Yt+1:0){for(;n<rt.length;n++){const r=rt[n];if(r&&r.pre){if(e&&r.id!==e.uid)continue;rt.splice(n,1),n--,r()}}}function Bm(e){if(jr.length){const t=[...new Set(jr)].sort((n,r)=>Fs(n)-Fs(r));if(jr.length=0,An){An.push(...t);return}for(An=t,Qn=0;Qn<An.length;Qn++){const n=An[Qn];n.active!==!1&&n()}An=null,Qn=0}}const Fs=e=>e.id==null?1/0:e.id,rv=(e,t)=>{const n=Fs(e)-Fs(t);if(n===0){if(e.pre&&!t.pre)return-1;if(t.pre&&!e.pre)return 1}return n};function Wm(e){Va=!1,Ds=!0,rt.sort(rv);try{for(Yt=0;Yt<rt.length;Yt++){const t=rt[Yt];t&&t.active!==!1&&Pn(t,null,14)}}finally{Yt=0,rt.length=0,Bm(),Ds=!1,Ql=null,(rt.length||jr.length)&&Wm()}}function sv(e,t,...n){if(e.isUnmounted)return;const r=e.vnode.props||ke;let s=n;const i=t.startsWith("update:"),o=i&&t.slice(7);if(o&&o in r){const c=`${o==="modelValue"?"model":o}Modifiers`,{number:f,trim:d}=r[c]||ke;d&&(s=n.map(m=>Ge(m)?m.trim():m)),f&&(s=n.map(Fa))}let a,l=r[a=Qo(t)]||r[a=Qo(Xt(t))];!l&&i&&(l=r[a=Qo(rs(t))]),l&&Mt(l,e,6,s);const u=r[a+"Once"];if(u){if(!e.emitted)e.emitted={};else if(e.emitted[a])return;e.emitted[a]=!0,Mt(u,e,6,s)}}function Ym(e,t,n=!1){const r=t.emitsCache,s=r.get(e);if(s!==void 0)return s;const i=e.emits;let o={},a=!1;if(!he(e)){const l=u=>{const c=Ym(u,t,!0);c&&(a=!0,Ze(o,c))};!n&&t.mixins.length&&t.mixins.forEach(l),e.extends&&l(e.extends),e.mixins&&e.mixins.forEach(l)}return!i&&!a?(Fe(e)&&r.set(e,null),null):(ce(i)?i.forEach(l=>o[l]=null):Ze(o,i),Fe(e)&&r.set(e,o),o)}function wo(e,t){return!e||!go(t)?!1:(t=t.slice(2).replace(/Once$/,""),we(e,t[0].toLowerCase()+t.slice(1))||we(e,rs(t))||we(e,t))}let ct=null,Ao=null;function Qi(e){const t=ct;return ct=e,Ao=e&&e.type.__scopeId||null,t}function iv(e){Ao=e}function ov(){Ao=null}function er(e,t=ct,n){if(!t||e._n)return e;const r=(...s)=>{r._d&&Eu(-1);const i=Qi(t);let o;try{o=e(...s)}finally{Qi(i),r._d&&Eu(1)}return o};return r._n=!0,r._c=!0,r._d=!0,r}function ea(e){const{type:t,vnode:n,proxy:r,withProxy:s,propsOptions:[i],slots:o,attrs:a,emit:l,render:u,renderCache:c,props:f,data:d,setupState:m,ctx:p,inheritAttrs:v}=e,y=Qi(e);let w,S;try{if(n.shapeFlag&4){const A=s||r,C=A;w=Wt(u.call(C,A,c,f,m,d,p)),S=a}else{const A=t;w=Wt(A.length>1?A(f,{attrs:a,slots:o,emit:l}):A(f,null)),S=t.props?a:av(a)}}catch(A){Ts.length=0,Eo(A,e,1),w=ye(dr)}let E=w;if(S&&v!==!1){const A=Object.keys(S),{shapeFlag:C}=E;A.length&&C&7&&(i&&A.some(jl)&&(S=lv(S,i)),E=Br(E,S,!1,!0))}return n.dirs&&(E=Br(E,null,!1,!0),E.dirs=E.dirs?E.dirs.concat(n.dirs):n.dirs),n.transition&&(E.transition=n.transition),w=E,Qi(y),w}const av=e=>{let t;for(const n in e)(n==="class"||n==="style"||go(n))&&((t||(t={}))[n]=e[n]);return t},lv=(e,t)=>{const n={};for(const r in e)(!jl(r)||!(r.slice(9)in t))&&(n[r]=e[r]);return n};function cv(e,t,n){const{props:r,children:s,component:i}=e,{props:o,children:a,patchFlag:l}=t,u=i.emitsOptions;if(t.dirs||t.transition)return!0;if(n&&l>=0){if(l&1024)return!0;if(l&16)return r?uu(r,o,u):!!o;if(l&8){const c=t.dynamicProps;for(let f=0;f<c.length;f++){const d=c[f];if(o[d]!==r[d]&&!wo(u,d))return!0}}}else return(s||a)&&(!a||!a.$stable)?!0:r===o?!1:r?o?uu(r,o,u):!0:!!o;return!1}function uu(e,t,n){const r=Object.keys(t);if(r.length!==Object.keys(e).length)return!0;for(let s=0;s<r.length;s++){const i=r[s];if(t[i]!==e[i]&&!wo(n,i))return!0}return!1}function uv({vnode:e,parent:t},n){for(;t;){const r=t.subTree;if(r.suspense&&r.suspense.activeBranch===e&&(r.el=e.el),r===e)(e=t.vnode).el=n,t=t.parent;else break}}const fv="components";function ec(e,t){return mv(fv,e,!0,t)||e}const dv=Symbol.for("v-ndc");function mv(e,t,n=!0,r=!1){const s=ct||Je;if(s){const i=s.type;{const a=sb(i,!1);if(a&&(a===t||a===Xt(t)||a===bo(Xt(t))))return i}const o=fu(s[e]||i[e],t)||fu(s.appContext[e],t);return!o&&r?i:o}}f
Line truncated
|
||||
* @vue/runtime-dom v3.4.29
|
||||
* (c) 2018-present Yuxi (Evan) You and Vue contributors
|
||||
* @license MIT
|
||||
**/const ab="http://www.w3.org/2000/svg",lb="http://www.w3.org/1998/Math/MathML",nn=typeof document<"u"?document:null,Ou=nn&&nn.createElement("template"),cb={insert:(e,t,n)=>{t.insertBefore(e,n||null)},remove:e=>{const t=e.parentNode;t&&t.removeChild(e)},createElement:(e,t,n,r)=>{const s=t==="svg"?nn.createElementNS(ab,e):t==="mathml"?nn.createElementNS(lb,e):n?nn.createElement(e,{is:n}):nn.createElement(e);return e==="select"&&r&&r.multiple!=null&&s.setAttribute("multiple",r.multiple),s},createText:e=>nn.createTextNode(e),createComment:e=>nn.createComment(e),setText:(e,t)=>{e.nodeValue=t},setElementText:(e,t)=>{e.textContent=t},parentNode:e=>e.parentNode,nextSibling:e=>e.nextSibling,querySelector:e=>nn.querySelector(e),setScopeId(e,t){e.setAttribute(t,"")},insertStaticContent(e,t,n,r,s,i){const o=n?n.previousSibling:t.lastChild;if(s&&(s===i||s.nextSibling))for(;t.insertBefore(s.cloneNode(!0),n),!(s===i||!(s=s.nextSibling)););else{Ou.innerHTML=r==="svg"?`<svg>${e}</svg>`:r==="mathml"?`<math>${e}</math>`:e;const a=Ou.content;if(r==="svg"||r==="mathml"){const l=a.firstChild;for(;l.firstChild;)a.appendChild(l.firstChild);a.removeChild(l)}t.insertBefore(a,n)}return[o?o.nextSibling:t.firstChild,n?n.previousSibling:t.lastChild]}},ub=Symbol("_vtc");function fb(e,t,n){const r=e[ub];r&&(t=(t?[t,...r]:[...r]).join(" ")),t==null?e.removeAttribute("class"):n?e.setAttribute("class",t):e.className=t}const Su=Symbol("_vod"),db=Symbol("_vsh"),mb=Symbol(""),hb=/(^|;)\s*display\s*:/;function pb(e,t,n){const r=e.style,s=Ge(n);let i=!1;if(n&&!s){if(t)if(Ge(t))for(const o of t.split(";")){const a=o.slice(0,o.indexOf(":")).trim();n[a]==null&&Ui(r,a,"")}else for(const o in t)n[o]==null&&Ui(r,o,"");for(const o in n)o==="display"&&(i=!0),Ui(r,o,n[o])}else if(s){if(t!==n){const o=r[mb];o&&(n+=";"+o),r.cssText=n,i=hb.test(n)}}else t&&e.removeAttribute("style");Su in e&&(e[Su]=i?r.display:"",e[db]&&(r.display="none"))}const Cu=/\s*!important$/;function Ui(e,t,n){if(ce(n))n.forEach(r=>Ui(e,t,r));else if(n==null&&(n=""),t.startsWith("--"))e.setProperty(t,n);else{const r=gb(e,t);Cu.test(n)?e.setProperty(rs(r),n.replace(Cu,""),"important"):e[r]=n}}const Nu=["Webkit","Moz","ms"],sa={};function gb(e,t){const n=sa[t];if(n)return n;let r=Xt(t);if(r!=="filter"&&r in e)return sa[t]=r;r=bo(r);for(let s=0;s<Nu.length;s++){const i=Nu[s]+r;if(i in e)return sa[t]=i}return t}const Lu="http://www.w3.org/1999/xlink";function Iu(e,t,n,r,s,i=T_(t)){r&&t.startsWith("xlink:")?n==null?e.removeAttributeNS(Lu,t.slice(6,t.length)):e.setAttributeNS(Lu,t,n):n==null||i&&!bm(n)?e.removeAttribute(t):e.setAttribute(t,i?"":String(n))}function _b(e,t,n,r,s,i,o){if(t==="innerHTML"||t==="textContent"){r&&o(r,s,i),e[t]=n??"";return}const a=e.tagName;if(t==="value"&&a!=="PROGRESS"&&!a.includes("-")){const u=a==="OPTION"?e.getAttribute("value")||"":e.value,c=n==null?"":String(n);(u!==c||!("_value"in e))&&(e.value=c),n==null&&e.removeAttribute(t),e._value=n;return}let l=!1;if(n===""||n==null){const u=typeof e[t];u==="boolean"?n=bm(n):n==null&&u==="string"?(n="",l=!0):u==="number"&&(n=0,l=!0)}try{e[t]=n}catch{}l&&e.removeAttribute(t)}function Cr(e,t,n,r){e.addEventListener(t,n,r)}function vb(e,t,n,r){e.removeEventListener(t,n,r)}const Pu=Symbol("_vei");function bb(e,t,n,r,s=null){const i=e[Pu]||(e[Pu]={}),o=i[t];if(r&&o)o.value=r;else{const[a,l]=yb(t);if(r){const u=i[t]=Ab(r,s);Cr(e,a,u,l)}else o&&(vb(e,a,o,l),i[t]=void 0)}}const Ru=/(?:Once|Passive|Capture)$/;function yb(e){let t;if(Ru.test(e)){t={};let r;for(;r=e.match(Ru);)e=e.slice(0,e.length-r[0].length),t[r[0].toLowerCase()]=!0}return[e[2]===":"?e.slice(3):rs(e.slice(2)),t]}let ia=0;const Eb=Promise.resolve(),wb=()=>ia||(Eb.then(()=>ia=0),ia=Date.now());function Ab(e,t){const n=r=>{if(!r._vts)r._vts=Date.now();else if(r._vts<=n.attached)return;Mt(Tb(r,n.value),t,5,[r])};return n.value=e,n.attached=wb(),n}function Tb(e,t){if(ce(t)){const n=e.stopImmediatePropagation;return e.stopImmediatePropagation=()=>{n.call(e),e._stopped=!0},t.map(r=>s=>!s._stopped&&r&&r(s))}else return t}const xu=e=>e.charCodeAt(0)===111&&e.charCodeAt(1)===110&&e.charCodeAt(2)>96&&e.charCodeAt(2)<123,Ob=(e,t,n,r,s,i,o,a,l)=>{const u=s==="svg";t==="class"?fb(e,r,u):t==="style"?pb(e,n,r):go(t)?jl(t)||bb(e,t,n,r,o):(t[0]==="."?(t=t.slice(1),!0):t[0]==="^"?(t=t.slice(1),!1):Sb(e,t,r,u))?(_b(e,t,r,i,o,a,l),(t==="value"||t==="checked"||t==="selected")&&Iu(e,t,r,u,o,t!=="value")):(t==="true-value"?e._trueValue=r:t==="false-value"&&(e._falseValue=r),Iu(e,t,r,u))};function Sb(e,t,n,r){if(r)return!!(t==="innerHTML"||t==="textContent"||t in e&&xu(t)&&he(n));if(t==="spellcheck"||t==="draggable"||t==="translate"||t==="form"||t==="list"&&e.tagName==="INPUT"||t==="type"&&e.tagName==="TEXTAREA")return!1;if(t==="width"||t==="height"){const s=e.tagName;if(s==="IMG"||s==="VIDEO"||s==="CANVAS"||s==="SOURCE")return!1}return xu(t)&&Ge(n)?!1:t in e}const ku=e=>{const t=e.props["onUpdate:modelValue"]||!1;return ce(t)?n=>Di(t,n):t};function Cb(e){e.target.composing=!0}fun
Line truncated
|
||||
* pinia v2.1.7
|
||||
* (c) 2023 Eduardo San Martin Morote
|
||||
* @license MIT
|
||||
*/let ph;const No=e=>ph=e,gh=Symbol();function Xa(e){return e&&typeof e=="object"&&Object.prototype.toString.call(e)==="[object Object]"&&typeof e.toJSON!="function"}var Ss;(function(e){e.direct="direct",e.patchObject="patch object",e.patchFunction="patch function"})(Ss||(Ss={}));function kb(){const e=Vl(!0),t=e.run(()=>ge({}));let n=[],r=[];const s=ql({install(i){No(s),s._a=i,i.provide(gh,s),i.config.globalProperties.$pinia=s,r.forEach(o=>n.push(o)),r=[]},use(i){return!this._a&&!xb?r.push(i):n.push(i),this},_p:n,_a:null,_e:e,_s:new Map,state:t});return s}const _h=()=>{};function Mu(e,t,n,r=_h){e.push(t);const s=()=>{const i=e.indexOf(t);i>-1&&(e.splice(i,1),r())};return!n&&wm()&&S_(s),s}function Tr(e,...t){e.slice().forEach(n=>{n(...t)})}const $b=e=>e();function Ja(e,t){e instanceof Map&&t instanceof Map&&t.forEach((n,r)=>e.set(r,n)),e instanceof Set&&t instanceof Set&&t.forEach(e.add,e);for(const n in t){if(!t.hasOwnProperty(n))continue;const r=t[n],s=e[n];Xa(s)&&Xa(r)&&e.hasOwnProperty(n)&&!He(r)&&!In(r)?e[n]=Ja(s,r):e[n]=r}return e}const Db=Symbol();function Mb(e){return!Xa(e)||!e.hasOwnProperty(Db)}const{assign:wn}=Object;function Fb(e){return!!(He(e)&&e.effect)}function jb(e,t,n,r){const{state:s,actions:i,getters:o}=t,a=n.state.value[e];let l;function u(){a||(n.state.value[e]=s?s():{});const c=X_(n.state.value[e]);return wn(c,i,Object.keys(o||{}).reduce((f,d)=>(f[d]=ql(ne(()=>{No(n);const m=n._s.get(e);return o[d].call(m,m)})),f),{}))}return l=vh(e,u,t,n,r,!0),l}function vh(e,t,n={},r,s,i){let o;const a=wn({actions:{}},n),l={deep:!0};let u,c,f=[],d=[],m;const p=r.state.value[e];!i&&!p&&(r.state.value[e]={}),ge({});let v;function y($){let P;u=c=!1,typeof $=="function"?($(r.state.value[e]),P={type:Ss.patchFunction,storeId:e,events:m}):(Ja(r.state.value[e],$),P={type:Ss.patchObject,payload:$,storeId:e,events:m});const q=v=Symbol();Ms().then(()=>{v===q&&(u=!0)}),c=!0,Tr(f,P,r.state.value[e])}const w=i?function(){const{state:P}=n,q=P?P():{};this.$patch(ie=>{wn(ie,q)})}:_h;function S(){o.stop(),f=[],d=[],r._s.delete(e)}function E($,P){return function(){No(r);const q=Array.from(arguments),ie=[],Q=[];function le(ee){ie.push(ee)}function je(ee){Q.push(ee)}Tr(d,{args:q,name:$,store:C,after:le,onError:je});let Ce;try{Ce=P.apply(this&&this.$id===e?this:C,q)}catch(ee){throw Tr(Q,ee),ee}return Ce instanceof Promise?Ce.then(ee=>(Tr(ie,ee),ee)).catch(ee=>(Tr(Q,ee),Promise.reject(ee))):(Tr(ie,Ce),Ce)}}const A={_p:r,$id:e,$onAction:Mu.bind(null,d),$patch:y,$reset:w,$subscribe($,P={}){const q=Mu(f,$,P.detached,()=>ie()),ie=o.run(()=>it(()=>r.state.value[e],Q=>{(P.flush==="sync"?c:u)&&$({storeId:e,type:Ss.direct,events:m},Q)},wn({},l,P)));return q},$dispose:S},C=Vn(A);r._s.set(e,C);const I=(r._a&&r._a.runWithContext||$b)(()=>r._e.run(()=>(o=Vl()).run(t)));for(const $ in I){const P=I[$];if(He(P)&&!Fb(P)||In(P))i||(p&&Mb(P)&&(He(P)?P.value=p[$]:Ja(P,p[$])),r.state.value[e][$]=P);else if(typeof P=="function"){const q=E($,P);I[$]=q,a.actions[$]=P}}return wn(C,I),wn(Ae(C),I),Object.defineProperty(C,"$state",{get:()=>r.state.value[e],set:$=>{y(P=>{wn(P,$)})}}),r._p.forEach($=>{wn(C,o.run(()=>$({store:C,app:r._a,pinia:r,options:a})))}),p&&i&&n.hydrate&&n.hydrate(C.$state,p),u=!0,c=!0,C}function Ub(e,t,n){let r,s;const i=typeof t=="function";r=e,s=i?n:t;function o(a,l){const u=Iv();return a=a||(u?st(gh,null):null),a&&No(a),a=ph,a._s.has(r)||(i?vh(r,t,s,a):jb(r,s,a)),a._s.get(r)}return o.$id=r,o}/*!
|
||||
* shared v9.13.1
|
||||
* (c) 2024 kazuya kawaguchi
|
||||
* Released under the MIT License.
|
||||
*/const to=typeof window<"u",Bn=(e,t=!1)=>t?Symbol.for(e):Symbol(e),Hb=(e,t,n)=>Vb({l:e,k:t,s:n}),Vb=e=>JSON.stringify(e).replace(/\u2028/g,"\\u2028").replace(/\u2029/g,"\\u2029").replace(/\u0027/g,"\\u0027"),Ke=e=>typeof e=="number"&&isFinite(e),Bb=e=>yh(e)==="[object Date]",xn=e=>yh(e)==="[object RegExp]",Lo=e=>fe(e)&&Object.keys(e).length===0,tt=Object.assign;let Fu;const rn=()=>Fu||(Fu=typeof globalThis<"u"?globalThis:typeof self<"u"?self:typeof window<"u"?window:typeof global<"u"?global:{});function ju(e){return e.replace(/</g,"<").replace(/>/g,">").replace(/"/g,""").replace(/'/g,"'")}const Wb=Object.prototype.hasOwnProperty;function no(e,t){return Wb.call(e,t)}const De=Array.isArray,Re=e=>typeof e=="function",G=e=>typeof e=="string",ve=e=>typeof e=="boolean",Se=e=>e!==null&&typeof e=="object",Yb=e=>Se(e)&&Re(e.then)&&Re(e.catch),bh=Object.prototype.toString,yh=e=>bh.call(e),fe=e=>{if(!Se(e))return!1;const t=Object.getPrototypeOf(e);return t===null||t.constructor===Object},Kb=e=>e==null?"":De(e)||fe(e)&&e.toString===bh?JSON.stringify(e,null,2):String(e);function zb(e,t=""){return e.reduce((n,r,s)=>s===0?n+r:n+t+r,"")}function Io(e){let t=e;return()=>++t}function Gb(e,t){typeof console<"u"&&(console.warn("[intlify] "+e),t&&console.warn(t.stack))}const bi=e=>!Se(e)||De(e);function Hi(e,t){if(bi(e)||bi(t))throw new Error("Invalid value");const n=[{src:e,des:t}];for(;n.length;){const{src:r,des:s}=n.pop();Object.keys(r).forEach(i=>{bi(r[i])||bi(s[i])?s[i]=r[i]:n.push({src:r[i],des:s[i]})})}}/*!
|
||||
* message-compiler v9.13.1
|
||||
* (c) 2024 kazuya kawaguchi
|
||||
* Released under the MIT License.
|
||||
*/function qb(e,t,n){return{line:e,column:t,offset:n}}function ro(e,t,n){return{start:e,end:t}}const Xb=/\{([0-9a-zA-Z]+)\}/g;function Eh(e,...t){return t.length===1&&Jb(t[0])&&(t=t[0]),(!t||!t.hasOwnProperty)&&(t={}),e.replace(Xb,(n,r)=>t.hasOwnProperty(r)?t[r]:"")}const wh=Object.assign,Uu=e=>typeof e=="string",Jb=e=>e!==null&&typeof e=="object";function Ah(e,t=""){return e.reduce((n,r,s)=>s===0?n+r:n+t+r,"")}const oc={USE_MODULO_SYNTAX:1,__EXTEND_POINT__:2},Qb={[oc.USE_MODULO_SYNTAX]:"Use modulo before '{{0}}'."};function Zb(e,t,...n){const r=Eh(Qb[e],...n||[]),s={message:String(r),code:e};return t&&(s.location=t),s}const oe={EXPECTED_TOKEN:1,INVALID_TOKEN_IN_PLACEHOLDER:2,UNTERMINATED_SINGLE_QUOTE_IN_PLACEHOLDER:3,UNKNOWN_ESCAPE_SEQUENCE:4,INVALID_UNICODE_ESCAPE_SEQUENCE:5,UNBALANCED_CLOSING_BRACE:6,UNTERMINATED_CLOSING_BRACE:7,EMPTY_PLACEHOLDER:8,NOT_ALLOW_NEST_PLACEHOLDER:9,INVALID_LINKED_FORMAT:10,MUST_HAVE_MESSAGES_IN_PLURAL:11,UNEXPECTED_EMPTY_LINKED_MODIFIER:12,UNEXPECTED_EMPTY_LINKED_KEY:13,UNEXPECTED_LEXICAL_ANALYSIS:14,UNHANDLED_CODEGEN_NODE_TYPE:15,UNHANDLED_MINIFIER_NODE_TYPE:16,__EXTEND_POINT__:17},ey={[oe.EXPECTED_TOKEN]:"Expected token: '{0}'",[oe.INVALID_TOKEN_IN_PLACEHOLDER]:"Invalid token in placeholder: '{0}'",[oe.UNTERMINATED_SINGLE_QUOTE_IN_PLACEHOLDER]:"Unterminated single quote in placeholder",[oe.UNKNOWN_ESCAPE_SEQUENCE]:"Unknown escape sequence: \\{0}",[oe.INVALID_UNICODE_ESCAPE_SEQUENCE]:"Invalid unicode escape sequence: {0}",[oe.UNBALANCED_CLOSING_BRACE]:"Unbalanced closing brace",[oe.UNTERMINATED_CLOSING_BRACE]:"Unterminated closing brace",[oe.EMPTY_PLACEHOLDER]:"Empty placeholder",[oe.NOT_ALLOW_NEST_PLACEHOLDER]:"Not allowed nest placeholder",[oe.INVALID_LINKED_FORMAT]:"Invalid linked format",[oe.MUST_HAVE_MESSAGES_IN_PLURAL]:"Plural must have messages",[oe.UNEXPECTED_EMPTY_LINKED_MODIFIER]:"Unexpected empty linked modifier",[oe.UNEXPECTED_EMPTY_LINKED_KEY]:"Unexpected empty linked key",[oe.UNEXPECTED_LEXICAL_ANALYSIS]:"Unexpected lexical analysis in token: '{0}'",[oe.UNHANDLED_CODEGEN_NODE_TYPE]:"unhandled codegen node type: '{0}'",[oe.UNHANDLED_MINIFIER_NODE_TYPE]:"unhandled mimifier node type: '{0}'"};function is(e,t,n={}){const{domain:r,messages:s,args:i}=n,o=Eh((s||ey)[e]||"",...i||[]),a=new SyntaxError(String(o));return a.code=e,t&&(a.location=t),a.domain=r,a}function ty(e){throw e}const Zt=" ",ny="\r",at=`
|
||||
`,ry="\u2028",sy="\u2029";function iy(e){const t=e;let n=0,r=1,s=1,i=0;const o=I=>t[I]===ny&&t[I+1]===at,a=I=>t[I]===at,l=I=>t[I]===sy,u=I=>t[I]===ry,c=I=>o(I)||a(I)||l(I)||u(I),f=()=>n,d=()=>r,m=()=>s,p=()=>i,v=I=>o(I)||l(I)||u(I)?at:t[I],y=()=>v(n),w=()=>v(n+i);function S(){return i=0,c(n)&&(r++,s=0),o(n)&&n++,n++,s++,t[n]}function E(){return o(n+i)&&i++,i++,t[n+i]}function A(){n=0,r=1,s=1,i=0}function C(I=0){i=I}function O(){const I=n+i;for(;I!==n;)S();i=0}return{index:f,line:d,column:m,peekOffset:p,charAt:v,currentChar:y,currentPeek:w,next:S,peek:E,reset:A,resetPeek:C,skipToPeek:O}}const _n=void 0,oy=".",Hu="'",ay="tokenizer";function ly(e,t={}){const n=t.location!==!1,r=iy(e),s=()=>r.index(),i=()=>qb(r.line(),r.column(),r.index()),o=i(),a=s(),l={currentType:14,offset:a,startLoc:o,endLoc:o,lastType:14,lastOffset:a,lastStartLoc:o,lastEndLoc:o,braceNest:0,inLinked:!1,text:""},u=()=>l,{onError:c}=t;function f(h,_,T,...M){const K=u();if(_.column+=T,_.offset+=T,c){const U=n?ro(K.startLoc,_):null,L=is(h,U,{domain:ay,args:M});c(L)}}function d(h,_,T){h.endLoc=i(),h.currentType=_;const M={type:_};return n&&(M.loc=ro(h.startLoc,h.endLoc)),T!=null&&(M.value=T),M}const m=h=>d(h,14);function p(h,_){return h.currentChar()===_?(h.next(),_):(f(oe.EXPECTED_TOKEN,i(),0,_),"")}function v(h){let _="";for(;h.currentPeek()===Zt||h.currentPeek()===at;)_+=h.currentPeek(),h.peek();return _}function y(h){const _=v(h);return h.skipToPeek(),_}function w(h){if(h===_n)return!1;const _=h.charCodeAt(0);return _>=97&&_<=122||_>=65&&_<=90||_===95}function S(h){if(h===_n)return!1;const _=h.charCodeAt(0);return _>=48&&_<=57}function E(h,_){const{currentType:T}=_;if(T!==2)return!1;v(h);const M=w(h.currentPeek());return h.resetPeek(),M}function A(h,_){const{currentType:T}=_;if(T!==2)return!1;v(h);const M=h.currentPeek()==="-"?h.peek():h.currentPeek(),K=S(M);return h.resetPeek(),K}function C(h,_){const{currentType:T}=_;if(T!==2)return!1;v(h);const M=h.currentPeek()===Hu;return h.resetPeek(),M}function O(h,_){const{currentType:T}=_;if(T!==8)return!1;v(h);const M=h.currentPeek()===".";return h.resetPeek(),M}function I(h,_){const{currentType:T}=_;if(T!==9)return!1;v(h);const M=w(h.currentPeek());return h.resetPeek(),M}function $(h,_){const{currentType:T}=_;if(!(T===8||T===12))return!1;v(h);const M=h.currentPeek()===":";return h.resetPeek(),M}function P(h,_){const{currentType:T}=_;if(T!==10)return!1;const M=()=>{const U=h.currentPeek();return U==="{"?w(h.peek()):U==="@"||U==="%"||U==="|"||U===":"||U==="."||U===Zt||!U?!1:U===at?(h.peek(),M()):Q(h,!1)},K=M();return h.resetPeek(),K}function q(h){v(h);const _=h.currentPeek()==="|";return h.resetPeek(),_}function ie(h){const _=v(h),T=h.currentPeek()==="%"&&h.peek()==="{";return h.resetPeek(),{isModulo:T,hasSpace:_.length>0}}function Q(h,_=!0){const T=(K=!1,U="",L=!1)=>{const R=h.currentPeek();return R==="{"?U==="%"?!1:K:R==="@"||!R?U==="%"?!0:K:R==="%"?(h.peek(),T(K,"%",!0)):R==="|"?U==="%"||L?!0:!(U===Zt||U===at):R===Zt?(h.peek(),T(!0,Zt,L)):R===at?(h.peek(),T(!0,at,L)):!0},M=T();return _&&h.resetPeek(),M}function le(h,_){const T=h.currentChar();return T===_n?_n:_(T)?(h.next(),T):null}function je(h){const _=h.charCodeAt(0);return _>=97&&_<=122||_>=65&&_<=90||_>=48&&_<=57||_===95||_===36}function Ce(h){return le(h,je)}function ee(h){const _=h.charCodeAt(0);return _>=97&&_<=122||_>=65&&_<=90||_>=48&&_<=57||_===95||_===36||_===45}function ae(h){return le(h,ee)}function de(h){const _=h.charCodeAt(0);return _>=48&&_<=57}function xe(h){return le(h,de)}function pe(h){const _=h.charCodeAt(0);return _>=48&&_<=57||_>=65&&_<=70||_>=97&&_<=102}function Ee(h){return le(h,pe)}function be(h){let _="",T="";for(;_=xe(h);)T+=_;return T}function et(h){y(h);const _=h.currentChar();return _!=="%"&&f(oe.EXPECTED_TOKEN,i(),0,_),h.next(),"%"}function Be(h){let _="";for(;;){const T=h.currentChar();if(T==="{"||T==="}"||T==="@"||T==="|"||!T)break;if(T==="%")if(Q(h))_+=T,h.next();else break;else if(T===Zt||T===at)if(Q(h))_+=T,h.next();else{if(q(h))break;_+=T,h.next()}else _+=T,h.next()}return _}function We(h){y(h);let _="",T="";for(;_=ae(h);)T+=_;return h.currentChar()===_n&&f(oe.UNTERMINATED_CLOSING_BRACE,i(),0),T}function Le(h){y(h);let _="";return h.currentChar()==="-"?(h.next(),_+=`-${be(h)}`):_+=be(h),h.currentChar()===_n&&f(oe.UNTERMINATED_CLOSING_BRACE,i(),0),_}function F(h){return h!==Hu&&h!==at}function Y(h){y(h),p(h,"'");let _="",T="";for(;_=le(h,F);)_==="\\"?T+=W(h):T+=_;const M=h.currentChar();return M===at||M===_n?(f(oe.UNTERMINATED_SINGLE_QUOTE_IN_PLACEHOLDER,i(),0),M===at&&(h.next(),p(h,"'")),T):(p(h,"'"),T)}function W(h){const _=h.currentChar();switch(_){case"\\":case"'":return h.next(),`\\${_}`;case"u":return J(h,_,4);case"U":return J(h,_,6);default:return f(oe.UNKNOWN_ESCAPE_SEQUENCE,i(),0,_),""}}function J(h,_,T){p(h,_);let M="";for(let K=0;K<T;K++){const U=Ee(h);if(!U){f(oe.INVALID_UNICODE_ESCAPE_SEQUENCE,i(),0,`\\${_}${M}${h.currentChar()}`);break}M+=U}return`\\${_}${M}`}function _e(h){return h!=="{"&&h!=
Line truncated
|
||||
`,o=t.needIndent?t.needIndent:n!=="arrow",a=e.helpers||[],l=vy(e,{mode:n,filename:r,sourceMap:s,breakLineCode:i,needIndent:o});l.push(n==="normal"?"function __msg__ (ctx) {":"(ctx) => {"),l.indent(o),a.length>0&&(l.push(`const { ${Ah(a.map(f=>`${f}: _${f}`),", ")} } = ctx`),l.newline()),l.push("return "),Yr(l,e),l.deindent(o),l.push("}"),delete e.helpers;const{code:u,map:c}=l.context();return{ast:e,code:u,map:c?c.toJSON():void 0}};function Ty(e,t={}){const n=wh({},t),r=!!n.jit,s=!!n.minify,i=n.optimize==null?!0:n.optimize,a=dy(n).parse(e);return r?(i&&py(a),s&&Nr(a),{ast:a,code:""}):(hy(a,n),Ay(a,n))}/*!
|
||||
* core-base v9.13.1
|
||||
* (c) 2024 kazuya kawaguchi
|
||||
* Released under the MIT License.
|
||||
*/function Oy(){typeof __INTLIFY_PROD_DEVTOOLS__!="boolean"&&(rn().__INTLIFY_PROD_DEVTOOLS__=!1),typeof __INTLIFY_JIT_COMPILATION__!="boolean"&&(rn().__INTLIFY_JIT_COMPILATION__=!1),typeof __INTLIFY_DROP_MESSAGE_COMPILER__!="boolean"&&(rn().__INTLIFY_DROP_MESSAGE_COMPILER__=!1)}const Wn=[];Wn[0]={w:[0],i:[3,0],"[":[4],o:[7]};Wn[1]={w:[1],".":[2],"[":[4],o:[7]};Wn[2]={w:[2],i:[3,0],0:[3,0]};Wn[3]={i:[3,0],0:[3,0],w:[1,1],".":[2,1],"[":[4,1],o:[7,1]};Wn[4]={"'":[5,0],'"':[6,0],"[":[4,2],"]":[1,3],o:8,l:[4,0]};Wn[5]={"'":[4,0],o:8,l:[5,0]};Wn[6]={'"':[4,0],o:8,l:[6,0]};const Sy=/^\s?(?:true|false|-?[\d.]+|'[^']*'|"[^"]*")\s?$/;function Cy(e){return Sy.test(e)}function Ny(e){const t=e.charCodeAt(0),n=e.charCodeAt(e.length-1);return t===n&&(t===34||t===39)?e.slice(1,-1):e}function Ly(e){if(e==null)return"o";switch(e.charCodeAt(0)){case 91:case 93:case 46:case 34:case 39:return e;case 95:case 36:case 45:return"i";case 9:case 10:case 13:case 160:case 65279:case 8232:case 8233:return"w"}return"i"}function Iy(e){const t=e.trim();return e.charAt(0)==="0"&&isNaN(parseInt(e))?!1:Cy(t)?Ny(t):"*"+t}function Py(e){const t=[];let n=-1,r=0,s=0,i,o,a,l,u,c,f;const d=[];d[0]=()=>{o===void 0?o=a:o+=a},d[1]=()=>{o!==void 0&&(t.push(o),o=void 0)},d[2]=()=>{d[0](),s++},d[3]=()=>{if(s>0)s--,r=4,d[0]();else{if(s=0,o===void 0||(o=Iy(o),o===!1))return!1;d[1]()}};function m(){const p=e[n+1];if(r===5&&p==="'"||r===6&&p==='"')return n++,a="\\"+p,d[0](),!0}for(;r!==null;)if(n++,i=e[n],!(i==="\\"&&m())){if(l=Ly(i),f=Wn[r],u=f[l]||f.l||8,u===8||(r=u[0],u[1]!==void 0&&(c=d[u[1]],c&&(a=i,c()===!1))))return;if(r===7)return t}}const Wu=new Map;function Ry(e,t){return Se(e)?e[t]:null}function xy(e,t){if(!Se(e))return null;let n=Wu.get(t);if(n||(n=Py(t),n&&Wu.set(t,n)),!n)return null;const r=n.length;let s=e,i=0;for(;i<r;){const o=s[n[i]];if(o===void 0||Re(s))return null;s=o,i++}return s}const ky=e=>e,$y=e=>"",Dy="text",My=e=>e.length===0?"":zb(e),Fy=Kb;function Yu(e,t){return e=Math.abs(e),t===2?e?e>1?1:0:1:e?Math.min(e,2):0}function jy(e){const t=Ke(e.pluralIndex)?e.pluralIndex:-1;return e.named&&(Ke(e.named.count)||Ke(e.named.n))?Ke(e.named.count)?e.named.count:Ke(e.named.n)?e.named.n:t:t}function Uy(e,t){t.count||(t.count=e),t.n||(t.n=e)}function Hy(e={}){const t=e.locale,n=jy(e),r=Se(e.pluralRules)&&G(t)&&Re(e.pluralRules[t])?e.pluralRules[t]:Yu,s=Se(e.pluralRules)&&G(t)&&Re(e.pluralRules[t])?Yu:void 0,i=w=>w[r(n,w.length,s)],o=e.list||[],a=w=>o[w],l=e.named||{};Ke(e.pluralIndex)&&Uy(n,l);const u=w=>l[w];function c(w){const S=Re(e.messages)?e.messages(w):Se(e.messages)?e.messages[w]:!1;return S||(e.parent?e.parent.message(w):$y)}const f=w=>e.modifiers?e.modifiers[w]:ky,d=fe(e.processor)&&Re(e.processor.normalize)?e.processor.normalize:My,m=fe(e.processor)&&Re(e.processor.interpolate)?e.processor.interpolate:Fy,p=fe(e.processor)&&G(e.processor.type)?e.processor.type:Dy,y={list:a,named:u,plural:i,linked:(w,...S)=>{const[E,A]=S;let C="text",O="";S.length===1?Se(E)?(O=E.modifier||O,C=E.type||C):G(E)&&(O=E||O):S.length===2&&(G(E)&&(O=E||O),G(A)&&(C=A||C));const I=c(w)(y),$=C==="vnode"&&De(I)&&O?I[0]:I;return O?f(O)($,C):$},message:c,type:p,interpolate:m,normalize:d,values:tt({},o,l)};return y}let Us=null;function Vy(e){Us=e}function By(e,t,n){Us&&Us.emit("i18n:init",{timestamp:Date.now(),i18n:e,version:t,meta:n})}const Wy=Yy("function:translate");function Yy(e){return t=>Us&&Us.emit(e,t)}const Th=oc.__EXTEND_POINT__,Xn=Io(Th),Ky={NOT_FOUND_KEY:Th,FALLBACK_TO_TRANSLATE:Xn(),CANNOT_FORMAT_NUMBER:Xn(),FALLBACK_TO_NUMBER_FORMAT:Xn(),CANNOT_FORMAT_DATE:Xn(),FALLBACK_TO_DATE_FORMAT:Xn(),EXPERIMENTAL_CUSTOM_MESSAGE_COMPILER:Xn(),__EXTEND_POINT__:Xn()},Oh=oe.__EXTEND_POINT__,Jn=Io(Oh),$t={INVALID_ARGUMENT:Oh,INVALID_DATE_ARGUMENT:Jn(),INVALID_ISO_DATE_ARGUMENT:Jn(),NOT_SUPPORT_NON_STRING_MESSAGE:Jn(),NOT_SUPPORT_LOCALE_PROMISE_VALUE:Jn(),NOT_SUPPORT_LOCALE_ASYNC_FUNCTION:Jn(),NOT_SUPPORT_LOCALE_TYPE:Jn(),__EXTEND_POINT__:Jn()};function Kt(e){return is(e,null,void 0)}function lc(e,t){return t.locale!=null?Ku(t.locale):Ku(e.locale)}let aa;function Ku(e){if(G(e))return e;if(Re(e)){if(e.resolvedOnce&&aa!=null)return aa;if(e.constructor.name==="Function"){const t=e();if(Yb(t))throw Kt($t.NOT_SUPPORT_LOCALE_PROMISE_VALUE);return aa=t}else throw Kt($t.NOT_SUPPORT_LOCALE_ASYNC_FUNCTION)}else throw Kt($t.NOT_SUPPORT_LOCALE_TYPE)}function zy(e,t,n){return[...new Set([n,...De(t)?t:Se(t)?Object.keys(t):G(t)?[t]:[n]])]}function Sh(e,t,n){const r=G(n)?n:Kr,s=e;s.__localeChainCache||(s.__localeChainCache=new Map);let i=s.__localeChainCache.get(r);if(!i){i=[];let o=[n];for(;De(o);)o=zu(i,o,t);const a=De(t)||!fe(t)?t:t.default?t.default:null;o=G(a)?[a]:a,De(o)&&zu(i,o,!1),s.__localeChainCache.set(r,i)}return i}function zu(e,t,n){let r=!0;for(let s=0;s<t.length&&ve(r);s++){const i=t[s];G(i)&&(r=Gy(e,t[s],n))}return r}function Gy(e,t,n){let r;const s=t.split("-");do{const i=s.join("-");r=qy(e,i,n),s.splice(-1,1)}while(s.length&&r===!0);return r}function qy(e,t,n){let rLine truncated
|
||||
* vue-i18n v9.13.1
|
||||
* (c) 2024 kazuya kawaguchi
|
||||
* Released under the MIT License.
|
||||
*/const mE="9.13.1";function hE(){typeof __VUE_I18N_FULL_INSTALL__!="boolean"&&(rn().__VUE_I18N_FULL_INSTALL__=!0),typeof __VUE_I18N_LEGACY_API__!="boolean"&&(rn().__VUE_I18N_LEGACY_API__=!0),typeof __INTLIFY_JIT_COMPILATION__!="boolean"&&(rn().__INTLIFY_JIT_COMPILATION__=!1),typeof __INTLIFY_DROP_MESSAGE_COMPILER__!="boolean"&&(rn().__INTLIFY_DROP_MESSAGE_COMPILER__=!1),typeof __INTLIFY_PROD_DEVTOOLS__!="boolean"&&(rn().__INTLIFY_PROD_DEVTOOLS__=!1)}const Fh=Ky.__EXTEND_POINT__,en=Io(Fh);en(),en(),en(),en(),en(),en(),en(),en(),en();const jh=$t.__EXTEND_POINT__,dt=Io(jh),ze={UNEXPECTED_RETURN_TYPE:jh,INVALID_ARGUMENT:dt(),MUST_BE_CALL_SETUP_TOP:dt(),NOT_INSTALLED:dt(),NOT_AVAILABLE_IN_LEGACY_MODE:dt(),REQUIRED_VALUE:dt(),INVALID_VALUE:dt(),CANNOT_SETUP_VUE_DEVTOOLS_PLUGIN:dt(),NOT_INSTALLED_WITH_PROVIDE:dt(),UNEXPECTED_ERROR:dt(),NOT_COMPATIBLE_LEGACY_VUE_I18N:dt(),BRIDGE_SUPPORT_VUE_2_ONLY:dt(),MUST_DEFINE_I18N_OPTION_IN_ALLOW_COMPOSITION:dt(),NOT_AVAILABLE_COMPOSITION_IN_LEGACY:dt(),__EXTEND_POINT__:dt()};function Qe(e,...t){return is(e,null,void 0)}const nl=Bn("__translateVNode"),rl=Bn("__datetimeParts"),sl=Bn("__numberParts"),Uh=Bn("__setPluralRules"),Hh=Bn("__injectWithOption"),il=Bn("__dispose");function Hs(e){if(!Se(e))return e;for(const t in e)if(no(e,t))if(!t.includes("."))Se(e[t])&&Hs(e[t]);else{const n=t.split("."),r=n.length-1;let s=e,i=!1;for(let o=0;o<r;o++){if(n[o]in s||(s[n[o]]={}),!Se(s[n[o]])){i=!0;break}s=s[n[o]]}i||(s[n[r]]=e[t],delete e[t]),Se(s[n[r]])&&Hs(s[n[r]])}return e}function Ro(e,t){const{messages:n,__i18n:r,messageResolver:s,flatJson:i}=t,o=fe(n)?n:De(r)?{}:{[e]:{}};if(De(r)&&r.forEach(a=>{if("locale"in a&&"resource"in a){const{locale:l,resource:u}=a;l?(o[l]=o[l]||{},Hi(u,o[l])):Hi(u,o)}else G(a)&&Hi(JSON.parse(a),o)}),s==null&&i)for(const a in o)no(o,a)&&Hs(o[a]);return o}function Vh(e){return e.type}function Bh(e,t,n){let r=Se(t.messages)?t.messages:{};"__i18nGlobal"in n&&(r=Ro(e.locale.value,{messages:r,__i18n:n.__i18nGlobal}));const s=Object.keys(r);s.length&&s.forEach(i=>{e.mergeLocaleMessage(i,r[i])});{if(Se(t.datetimeFormats)){const i=Object.keys(t.datetimeFormats);i.length&&i.forEach(o=>{e.mergeDateTimeFormat(o,t.datetimeFormats[o])})}if(Se(t.numberFormats)){const i=Object.keys(t.numberFormats);i.length&&i.forEach(o=>{e.mergeNumberFormat(o,t.numberFormats[o])})}}}function af(e){return ye(Js,null,e,0)}const lf="__INTLIFY_META__",cf=()=>[],pE=()=>!1;let uf=0;function ff(e){return(t,n,r,s)=>e(n,r,Wr()||void 0,s)}const gE=()=>{const e=Wr();let t=null;return e&&(t=Vh(e)[lf])?{[lf]:t}:null};function uc(e={},t){const{__root:n,__injectWithOption:r}=e,s=n===void 0,i=e.flatJson,o=to?ge:Jl,a=!!e.translateExistCompatible;let l=ve(e.inheritLocale)?e.inheritLocale:!0;const u=o(n&&l?n.locale.value:G(e.locale)?e.locale:Kr),c=o(n&&l?n.fallbackLocale.value:G(e.fallbackLocale)||De(e.fallbackLocale)||fe(e.fallbackLocale)||e.fallbackLocale===!1?e.fallbackLocale:u.value),f=o(Ro(u.value,e)),d=o(fe(e.datetimeFormats)?e.datetimeFormats:{[u.value]:{}}),m=o(fe(e.numberFormats)?e.numberFormats:{[u.value]:{}});let p=n?n.missingWarn:ve(e.missingWarn)||xn(e.missingWarn)?e.missingWarn:!0,v=n?n.fallbackWarn:ve(e.fallbackWarn)||xn(e.fallbackWarn)?e.fallbackWarn:!0,y=n?n.fallbackRoot:ve(e.fallbackRoot)?e.fallbackRoot:!0,w=!!e.fallbackFormat,S=Re(e.missing)?e.missing:null,E=Re(e.missing)?ff(e.missing):null,A=Re(e.postTranslation)?e.postTranslation:null,C=n?n.warnHtmlMessage:ve(e.warnHtmlMessage)?e.warnHtmlMessage:!0,O=!!e.escapeParameter;const I=n?n.modifiers:fe(e.modifiers)?e.modifiers:{};let $=e.pluralRules||n&&n.pluralRules,P;P=(()=>{s&&Ju(null);const L={version:mE,locale:u.value,fallbackLocale:c.value,messages:f.value,modifiers:I,pluralRules:$,missing:E===null?void 0:E,missingWarn:p,fallbackWarn:v,fallbackFormat:w,unresolving:!0,postTranslation:A===null?void 0:A,warnHtmlMessage:C,escapeParameter:O,messageResolver:e.messageResolver,messageCompiler:e.messageCompiler,__meta:{framework:"vue"}};L.datetimeFormats=d.value,L.numberFormats=m.value,L.__datetimeFormatters=fe(P)?P.__datetimeFormatters:void 0,L.__numberFormatters=fe(P)?P.__numberFormatters:void 0;const R=rE(L);return s&&Ju(R),R})(),hs(P,u.value,c.value);function ie(){return[u.value,c.value,f.value,d.value,m.value]}const Q=ne({get:()=>u.value,set:L=>{u.value=L,P.locale=u.value}}),le=ne({get:()=>c.value,set:L=>{c.value=L,P.fallbackLocale=c.value,hs(P,u.value,L)}}),je=ne(()=>f.value),Ce=ne(()=>d.value),ee=ne(()=>m.value);function ae(){return Re(A)?A:null}function de(L){A=L,P.postTranslation=L}function xe(){return S}function pe(L){L!==null&&(E=ff(L)),S=L,P.missing=E}const Ee=(L,R,te,se,Pe,nt)=>{ie();let vt;try{__INTLIFY_PROD_DEVTOOLS__,s||(P.fallbackContext=n?nE():void 0),vt=L(P)}finally{__INTLIFY_PROD_DEVTOOLS__,s||(P.fallbackContext=void 0)}if(te!=="translate exists"&&Ke(vt)&&vt===Po||te==="translate exists"&&!vt){const[di,Ar]=R();return n&&y?se(n):Pe(di)}else{if(nt(vt))return vt;throw Qe(ze.UNEXPECTED_RETURN_TYPE)}};function be(...L){return Ee(RLine truncated
|
||||
* vue-router v4.3.3
|
||||
* (c) 2024 Eduardo San Martin Morote
|
||||
* @license MIT
|
||||
*/const Lr=typeof document<"u";function jE(e){return e.__esModule||e[Symbol.toStringTag]==="Module"}const Ne=Object.assign;function ca(e,t){const n={};for(const r in t){const s=t[r];n[r]=jt(s)?s.map(e):e(s)}return n}const Cs=()=>{},jt=Array.isArray,Kh=/#/g,UE=/&/g,HE=/\//g,VE=/=/g,BE=/\?/g,zh=/\+/g,WE=/%5B/g,YE=/%5D/g,Gh=/%5E/g,KE=/%60/g,qh=/%7B/g,zE=/%7C/g,Xh=/%7D/g,GE=/%20/g;function dc(e){return encodeURI(""+e).replace(zE,"|").replace(WE,"[").replace(YE,"]")}function qE(e){return dc(e).replace(qh,"{").replace(Xh,"}").replace(Gh,"^")}function al(e){return dc(e).replace(zh,"%2B").replace(GE,"+").replace(Kh,"%23").replace(UE,"%26").replace(KE,"`").replace(qh,"{").replace(Xh,"}").replace(Gh,"^")}function XE(e){return al(e).replace(VE,"%3D")}function JE(e){return dc(e).replace(Kh,"%23").replace(BE,"%3F")}function QE(e){return e==null?"":JE(e).replace(HE,"%2F")}function Vs(e){try{return decodeURIComponent(""+e)}catch{}return""+e}const ZE=/\/$/,e1=e=>e.replace(ZE,"");function ua(e,t,n="/"){let r,s={},i="",o="";const a=t.indexOf("#");let l=t.indexOf("?");return a<l&&a>=0&&(l=-1),l>-1&&(r=t.slice(0,l),i=t.slice(l+1,a>-1?a:t.length),s=e(i)),a>-1&&(r=r||t.slice(0,a),o=t.slice(a,t.length)),r=s1(r??t,n),{fullPath:r+(i&&"?")+i+o,path:r,query:s,hash:Vs(o)}}function t1(e,t){const n=t.query?e(t.query):"";return t.path+(n&&"?")+n+(t.hash||"")}function bf(e,t){return!t||!e.toLowerCase().startsWith(t.toLowerCase())?e:e.slice(t.length)||"/"}function n1(e,t,n){const r=t.matched.length-1,s=n.matched.length-1;return r>-1&&r===s&&Gr(t.matched[r],n.matched[s])&&Jh(t.params,n.params)&&e(t.query)===e(n.query)&&t.hash===n.hash}function Gr(e,t){return(e.aliasOf||e)===(t.aliasOf||t)}function Jh(e,t){if(Object.keys(e).length!==Object.keys(t).length)return!1;for(const n in e)if(!r1(e[n],t[n]))return!1;return!0}function r1(e,t){return jt(e)?yf(e,t):jt(t)?yf(t,e):e===t}function yf(e,t){return jt(t)?e.length===t.length&&e.every((n,r)=>n===t[r]):e.length===1&&e[0]===t}function s1(e,t){if(e.startsWith("/"))return e;if(!e)return t;const n=t.split("/"),r=e.split("/"),s=r[r.length-1];(s===".."||s===".")&&r.push("");let i=n.length-1,o,a;for(o=0;o<r.length;o++)if(a=r[o],a!==".")if(a==="..")i>1&&i--;else break;return n.slice(0,i).join("/")+"/"+r.slice(o).join("/")}var Bs;(function(e){e.pop="pop",e.push="push"})(Bs||(Bs={}));var Ns;(function(e){e.back="back",e.forward="forward",e.unknown=""})(Ns||(Ns={}));function i1(e){if(!e)if(Lr){const t=document.querySelector("base");e=t&&t.getAttribute("href")||"/",e=e.replace(/^\w+:\/\/[^\/]+/,"")}else e="/";return e[0]!=="/"&&e[0]!=="#"&&(e="/"+e),e1(e)}const o1=/^[^#]+#/;function a1(e,t){return e.replace(o1,"#")+t}function l1(e,t){const n=document.documentElement.getBoundingClientRect(),r=e.getBoundingClientRect();return{behavior:t.behavior,left:r.left-n.left-(t.left||0),top:r.top-n.top-(t.top||0)}}const xo=()=>({left:window.scrollX,top:window.scrollY});function c1(e){let t;if("el"in e){const n=e.el,r=typeof n=="string"&&n.startsWith("#"),s=typeof n=="string"?r?document.getElementById(n.slice(1)):document.querySelector(n):n;if(!s)return;t=l1(s,e)}else t=e;"scrollBehavior"in document.documentElement.style?window.scrollTo(t):window.scrollTo(t.left!=null?t.left:window.scrollX,t.top!=null?t.top:window.scrollY)}function Ef(e,t){return(history.state?history.state.position-t:-1)+e}const ll=new Map;function u1(e,t){ll.set(e,t)}function f1(e){const t=ll.get(e);return ll.delete(e),t}let d1=()=>location.protocol+"//"+location.host;function Qh(e,t){const{pathname:n,search:r,hash:s}=t,i=e.indexOf("#");if(i>-1){let a=s.includes(e.slice(i))?e.slice(i).length:1,l=s.slice(a);return l[0]!=="/"&&(l="/"+l),bf(l,"")}return bf(n,e)+r+s}function m1(e,t,n,r){let s=[],i=[],o=null;const a=({state:d})=>{const m=Qh(e,location),p=n.value,v=t.value;let y=0;if(d){if(n.value=m,t.value=d,o&&o===p){o=null;return}y=v?d.position-v.position:0}else r(m);s.forEach(w=>{w(n.value,p,{delta:y,type:Bs.pop,direction:y?y>0?Ns.forward:Ns.back:Ns.unknown})})};function l(){o=n.value}function u(d){s.push(d);const m=()=>{const p=s.indexOf(d);p>-1&&s.splice(p,1)};return i.push(m),m}function c(){const{history:d}=window;d.state&&d.replaceState(Ne({},d.state,{scroll:xo()}),"")}function f(){for(const d of i)d();i=[],window.removeEventListener("popstate",a),window.removeEventListener("beforeunload",c)}return window.addEventListener("popstate",a),window.addEventListener("beforeunload",c,{passive:!0}),{pauseListeners:l,listen:u,destroy:f}}function wf(e,t,n,r=!1,s=!1){return{back:e,current:t,forward:n,replaced:r,position:window.history.length,scroll:s?xo():null}}function h1(e){const{history:t,location:n}=window,r={value:Qh(e,n)},s={value:t.state};s.value||i(r.value,{back:null,current:r.value,forward:null,position:t.length-1,replaced:!0,scroll:null},!0);function i(l,u,c){const f=e.indexOf("#"),d=f>-1?(n.host&&document.querySelector("base")?e:e.slice(f))+l:d1()+e+l;try{t[c?"replaceState":"pushState"](u,"",d),s.value=u}catch(m){console.error(m),n[c?"replace":"assignLine truncated
|
||||
* Bootstrap v5.3.3 (https://getbootstrap.com/)
|
||||
* Copyright 2011-2024 The Bootstrap Authors (https://github.com/twbs/bootstrap/graphs/contributors)
|
||||
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
|
||||
*/const bn=new Map,ma={set(e,t,n){bn.has(e)||bn.set(e,new Map);const r=bn.get(e);if(!r.has(t)&&r.size!==0){console.error(`Bootstrap doesn't allow more than one instance per element. Bound instance: ${Array.from(r.keys())[0]}.`);return}r.set(t,n)},get(e,t){return bn.has(e)&&bn.get(e).get(t)||null},remove(e,t){if(!bn.has(e))return;const n=bn.get(e);n.delete(t),n.size===0&&bn.delete(e)}},sw=1e6,iw=1e3,ml="transitionend",Lp=e=>(e&&window.CSS&&window.CSS.escape&&(e=e.replace(/#([^\s"#']+)/g,(t,n)=>`#${CSS.escape(n)}`)),e),ow=e=>e==null?`${e}`:Object.prototype.toString.call(e).match(/\s([a-z]+)/i)[1].toLowerCase(),aw=e=>{do e+=Math.floor(Math.random()*sw);while(document.getElementById(e));return e},lw=e=>{if(!e)return 0;let{transitionDuration:t,transitionDelay:n}=window.getComputedStyle(e);const r=Number.parseFloat(t),s=Number.parseFloat(n);return!r&&!s?0:(t=t.split(",")[0],n=n.split(",")[0],(Number.parseFloat(t)+Number.parseFloat(n))*iw)},Ip=e=>{e.dispatchEvent(new Event(ml))},an=e=>!e||typeof e!="object"?!1:(typeof e.jquery<"u"&&(e=e[0]),typeof e.nodeType<"u"),kn=e=>an(e)?e.jquery?e[0]:e:typeof e=="string"&&e.length>0?document.querySelector(Lp(e)):null,as=e=>{if(!an(e)||e.getClientRects().length===0)return!1;const t=getComputedStyle(e).getPropertyValue("visibility")==="visible",n=e.closest("details:not([open])");if(!n)return t;if(n!==e){const r=e.closest("summary");if(r&&r.parentNode!==n||r===null)return!1}return t},$n=e=>!e||e.nodeType!==Node.ELEMENT_NODE||e.classList.contains("disabled")?!0:typeof e.disabled<"u"?e.disabled:e.hasAttribute("disabled")&&e.getAttribute("disabled")!=="false",Pp=e=>{if(!document.documentElement.attachShadow)return null;if(typeof e.getRootNode=="function"){const t=e.getRootNode();return t instanceof ShadowRoot?t:null}return e instanceof ShadowRoot?e:e.parentNode?Pp(e.parentNode):null},io=()=>{},ti=e=>{e.offsetHeight},Rp=()=>window.jQuery&&!document.body.hasAttribute("data-bs-no-jquery")?window.jQuery:null,ha=[],cw=e=>{document.readyState==="loading"?(ha.length||document.addEventListener("DOMContentLoaded",()=>{for(const t of ha)t()}),ha.push(e)):e()},It=()=>document.documentElement.dir==="rtl",Rt=e=>{cw(()=>{const t=Rp();if(t){const n=e.NAME,r=t.fn[n];t.fn[n]=e.jQueryInterface,t.fn[n].Constructor=e,t.fn[n].noConflict=()=>(t.fn[n]=r,e.jQueryInterface)}})},pt=(e,t=[],n=e)=>typeof e=="function"?e(...t):n,xp=(e,t,n=!0)=>{if(!n){pt(e);return}const s=lw(t)+5;let i=!1;const o=({target:a})=>{a===t&&(i=!0,t.removeEventListener(ml,o),pt(e))};t.addEventListener(ml,o),setTimeout(()=>{i||Ip(t)},s)},Nc=(e,t,n,r)=>{const s=e.length;let i=e.indexOf(t);return i===-1?!n&&r?e[s-1]:e[0]:(i+=n?1:-1,r&&(i=(i+s)%s),e[Math.max(0,Math.min(i,s-1))])},uw=/[^.]*(?=\..*)\.|.*/,fw=/\..*/,dw=/::\d+$/,pa={};let Yf=1;const kp={mouseenter:"mouseover",mouseleave:"mouseout"},mw=new Set(["click","dblclick","mouseup","mousedown","contextmenu","mousewheel","DOMMouseScroll","mouseover","mouseout","mousemove","selectstart","selectend","keydown","keypress","keyup","orientationchange","touchstart","touchmove","touchend","touchcancel","pointerdown","pointermove","pointerup","pointerleave","pointercancel","gesturestart","gesturechange","gestureend","focus","blur","change","reset","select","submit","focusin","focusout","load","unload","beforeunload","resize","move","DOMContentLoaded","readystatechange","error","abort","scroll"]);function $p(e,t){return t&&`${t}::${Yf++}`||e.uidEvent||Yf++}function Dp(e){const t=$p(e);return e.uidEvent=t,pa[t]=pa[t]||{},pa[t]}function hw(e,t){return function n(r){return Lc(r,{delegateTarget:e}),n.oneOff&&H.off(e,r.type,t),t.apply(e,[r])}}function pw(e,t,n){return function r(s){const i=e.querySelectorAll(t);for(let{target:o}=s;o&&o!==this;o=o.parentNode)for(const a of i)if(a===o)return Lc(s,{delegateTarget:o}),r.oneOff&&H.off(e,s.type,t,n),n.apply(o,[s])}}function Mp(e,t,n=null){return Object.values(e).find(r=>r.callable===t&&r.delegationSelector===n)}function Fp(e,t,n){const r=typeof t=="string",s=r?n:t||n;let i=jp(e);return mw.has(i)||(i=e),[r,s,i]}function Kf(e,t,n,r,s){if(typeof t!="string"||!e)return;let[i,o,a]=Fp(t,n,r);t in kp&&(o=(p=>function(v){if(!v.relatedTarget||v.relatedTarget!==v.delegateTarget&&!v.delegateTarget.contains(v.relatedTarget))return p.call(this,v)})(o));const l=Dp(e),u=l[a]||(l[a]={}),c=Mp(u,o,i?n:null);if(c){c.oneOff=c.oneOff&&s;return}const f=$p(o,t.replace(uw,"")),d=i?pw(e,n,o):hw(e,o);d.delegationSelector=i?n:null,d.callable=o,d.oneOff=s,d.uidEvent=f,u[f]=d,e.addEventListener(a,d,i)}function hl(e,t,n,r,s){const i=Mp(t[n],r,s);i&&(e.removeEventListener(n,i,!!s),delete t[n][i.uidEvent])}function gw(e,t,n,r){const s=t[n]||{};for(const[i,o]of Object.entries(s))i.includes(r)&&hl(e,t,n,o.callable,o.delegationSelector)}function jp(e){return e=e.replace(fw,""),kp[e]||e}const H={on(e,t,n,r){Kf(e,t,n,r,!1)},one(e,t,n,r){Kf(e,t,n,r,!0)},off(e,t,n,r){if(typeof t!="string"||!e)return;const[s,i,o]=Fp(t,n,r),a=o!==t,l=Dp(e),u=l[o]||{},c=t.startsWith(".");if(typeof i<"u"){if(!ObLine truncated
|
||||
`).forEach(function(o){s=o.indexOf(":"),n=o.substring(0,s).trim().toLowerCase(),r=o.substring(s+1).trim(),!(!n||t[n]&&kC[n])&&(n==="set-cookie"?t[n]?t[n].push(r):t[n]=[r]:t[n]=t[n]?t[n]+", "+r:r)}),t},Td=Symbol("internals");function vs(e){return e&&String(e).trim().toLowerCase()}function Ki(e){return e===!1||e==null?e:x.isArray(e)?e.map(Ki):String(e)}function DC(e){const t=Object.create(null),n=/([^\s,;=]+)\s*(?:=\s*([^,;]+))?/g;let r;for(;r=n.exec(e);)t[r[1]]=r[2];return t}const MC=e=>/^[-_a-zA-Z0-9^`|~,!#$%&'*+.]+$/.test(e.trim());function La(e,t,n,r,s){if(x.isFunction(r))return r.call(this,t,n);if(s&&(t=n),!!x.isString(t)){if(x.isString(r))return t.indexOf(r)!==-1;if(x.isRegExp(r))return r.test(t)}}function FC(e){return e.trim().toLowerCase().replace(/([a-z\d])(\w*)/g,(t,n,r)=>n.toUpperCase()+r)}function jC(e,t){const n=x.toCamelCase(" "+t);["get","set","has"].forEach(r=>{Object.defineProperty(e,r+n,{value:function(s,i,o){return this[r].call(this,t,s,i,o)},configurable:!0})})}class gt{constructor(t){t&&this.set(t)}set(t,n,r){const s=this;function i(a,l,u){const c=vs(l);if(!c)throw new Error("header name must be a non-empty string");const f=x.findKey(s,c);(!f||s[f]===void 0||u===!0||u===void 0&&s[f]!==!1)&&(s[f||l]=Ki(a))}const o=(a,l)=>x.forEach(a,(u,c)=>i(u,c,l));if(x.isPlainObject(t)||t instanceof this.constructor)o(t,n);else if(x.isString(t)&&(t=t.trim())&&!MC(t))o($C(t),n);else if(x.isHeaders(t))for(const[a,l]of t.entries())i(l,a,r);else t!=null&&i(n,t,r);return this}get(t,n){if(t=vs(t),t){const r=x.findKey(this,t);if(r){const s=this[r];if(!n)return s;if(n===!0)return DC(s);if(x.isFunction(n))return n.call(this,s,r);if(x.isRegExp(n))return n.exec(s);throw new TypeError("parser must be boolean|regexp|function")}}}has(t,n){if(t=vs(t),t){const r=x.findKey(this,t);return!!(r&&this[r]!==void 0&&(!n||La(this,this[r],r,n)))}return!1}delete(t,n){const r=this;let s=!1;function i(o){if(o=vs(o),o){const a=x.findKey(r,o);a&&(!n||La(r,r[a],a,n))&&(delete r[a],s=!0)}}return x.isArray(t)?t.forEach(i):i(t),s}clear(t){const n=Object.keys(this);let r=n.length,s=!1;for(;r--;){const i=n[r];(!t||La(this,this[i],i,t,!0))&&(delete this[i],s=!0)}return s}normalize(t){const n=this,r={};return x.forEach(this,(s,i)=>{const o=x.findKey(r,i);if(o){n[o]=Ki(s),delete n[i];return}const a=t?FC(i):String(i).trim();a!==i&&delete n[i],n[a]=Ki(s),r[a]=!0}),this}concat(...t){return this.constructor.concat(this,...t)}toJSON(t){const n=Object.create(null);return x.forEach(this,(r,s)=>{r!=null&&r!==!1&&(n[s]=t&&x.isArray(r)?r.join(", "):r)}),n}[Symbol.iterator](){return Object.entries(this.toJSON())[Symbol.iterator]()}toString(){return Object.entries(this.toJSON()).map(([t,n])=>t+": "+n).join(`
|
||||
`)}get[Symbol.toStringTag](){return"AxiosHeaders"}static from(t){return t instanceof this?t:new this(t)}static concat(t,...n){const r=new this(t);return n.forEach(s=>r.set(s)),r}static accessor(t){const r=(this[Td]=this[Td]={accessors:{}}).accessors,s=this.prototype;function i(o){const a=vs(o);r[a]||(jC(s,o),r[a]=!0)}return x.isArray(t)?t.forEach(i):i(t),this}}gt.accessor(["Content-Type","Content-Length","Accept","Accept-Encoding","User-Agent","Authorization"]);x.reduceDescriptors(gt.prototype,({value:e},t)=>{let n=t[0].toUpperCase()+t.slice(1);return{get:()=>e,set(r){this[n]=r}}});x.freezeMethods(gt);function Ia(e,t){const n=this||oi,r=t||n,s=gt.from(r.headers);let i=r.data;return x.forEach(e,function(a){i=a.call(n,i,s.normalize(),t?t.status:void 0)}),s.normalize(),i}function yg(e){return!!(e&&e.__CANCEL__)}function fs(e,t,n){me.call(this,e??"canceled",me.ERR_CANCELED,t,n),this.name="CanceledError"}x.inherits(fs,me,{__CANCEL__:!0});function Eg(e,t,n){const r=n.config.validateStatus;!n.status||!r||r(n.status)?e(n):t(new me("Request failed with status code "+n.status,[me.ERR_BAD_REQUEST,me.ERR_BAD_RESPONSE][Math.floor(n.status/100)-4],n.config,n.request,n))}function UC(e){const t=/^([-+\w]{1,25})(:?\/\/|:)/.exec(e);return t&&t[1]||""}function HC(e,t){e=e||10;const n=new Array(e),r=new Array(e);let s=0,i=0,o;return t=t!==void 0?t:1e3,function(l){const u=Date.now(),c=r[i];o||(o=u),n[s]=l,r[s]=u;let f=i,d=0;for(;f!==s;)d+=n[f++],f=f%e;if(s=(s+1)%e,s===i&&(i=(i+1)%e),u-o<t)return;const m=c&&u-c;return m?Math.round(d*1e3/m):void 0}}function VC(e,t){let n=0,r=1e3/t,s,i;const o=(u,c=Date.now())=>{n=c,s=null,i&&(clearTimeout(i),i=null),e.apply(null,u)};return[(...u)=>{const c=Date.now(),f=c-n;f>=r?o(u,c):(s=u,i||(i=setTimeout(()=>{i=null,o(s)},r-f)))},()=>s&&o(s)]}const lo=(e,t,n=3)=>{let r=0;const s=HC(50,250);return VC(i=>{const o=i.loaded,a=i.lengthComputable?i.total:void 0,l=o-r,u=s(l),c=o<=a;r=o;const f={loaded:o,total:a,progress:a?o/a:void 0,bytes:l,rate:u||void 0,estimated:u&&a&&c?(a-o)/u:void 0,event:i,lengthComputable:a!=null,[t?"download":"upload"]:!0};e(f)},n)},Od=(e,t)=>{const n=e!=null;return[r=>t[0]({lengthComputable:n,total:e,loaded:r}),t[1]]},Sd=e=>(...t)=>x.asap(()=>e(...t)),BC=Ft.hasStandardBrowserEnv?function(){const t=/(msie|trident)/i.test(navigator.userAgent),n=document.createElement("a");let r;function s(i){let o=i;return t&&(n.setAttribute("href",o),o=n.href),n.setAttribute("href",o),{href:n.href,protocol:n.protocol?n.protocol.replace(/:$/,""):"",host:n.host,search:n.search?n.search.replace(/^\?/,""):"",hash:n.hash?n.hash.replace(/^#/,""):"",hostname:n.hostname,port:n.port,pathname:n.pathname.charAt(0)==="/"?n.pathname:"/"+n.pathname}}return r=s(window.location.href),function(o){const a=x.isString(o)?s(o):o;return a.protocol===r.protocol&&a.host===r.host}}():function(){return function(){return!0}}(),WC=Ft.hasStandardBrowserEnv?{write(e,t,n,r,s,i){const o=[e+"="+encodeURIComponent(t)];x.isNumber(n)&&o.push("expires="+new Date(n).toGMTString()),x.isString(r)&&o.push("path="+r),x.isString(s)&&o.push("domain="+s),i===!0&&o.push("secure"),document.cookie=o.join("; ")},read(e){const t=document.cookie.match(new RegExp("(^|;\\s*)("+e+")=([^;]*)"));return t?decodeURIComponent(t[3]):null},remove(e){this.write(e,"",Date.now()-864e5)}}:{write(){},read(){return null},remove(){}};function YC(e){return/^([a-z][a-z\d+\-.]*:)?\/\//i.test(e)}function KC(e,t){return t?e.replace(/\/?\/$/,"")+"/"+t.replace(/^\/+/,""):e}function wg(e,t){return e&&!YC(t)?KC(e,t):t}const Cd=e=>e instanceof gt?{...e}:e;function gr(e,t){t=t||{};const n={};function r(u,c,f){return x.isPlainObject(u)&&x.isPlainObject(c)?x.merge.call({caseless:f},u,c):x.isPlainObject(c)?x.merge({},c):x.isArray(c)?c.slice():c}function s(u,c,f){if(x.isUndefined(c)){if(!x.isUndefined(u))return r(void 0,u,f)}else return r(u,c,f)}function i(u,c){if(!x.isUndefined(c))return r(void 0,c)}function o(u,c){if(x.isUndefined(c)){if(!x.isUndefined(u))return r(void 0,u)}else return r(void 0,c)}function a(u,c,f){if(f in t)return r(u,c);if(f in e)return r(void 0,u)}const l={url:i,method:i,data:i,baseURL:o,transformRequest:o,transformResponse:o,paramsSerializer:o,timeout:o,timeoutMessage:o,withCredentials:o,withXSRFToken:o,adapter:o,responseType:o,xsrfCookieName:o,xsrfHeaderName:o,onUploadProgress:o,onDownloadProgress:o,decompress:o,maxContentLength:o,maxBodyLength:o,beforeRedirect:o,transport:o,httpAgent:o,httpsAgent:o,cancelToken:o,socketPath:o,responseEncoding:o,validateStatus:a,headers:(u,c)=>s(Cd(u),Cd(c),!0)};return x.forEach(Object.keys(Object.assign({},e,t)),function(c){const f=l[c]||s,d=f(e[c],t[c],c);x.isUndefined(d)&&f!==a||(n[c]=d)}),n}const Ag=e=>{const t=gr({},e);let{data:n,withXSRFToken:r,xsrfHeaderName:s,xsrfCookieName:i,headers:o,auth:a}=t;t.headers=o=gt.from(o),t.url=_g(wg(t.baseURL,t.url),e.params,e.paramsSerializer),a&&o.set("Authorization","Basic "+btoa((a.username||"")+":"+(a.password?unescape(encodeURIComponent(a.password)):"")));let l;if(x.isFormD
Line truncated
|
||||
`+i.map(Id).join(`
|
||||
`):" "+Id(i[0]):"as no adapter specified";throw new me("There is no suitable adapter to dispatch the request "+o,"ERR_NOT_SUPPORT")}return r},adapters:El};function Pa(e){if(e.cancelToken&&e.cancelToken.throwIfRequested(),e.signal&&e.signal.aborted)throw new fs(null,e)}function Pd(e){return Pa(e),e.headers=gt.from(e.headers),e.data=Ia.call(e,e.transformRequest),["post","put","patch"].indexOf(e.method)!==-1&&e.headers.setContentType("application/x-www-form-urlencoded",!1),Sg.getAdapter(e.adapter||oi.adapter)(e).then(function(r){return Pa(e),r.data=Ia.call(e,e.transformResponse,r),r.headers=gt.from(r.headers),r},function(r){return yg(r)||(Pa(e),r&&r.response&&(r.response.data=Ia.call(e,e.transformResponse,r.response),r.response.headers=gt.from(r.response.headers))),Promise.reject(r)})}const Cg="1.7.3",Mc={};["object","boolean","number","function","string","symbol"].forEach((e,t)=>{Mc[e]=function(r){return typeof r===e||"a"+(t<1?"n ":" ")+e}});const Rd={};Mc.transitional=function(t,n,r){function s(i,o){return"[Axios v"+Cg+"] Transitional option '"+i+"'"+o+(r?". "+r:"")}return(i,o,a)=>{if(t===!1)throw new me(s(o," has been removed"+(n?" in "+n:"")),me.ERR_DEPRECATED);return n&&!Rd[o]&&(Rd[o]=!0,console.warn(s(o," has been deprecated since v"+n+" and will be removed in the near future"))),t?t(i,o,a):!0}};function rN(e,t,n){if(typeof e!="object")throw new me("options must be an object",me.ERR_BAD_OPTION_VALUE);const r=Object.keys(e);let s=r.length;for(;s-- >0;){const i=r[s],o=t[i];if(o){const a=e[i],l=a===void 0||o(a,i,e);if(l!==!0)throw new me("option "+i+" must be "+l,me.ERR_BAD_OPTION_VALUE);continue}if(n!==!0)throw new me("Unknown option "+i,me.ERR_BAD_OPTION)}}const wl={assertOptions:rN,validators:Mc},yn=wl.validators;class fr{constructor(t){this.defaults=t,this.interceptors={request:new Ad,response:new Ad}}async request(t,n){try{return await this._request(t,n)}catch(r){if(r instanceof Error){let s;Error.captureStackTrace?Error.captureStackTrace(s={}):s=new Error;const i=s.stack?s.stack.replace(/^.+\n/,""):"";try{r.stack?i&&!String(r.stack).endsWith(i.replace(/^.+\n.+\n/,""))&&(r.stack+=`
|
||||
`+i):r.stack=i}catch{}}throw r}}_request(t,n){typeof t=="string"?(n=n||{},n.url=t):n=t||{},n=gr(this.defaults,n);const{transitional:r,paramsSerializer:s,headers:i}=n;r!==void 0&&wl.assertOptions(r,{silentJSONParsing:yn.transitional(yn.boolean),forcedJSONParsing:yn.transitional(yn.boolean),clarifyTimeoutError:yn.transitional(yn.boolean)},!1),s!=null&&(x.isFunction(s)?n.paramsSerializer={serialize:s}:wl.assertOptions(s,{encode:yn.function,serialize:yn.function},!0)),n.method=(n.method||this.defaults.method||"get").toLowerCase();let o=i&&x.merge(i.common,i[n.method]);i&&x.forEach(["delete","get","head","post","put","patch","common"],p=>{delete i[p]}),n.headers=gt.concat(o,i);const a=[];let l=!0;this.interceptors.request.forEach(function(v){typeof v.runWhen=="function"&&v.runWhen(n)===!1||(l=l&&v.synchronous,a.unshift(v.fulfilled,v.rejected))});const u=[];this.interceptors.response.forEach(function(v){u.push(v.fulfilled,v.rejected)});let c,f=0,d;if(!l){const p=[Pd.bind(this),void 0];for(p.unshift.apply(p,a),p.push.apply(p,u),d=p.length,c=Promise.resolve(n);f<d;)c=c.then(p[f++],p[f++]);return c}d=a.length;let m=n;for(f=0;f<d;){const p=a[f++],v=a[f++];try{m=p(m)}catch(y){v.call(this,y);break}}try{c=Pd.call(this,m)}catch(p){return Promise.reject(p)}for(f=0,d=u.length;f<d;)c=c.then(u[f++],u[f++]);return c}getUri(t){t=gr(this.defaults,t);const n=wg(t.baseURL,t.url);return _g(n,t.params,t.paramsSerializer)}}x.forEach(["delete","get","head","options"],function(t){fr.prototype[t]=function(n,r){return this.request(gr(r||{},{method:t,url:n,data:(r||{}).data}))}});x.forEach(["post","put","patch"],function(t){function n(r){return function(i,o,a){return this.request(gr(a||{},{method:t,headers:r?{"Content-Type":"multipart/form-data"}:{},url:i,data:o}))}}fr.prototype[t]=n(),fr.prototype[t+"Form"]=n(!0)});class Fc{constructor(t){if(typeof t!="function")throw new TypeError("executor must be a function.");let n;this.promise=new Promise(function(i){n=i});const r=this;this.promise.then(s=>{if(!r._listeners)return;let i=r._listeners.length;for(;i-- >0;)r._listeners[i](s);r._listeners=null}),this.promise.then=s=>{let i;const o=new Promise(a=>{r.subscribe(a),i=a}).then(s);return o.cancel=function(){r.unsubscribe(i)},o},t(function(i,o,a){r.reason||(r.reason=new fs(i,o,a),n(r.reason))})}throwIfRequested(){if(this.reason)throw this.reason}subscribe(t){if(this.reason){t(this.reason);return}this._listeners?this._listeners.push(t):this._listeners=[t]}unsubscribe(t){if(!this._listeners)return;const n=this._listeners.indexOf(t);n!==-1&&this._listeners.splice(n,1)}static source(){let t;return{token:new Fc(function(s){t=s}),cancel:t}}}function sN(e){return function(n){return e.apply(null,n)}}function iN(e){return x.isObject(e)&&e.isAxiosError===!0}const Al={Continue:100,SwitchingProtocols:101,Processing:102,EarlyHints:103,Ok:200,Created:201,Accepted:202,NonAuthoritativeInformation:203,NoContent:204,ResetContent:205,PartialContent:206,MultiStatus:207,AlreadyReported:208,ImUsed:226,MultipleChoices:300,MovedPermanently:301,Found:302,SeeOther:303,NotModified:304,UseProxy:305,Unused:306,TemporaryRedirect:307,PermanentRedirect:308,BadRequest:400,Unauthorized:401,PaymentRequired:402,Forbidden:403,NotFound:404,MethodNotAllowed:405,NotAcceptable:406,ProxyAuthenticationRequired:407,RequestTimeout:408,Conflict:409,Gone:410,LengthRequired:411,PreconditionFailed:412,PayloadTooLarge:413,UriTooLong:414,UnsupportedMediaType:415,RangeNotSatisfiable:416,ExpectationFailed:417,ImATeapot:418,MisdirectedRequest:421,UnprocessableEntity:422,Locked:423,FailedDependency:424,TooEarly:425,UpgradeRequired:426,PreconditionRequired:428,TooManyRequests:429,RequestHeaderFieldsTooLarge:431,UnavailableForLegalReasons:451,InternalServerError:500,NotImplemented:501,BadGateway:502,ServiceUnavailable:503,GatewayTimeout:504,HttpVersionNotSupported:505,VariantAlsoNegotiates:506,InsufficientStorage:507,LoopDetected:508,NotExtended:510,NetworkAuthenticationRequired:511};Object.entries(Al).forEach(([e,t])=>{Al[t]=e});function Ng(e){const t=new fr(e),n=ig(fr.prototype.request,t);return x.extend(n,fr.prototype,t,{allOwnKeys:!0}),x.extend(n,t,null,{allOwnKeys:!0}),n.create=function(s){return Ng(gr(e,s))},n}const Ue=Ng(oi);Ue.Axios=fr;Ue.CanceledError=fs;Ue.CancelToken=Fc;Ue.isCancel=yg;Ue.VERSION=Cg;Ue.toFormData=Ko;Ue.AxiosError=me;Ue.Cancel=Ue.CanceledError;Ue.all=function(t){return Promise.all(t)};Ue.spread=sN;Ue.isAxiosError=iN;Ue.mergeConfig=gr;Ue.AxiosHeaders=gt;Ue.formToJSON=e=>bg(x.isHTMLForm(e)?new FormData(e):e);Ue.getAdapter=Sg.getAdapter;Ue.HttpStatusCode=Al;Ue.default=Ue;class oN{getTest(t,n){return new Promise((r,s)=>{Ue.get(`${Rs.API_BASE_URL}/user/test/${t}`,{params:{param1:n},withCredentials:!0}).then(i=>{r(i)}).catch(i=>{s(i)})})}}const aN=new oN,ai=e=>(iv("data-v-6c838f03"),e=e(),ov(),e),lN={class:"row"},cN={class:"col"},uN={class:"w-100 d-flex justify-content-center my-5"},fN={class:"container-fluid px-0 d-flex justify-content-center align-items-center flex-column"},dN
Line truncated
|
||||
In order to be iterable, non-array objects must have a [Symbol.iterator]() method.`)}function II(){throw new TypeError(`Invalid attempt to destructure non-iterable instance.
|
||||
In order to be iterable, non-array objects must have a [Symbol.iterator]() method.`)}var Vd=function(){},Hc={},jg={},Ug=null,Hg={mark:Vd,measure:Vd};try{typeof window<"u"&&(Hc=window),typeof document<"u"&&(jg=document),typeof MutationObserver<"u"&&(Ug=MutationObserver),typeof performance<"u"&&(Hg=performance)}catch{}var PI=Hc.navigator||{},Bd=PI.userAgent,Wd=Bd===void 0?"":Bd,Mn=Hc,Me=jg,Yd=Ug,Ci=Hg;Mn.document;var pn=!!Me.documentElement&&!!Me.head&&typeof Me.addEventListener=="function"&&typeof Me.createElement=="function",Vg=~Wd.indexOf("MSIE")||~Wd.indexOf("Trident/"),Ni,Li,Ii,Pi,Ri,un="___FONT_AWESOME___",Cl=16,Bg="fa",Wg="svg-inline--fa",_r="data-fa-i2svg",Nl="data-fa-pseudo-element",RI="data-fa-pseudo-element-pending",Vc="data-prefix",Bc="data-icon",Kd="fontawesome-i2svg",xI="async",kI=["HTML","HEAD","STYLE","SCRIPT"],Yg=function(){try{return!0}catch{return!1}}(),$e="classic",Ve="sharp",Wc=[$e,Ve];function ci(e){return new Proxy(e,{get:function(n,r){return r in n?n[r]:n[$e]}})}var Ks=ci((Ni={},qe(Ni,$e,{fa:"solid",fas:"solid","fa-solid":"solid",far:"regular","fa-regular":"regular",fal:"light","fa-light":"light",fat:"thin","fa-thin":"thin",fad:"duotone","fa-duotone":"duotone",fab:"brands","fa-brands":"brands",fak:"kit",fakd:"kit","fa-kit":"kit","fa-kit-duotone":"kit"}),qe(Ni,Ve,{fa:"solid",fass:"solid","fa-solid":"solid",fasr:"regular","fa-regular":"regular",fasl:"light","fa-light":"light",fast:"thin","fa-thin":"thin"}),Ni)),zs=ci((Li={},qe(Li,$e,{solid:"fas",regular:"far",light:"fal",thin:"fat",duotone:"fad",brands:"fab",kit:"fak"}),qe(Li,Ve,{solid:"fass",regular:"fasr",light:"fasl",thin:"fast"}),Li)),Gs=ci((Ii={},qe(Ii,$e,{fab:"fa-brands",fad:"fa-duotone",fak:"fa-kit",fal:"fa-light",far:"fa-regular",fas:"fa-solid",fat:"fa-thin"}),qe(Ii,Ve,{fass:"fa-solid",fasr:"fa-regular",fasl:"fa-light",fast:"fa-thin"}),Ii)),$I=ci((Pi={},qe(Pi,$e,{"fa-brands":"fab","fa-duotone":"fad","fa-kit":"fak","fa-light":"fal","fa-regular":"far","fa-solid":"fas","fa-thin":"fat"}),qe(Pi,Ve,{"fa-solid":"fass","fa-regular":"fasr","fa-light":"fasl","fa-thin":"fast"}),Pi)),DI=/fa(s|r|l|t|d|b|k|ss|sr|sl|st)?[\-\ ]/,Kg="fa-layers-text",MI=/Font ?Awesome ?([56 ]*)(Solid|Regular|Light|Thin|Duotone|Brands|Free|Pro|Sharp|Kit)?.*/i,FI=ci((Ri={},qe(Ri,$e,{900:"fas",400:"far",normal:"far",300:"fal",100:"fat"}),qe(Ri,Ve,{900:"fass",400:"fasr",300:"fasl",100:"fast"}),Ri)),zg=[1,2,3,4,5,6,7,8,9,10],jI=zg.concat([11,12,13,14,15,16,17,18,19,20]),UI=["class","data-prefix","data-icon","data-fa-transform","data-fa-mask"],ir={GROUP:"duotone-group",SWAP_OPACITY:"swap-opacity",PRIMARY:"primary",SECONDARY:"secondary"},qs=new Set;Object.keys(zs[$e]).map(qs.add.bind(qs));Object.keys(zs[Ve]).map(qs.add.bind(qs));var HI=[].concat(Wc,li(qs),["2xs","xs","sm","lg","xl","2xl","beat","border","fade","beat-fade","bounce","flip-both","flip-horizontal","flip-vertical","flip","fw","inverse","layers-counter","layers-text","layers","li","pull-left","pull-right","pulse","rotate-180","rotate-270","rotate-90","rotate-by","shake","spin-pulse","spin-reverse","spin","stack-1x","stack-2x","stack","ul",ir.GROUP,ir.SWAP_OPACITY,ir.PRIMARY,ir.SECONDARY]).concat(zg.map(function(e){return"".concat(e,"x")})).concat(jI.map(function(e){return"w-".concat(e)})),xs=Mn.FontAwesomeConfig||{};function VI(e){var t=Me.querySelector("script["+e+"]");if(t)return t.getAttribute(e)}function BI(e){return e===""?!0:e==="false"?!1:e==="true"?!0:e}if(Me&&typeof Me.querySelector=="function"){var WI=[["data-family-prefix","familyPrefix"],["data-css-prefix","cssPrefix"],["data-family-default","familyDefault"],["data-style-default","styleDefault"],["data-replacement-class","replacementClass"],["data-auto-replace-svg","autoReplaceSvg"],["data-auto-add-css","autoAddCss"],["data-auto-a11y","autoA11y"],["data-search-pseudo-elements","searchPseudoElements"],["data-observe-mutations","observeMutations"],["data-mutate-approach","mutateApproach"],["data-keep-original-source","keepOriginalSource"],["data-measure-performance","measurePerformance"],["data-show-missing-icons","showMissingIcons"]];WI.forEach(function(e){var t=Uc(e,2),n=t[0],r=t[1],s=BI(VI(n));s!=null&&(xs[r]=s)})}var Gg={styleDefault:"solid",familyDefault:"classic",cssPrefix:Bg,replacementClass:Wg,autoReplaceSvg:!0,autoAddCss:!0,autoA11y:!0,searchPseudoElements:!1,observeMutations:!0,mutateApproach:"async",keepOriginalSource:!0,measurePerformance:!1,showMissingIcons:!0};xs.familyPrefix&&(xs.cssPrefix=xs.familyPrefix);var ns=X(X({},Gg),xs);ns.autoReplaceSvg||(ns.observeMutations=!1);var Z={};Object.keys(Gg).forEach(function(e){Object.defineProperty(Z,e,{enumerable:!0,set:function(n){ns[e]=n,ks.forEach(function(r){return r(Z)})},get:function(){return ns[e]}})});Object.defineProperty(Z,"familyPrefix",{enumerable:!0,set:function(t){ns.cssPrefix=t,ks.forEach(function(n){return n(Z)})},get:function(){return ns.cssPrefix}});Mn.FontAwesomeConfig=Z;var ks=[];function YI(e){return ks.push(e),function(){ks.splice(ks.indexOf(e),1)}}var En=Cl,zt={size:16,x:0
Line truncated
|
||||
--fa-font-solid: normal 900 1em/1 "Font Awesome 6 Solid";
|
||||
--fa-font-regular: normal 400 1em/1 "Font Awesome 6 Regular";
|
||||
--fa-font-light: normal 300 1em/1 "Font Awesome 6 Light";
|
||||
--fa-font-thin: normal 100 1em/1 "Font Awesome 6 Thin";
|
||||
--fa-font-duotone: normal 900 1em/1 "Font Awesome 6 Duotone";
|
||||
--fa-font-sharp-solid: normal 900 1em/1 "Font Awesome 6 Sharp";
|
||||
--fa-font-sharp-regular: normal 400 1em/1 "Font Awesome 6 Sharp";
|
||||
--fa-font-sharp-light: normal 300 1em/1 "Font Awesome 6 Sharp";
|
||||
--fa-font-sharp-thin: normal 100 1em/1 "Font Awesome 6 Sharp";
|
||||
--fa-font-brands: normal 400 1em/1 "Font Awesome 6 Brands";
|
||||
}
|
||||
|
||||
svg:not(:root).svg-inline--fa, svg:not(:host).svg-inline--fa {
|
||||
overflow: visible;
|
||||
box-sizing: content-box;
|
||||
}
|
||||
|
||||
.svg-inline--fa {
|
||||
display: var(--fa-display, inline-block);
|
||||
height: 1em;
|
||||
overflow: visible;
|
||||
vertical-align: -0.125em;
|
||||
}
|
||||
.svg-inline--fa.fa-2xs {
|
||||
vertical-align: 0.1em;
|
||||
}
|
||||
.svg-inline--fa.fa-xs {
|
||||
vertical-align: 0em;
|
||||
}
|
||||
.svg-inline--fa.fa-sm {
|
||||
vertical-align: -0.0714285705em;
|
||||
}
|
||||
.svg-inline--fa.fa-lg {
|
||||
vertical-align: -0.2em;
|
||||
}
|
||||
.svg-inline--fa.fa-xl {
|
||||
vertical-align: -0.25em;
|
||||
}
|
||||
.svg-inline--fa.fa-2xl {
|
||||
vertical-align: -0.3125em;
|
||||
}
|
||||
.svg-inline--fa.fa-pull-left {
|
||||
margin-right: var(--fa-pull-margin, 0.3em);
|
||||
width: auto;
|
||||
}
|
||||
.svg-inline--fa.fa-pull-right {
|
||||
margin-left: var(--fa-pull-margin, 0.3em);
|
||||
width: auto;
|
||||
}
|
||||
.svg-inline--fa.fa-li {
|
||||
width: var(--fa-li-width, 2em);
|
||||
top: 0.25em;
|
||||
}
|
||||
.svg-inline--fa.fa-fw {
|
||||
width: var(--fa-fw-width, 1.25em);
|
||||
}
|
||||
|
||||
.fa-layers svg.svg-inline--fa {
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
margin: auto;
|
||||
position: absolute;
|
||||
right: 0;
|
||||
top: 0;
|
||||
}
|
||||
|
||||
.fa-layers-counter, .fa-layers-text {
|
||||
display: inline-block;
|
||||
position: absolute;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.fa-layers {
|
||||
display: inline-block;
|
||||
height: 1em;
|
||||
position: relative;
|
||||
text-align: center;
|
||||
vertical-align: -0.125em;
|
||||
width: 1em;
|
||||
}
|
||||
.fa-layers svg.svg-inline--fa {
|
||||
-webkit-transform-origin: center center;
|
||||
transform-origin: center center;
|
||||
}
|
||||
|
||||
.fa-layers-text {
|
||||
left: 50%;
|
||||
top: 50%;
|
||||
-webkit-transform: translate(-50%, -50%);
|
||||
transform: translate(-50%, -50%);
|
||||
-webkit-transform-origin: center center;
|
||||
transform-origin: center center;
|
||||
}
|
||||
|
||||
.fa-layers-counter {
|
||||
background-color: var(--fa-counter-background-color, #ff253a);
|
||||
border-radius: var(--fa-counter-border-radius, 1em);
|
||||
box-sizing: border-box;
|
||||
color: var(--fa-inverse, #fff);
|
||||
line-height: var(--fa-counter-line-height, 1);
|
||||
max-width: var(--fa-counter-max-width, 5em);
|
||||
min-width: var(--fa-counter-min-width, 1.5em);
|
||||
overflow: hidden;
|
||||
padding: var(--fa-counter-padding, 0.25em 0.5em);
|
||||
right: var(--fa-right, 0);
|
||||
text-overflow: ellipsis;
|
||||
top: var(--fa-top, 0);
|
||||
-webkit-transform: scale(var(--fa-counter-scale, 0.25));
|
||||
transform: scale(var(--fa-counter-scale, 0.25));
|
||||
-webkit-transform-origin: top right;
|
||||
transform-origin: top right;
|
||||
}
|
||||
|
||||
.fa-layers-bottom-right {
|
||||
bottom: var(--fa-bottom, 0);
|
||||
right: var(--fa-right, 0);
|
||||
top: auto;
|
||||
-webkit-transform: scale(var(--fa-layers-scale, 0.25));
|
||||
transform: scale(var(--fa-layers-scale, 0.25));
|
||||
-webkit-transform-origin: bottom right;
|
||||
transform-origin: bottom right;
|
||||
}
|
||||
|
||||
.fa-layers-bottom-left {
|
||||
bottom: var(--fa-bottom, 0);
|
||||
left: var(--fa-left, 0);
|
||||
right: auto;
|
||||
top: auto;
|
||||
-webkit-transform: scale(var(--fa-layers-scale, 0.25));
|
||||
transform: scale(var(--fa-layers-scale, 0.25));
|
||||
-webkit-transform-origin: bottom left;
|
||||
transform-origin: bottom left;
|
||||
}
|
||||
|
||||
.fa-layers-top-right {
|
||||
top: var(--fa-top, 0);
|
||||
right: var(--fa-right, 0);
|
||||
-webkit-transform: scale(var(--fa-layers-scale, 0.25));
|
||||
transform: scale(var(--fa-layers-scale, 0.25));
|
||||
-webkit-transform-origin: top right;
|
||||
transform-origin: top right;
|
||||
}
|
||||
|
||||
.fa-layers-top-left {
|
||||
left: var(--fa-left, 0);
|
||||
right: auto;
|
||||
top: var(--fa-top, 0);
|
||||
-webkit-transform: scale(var(--fa-layers-scale, 0.25));
|
||||
transform: scale(var(--fa-layers-scale, 0.25));
|
||||
-webkit-transform-origin: top left;
|
||||
transform-origin: top left;
|
||||
}
|
||||
|
||||
.fa-1x {
|
||||
font-size: 1em;
|
||||
}
|
||||
|
||||
.fa-2x {
|
||||
font-size: 2em;
|
||||
}
|
||||
|
||||
.fa-3x {
|
||||
font-size: 3em;
|
||||
}
|
||||
|
||||
.fa-4x {
|
||||
font-size: 4em;
|
||||
}
|
||||
|
||||
.fa-5x {
|
||||
font-size: 5em;
|
||||
}
|
||||
|
||||
.fa-6x {
|
||||
font-size: 6em;
|
||||
}
|
||||
|
||||
.fa-7x {
|
||||
font-size: 7em;
|
||||
}
|
||||
|
||||
.fa-8x {
|
||||
font-size: 8em;
|
||||
}
|
||||
|
||||
.fa-9x {
|
||||
font-size: 9em;
|
||||
}
|
||||
|
||||
.fa-10x {
|
||||
font-size: 10em;
|
||||
}
|
||||
|
||||
.fa-2xs {
|
||||
font-size: 0.625em;
|
||||
line-height: 0.1em;
|
||||
vertical-align: 0.225em;
|
||||
}
|
||||
|
||||
.fa-xs {
|
||||
font-size: 0.75em;
|
||||
line-height: 0.0833333337em;
|
||||
vertical-align: 0.125em;
|
||||
}
|
||||
|
||||
.fa-sm {
|
||||
font-size: 0.875em;
|
||||
line-height: 0.0714285718em;
|
||||
vertical-align: 0.0535714295em;
|
||||
}
|
||||
|
||||
.fa-lg {
|
||||
font-size: 1.25em;
|
||||
line-height: 0.05em;
|
||||
vertical-align: -0.075em;
|
||||
}
|
||||
|
||||
.fa-xl {
|
||||
font-size: 1.5em;
|
||||
line-height: 0.0416666682em;
|
||||
vertical-align: -0.125em;
|
||||
}
|
||||
|
||||
.fa-2xl {
|
||||
font-size: 2em;
|
||||
line-height: 0.03125em;
|
||||
vertical-align: -0.1875em;
|
||||
}
|
||||
|
||||
.fa-fw {
|
||||
text-align: center;
|
||||
width: 1.25em;
|
||||
}
|
||||
|
||||
.fa-ul {
|
||||
list-style-type: none;
|
||||
margin-left: var(--fa-li-margin, 2.5em);
|
||||
padding-left: 0;
|
||||
}
|
||||
.fa-ul > li {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.fa-li {
|
||||
left: calc(var(--fa-li-width, 2em) * -1);
|
||||
position: absolute;
|
||||
text-align: center;
|
||||
width: var(--fa-li-width, 2em);
|
||||
line-height: inherit;
|
||||
}
|
||||
|
||||
.fa-border {
|
||||
border-color: var(--fa-border-color, #eee);
|
||||
border-radius: var(--fa-border-radius, 0.1em);
|
||||
border-style: var(--fa-border-style, solid);
|
||||
border-width: var(--fa-border-width, 0.08em);
|
||||
padding: var(--fa-border-padding, 0.2em 0.25em 0.15em);
|
||||
}
|
||||
|
||||
.fa-pull-left {
|
||||
float: left;
|
||||
margin-right: var(--fa-pull-margin, 0.3em);
|
||||
}
|
||||
|
||||
.fa-pull-right {
|
||||
float: right;
|
||||
margin-left: var(--fa-pull-margin, 0.3em);
|
||||
}
|
||||
|
||||
.fa-beat {
|
||||
-webkit-animation-name: fa-beat;
|
||||
animation-name: fa-beat;
|
||||
-webkit-animation-delay: var(--fa-animation-delay, 0s);
|
||||
animation-delay: var(--fa-animation-delay, 0s);
|
||||
-webkit-animation-direction: var(--fa-animation-direction, normal);
|
||||
animation-direction: var(--fa-animation-direction, normal);
|
||||
-webkit-animation-duration: var(--fa-animation-duration, 1s);
|
||||
animation-duration: var(--fa-animation-duration, 1s);
|
||||
-webkit-animation-iteration-count: var(--fa-animation-iteration-count, infinite);
|
||||
animation-iteration-count: var(--fa-animation-iteration-count, infinite);
|
||||
-webkit-animation-timing-function: var(--fa-animation-timing, ease-in-out);
|
||||
animation-timing-function: var(--fa-animation-timing, ease-in-out);
|
||||
}
|
||||
|
||||
.fa-bounce {
|
||||
-webkit-animation-name: fa-bounce;
|
||||
animation-name: fa-bounce;
|
||||
-webkit-animation-delay: var(--fa-animation-delay, 0s);
|
||||
animation-delay: var(--fa-animation-delay, 0s);
|
||||
-webkit-animation-direction: var(--fa-animation-direction, normal);
|
||||
animation-direction: var(--fa-animation-direction, normal);
|
||||
-webkit-animation-duration: var(--fa-animation-duration, 1s);
|
||||
animation-duration: var(--fa-animation-duration, 1s);
|
||||
-webkit-animation-iteration-count: var(--fa-animation-iteration-count, infinite);
|
||||
animation-iteration-count: var(--fa-animation-iteration-count, infinite);
|
||||
-webkit-animation-timing-function: var(--fa-animation-timing, cubic-bezier(0.28, 0.84, 0.42, 1));
|
||||
animation-timing-function: var(--fa-animation-timing, cubic-bezier(0.28, 0.84, 0.42, 1));
|
||||
}
|
||||
|
||||
.fa-fade {
|
||||
-webkit-animation-name: fa-fade;
|
||||
animation-name: fa-fade;
|
||||
-webkit-animation-delay: var(--fa-animation-delay, 0s);
|
||||
animation-delay: var(--fa-animation-delay, 0s);
|
||||
-webkit-animation-direction: var(--fa-animation-direction, normal);
|
||||
animation-direction: var(--fa-animation-direction, normal);
|
||||
-webkit-animation-duration: var(--fa-animation-duration, 1s);
|
||||
animation-duration: var(--fa-animation-duration, 1s);
|
||||
-webkit-animation-iteration-count: var(--fa-animation-iteration-count, infinite);
|
||||
animation-iteration-count: var(--fa-animation-iteration-count, infinite);
|
||||
-webkit-animation-timing-function: var(--fa-animation-timing, cubic-bezier(0.4, 0, 0.6, 1));
|
||||
animation-timing-function: var(--fa-animation-timing, cubic-bezier(0.4, 0, 0.6, 1));
|
||||
}
|
||||
|
||||
.fa-beat-fade {
|
||||
-webkit-animation-name: fa-beat-fade;
|
||||
animation-name: fa-beat-fade;
|
||||
-webkit-animation-delay: var(--fa-animation-delay, 0s);
|
||||
animation-delay: var(--fa-animation-delay, 0s);
|
||||
-webkit-animation-direction: var(--fa-animation-direction, normal);
|
||||
animation-direction: var(--fa-animation-direction, normal);
|
||||
-webkit-animation-duration: var(--fa-animation-duration, 1s);
|
||||
animation-duration: var(--fa-animation-duration, 1s);
|
||||
-webkit-animation-iteration-count: var(--fa-animation-iteration-count, infinite);
|
||||
animation-iteration-count: var(--fa-animation-iteration-count, infinite);
|
||||
-webkit-animation-timing-function: var(--fa-animation-timing, cubic-bezier(0.4, 0, 0.6, 1));
|
||||
animation-timing-function: var(--fa-animation-timing, cubic-bezier(0.4, 0, 0.6, 1));
|
||||
}
|
||||
|
||||
.fa-flip {
|
||||
-webkit-animation-name: fa-flip;
|
||||
animation-name: fa-flip;
|
||||
-webkit-animation-delay: var(--fa-animation-delay, 0s);
|
||||
animation-delay: var(--fa-animation-delay, 0s);
|
||||
-webkit-animation-direction: var(--fa-animation-direction, normal);
|
||||
animation-direction: var(--fa-animation-direction, normal);
|
||||
-webkit-animation-duration: var(--fa-animation-duration, 1s);
|
||||
animation-duration: var(--fa-animation-duration, 1s);
|
||||
-webkit-animation-iteration-count: var(--fa-animation-iteration-count, infinite);
|
||||
animation-iteration-count: var(--fa-animation-iteration-count, infinite);
|
||||
-webkit-animation-timing-function: var(--fa-animation-timing, ease-in-out);
|
||||
animation-timing-function: var(--fa-animation-timing, ease-in-out);
|
||||
}
|
||||
|
||||
.fa-shake {
|
||||
-webkit-animation-name: fa-shake;
|
||||
animation-name: fa-shake;
|
||||
-webkit-animation-delay: var(--fa-animation-delay, 0s);
|
||||
animation-delay: var(--fa-animation-delay, 0s);
|
||||
-webkit-animation-direction: var(--fa-animation-direction, normal);
|
||||
animation-direction: var(--fa-animation-direction, normal);
|
||||
-webkit-animation-duration: var(--fa-animation-duration, 1s);
|
||||
animation-duration: var(--fa-animation-duration, 1s);
|
||||
-webkit-animation-iteration-count: var(--fa-animation-iteration-count, infinite);
|
||||
animation-iteration-count: var(--fa-animation-iteration-count, infinite);
|
||||
-webkit-animation-timing-function: var(--fa-animation-timing, linear);
|
||||
animation-timing-function: var(--fa-animation-timing, linear);
|
||||
}
|
||||
|
||||
.fa-spin {
|
||||
-webkit-animation-name: fa-spin;
|
||||
animation-name: fa-spin;
|
||||
-webkit-animation-delay: var(--fa-animation-delay, 0s);
|
||||
animation-delay: var(--fa-animation-delay, 0s);
|
||||
-webkit-animation-direction: var(--fa-animation-direction, normal);
|
||||
animation-direction: var(--fa-animation-direction, normal);
|
||||
-webkit-animation-duration: var(--fa-animation-duration, 2s);
|
||||
animation-duration: var(--fa-animation-duration, 2s);
|
||||
-webkit-animation-iteration-count: var(--fa-animation-iteration-count, infinite);
|
||||
animation-iteration-count: var(--fa-animation-iteration-count, infinite);
|
||||
-webkit-animation-timing-function: var(--fa-animation-timing, linear);
|
||||
animation-timing-function: var(--fa-animation-timing, linear);
|
||||
}
|
||||
|
||||
.fa-spin-reverse {
|
||||
--fa-animation-direction: reverse;
|
||||
}
|
||||
|
||||
.fa-pulse,
|
||||
.fa-spin-pulse {
|
||||
-webkit-animation-name: fa-spin;
|
||||
animation-name: fa-spin;
|
||||
-webkit-animation-direction: var(--fa-animation-direction, normal);
|
||||
animation-direction: var(--fa-animation-direction, normal);
|
||||
-webkit-animation-duration: var(--fa-animation-duration, 1s);
|
||||
animation-duration: var(--fa-animation-duration, 1s);
|
||||
-webkit-animation-iteration-count: var(--fa-animation-iteration-count, infinite);
|
||||
animation-iteration-count: var(--fa-animation-iteration-count, infinite);
|
||||
-webkit-animation-timing-function: var(--fa-animation-timing, steps(8));
|
||||
animation-timing-function: var(--fa-animation-timing, steps(8));
|
||||
}
|
||||
|
||||
@media (prefers-reduced-motion: reduce) {
|
||||
.fa-beat,
|
||||
.fa-bounce,
|
||||
.fa-fade,
|
||||
.fa-beat-fade,
|
||||
.fa-flip,
|
||||
.fa-pulse,
|
||||
.fa-shake,
|
||||
.fa-spin,
|
||||
.fa-spin-pulse {
|
||||
-webkit-animation-delay: -1ms;
|
||||
animation-delay: -1ms;
|
||||
-webkit-animation-duration: 1ms;
|
||||
animation-duration: 1ms;
|
||||
-webkit-animation-iteration-count: 1;
|
||||
animation-iteration-count: 1;
|
||||
-webkit-transition-delay: 0s;
|
||||
transition-delay: 0s;
|
||||
-webkit-transition-duration: 0s;
|
||||
transition-duration: 0s;
|
||||
}
|
||||
}
|
||||
@-webkit-keyframes fa-beat {
|
||||
0%, 90% {
|
||||
-webkit-transform: scale(1);
|
||||
transform: scale(1);
|
||||
}
|
||||
45% {
|
||||
-webkit-transform: scale(var(--fa-beat-scale, 1.25));
|
||||
transform: scale(var(--fa-beat-scale, 1.25));
|
||||
}
|
||||
}
|
||||
@keyframes fa-beat {
|
||||
0%, 90% {
|
||||
-webkit-transform: scale(1);
|
||||
transform: scale(1);
|
||||
}
|
||||
45% {
|
||||
-webkit-transform: scale(var(--fa-beat-scale, 1.25));
|
||||
transform: scale(var(--fa-beat-scale, 1.25));
|
||||
}
|
||||
}
|
||||
@-webkit-keyframes fa-bounce {
|
||||
0% {
|
||||
-webkit-transform: scale(1, 1) translateY(0);
|
||||
transform: scale(1, 1) translateY(0);
|
||||
}
|
||||
10% {
|
||||
-webkit-transform: scale(var(--fa-bounce-start-scale-x, 1.1), var(--fa-bounce-start-scale-y, 0.9)) translateY(0);
|
||||
transform: scale(var(--fa-bounce-start-scale-x, 1.1), var(--fa-bounce-start-scale-y, 0.9)) translateY(0);
|
||||
}
|
||||
30% {
|
||||
-webkit-transform: scale(var(--fa-bounce-jump-scale-x, 0.9), var(--fa-bounce-jump-scale-y, 1.1)) translateY(var(--fa-bounce-height, -0.5em));
|
||||
transform: scale(var(--fa-bounce-jump-scale-x, 0.9), var(--fa-bounce-jump-scale-y, 1.1)) translateY(var(--fa-bounce-height, -0.5em));
|
||||
}
|
||||
50% {
|
||||
-webkit-transform: scale(var(--fa-bounce-land-scale-x, 1.05), var(--fa-bounce-land-scale-y, 0.95)) translateY(0);
|
||||
transform: scale(var(--fa-bounce-land-scale-x, 1.05), var(--fa-bounce-land-scale-y, 0.95)) translateY(0);
|
||||
}
|
||||
57% {
|
||||
-webkit-transform: scale(1, 1) translateY(var(--fa-bounce-rebound, -0.125em));
|
||||
transform: scale(1, 1) translateY(var(--fa-bounce-rebound, -0.125em));
|
||||
}
|
||||
64% {
|
||||
-webkit-transform: scale(1, 1) translateY(0);
|
||||
transform: scale(1, 1) translateY(0);
|
||||
}
|
||||
100% {
|
||||
-webkit-transform: scale(1, 1) translateY(0);
|
||||
transform: scale(1, 1) translateY(0);
|
||||
}
|
||||
}
|
||||
@keyframes fa-bounce {
|
||||
0% {
|
||||
-webkit-transform: scale(1, 1) translateY(0);
|
||||
transform: scale(1, 1) translateY(0);
|
||||
}
|
||||
10% {
|
||||
-webkit-transform: scale(var(--fa-bounce-start-scale-x, 1.1), var(--fa-bounce-start-scale-y, 0.9)) translateY(0);
|
||||
transform: scale(var(--fa-bounce-start-scale-x, 1.1), var(--fa-bounce-start-scale-y, 0.9)) translateY(0);
|
||||
}
|
||||
30% {
|
||||
-webkit-transform: scale(var(--fa-bounce-jump-scale-x, 0.9), var(--fa-bounce-jump-scale-y, 1.1)) translateY(var(--fa-bounce-height, -0.5em));
|
||||
transform: scale(var(--fa-bounce-jump-scale-x, 0.9), var(--fa-bounce-jump-scale-y, 1.1)) translateY(var(--fa-bounce-height, -0.5em));
|
||||
}
|
||||
50% {
|
||||
-webkit-transform: scale(var(--fa-bounce-land-scale-x, 1.05), var(--fa-bounce-land-scale-y, 0.95)) translateY(0);
|
||||
transform: scale(var(--fa-bounce-land-scale-x, 1.05), var(--fa-bounce-land-scale-y, 0.95)) translateY(0);
|
||||
}
|
||||
57% {
|
||||
-webkit-transform: scale(1, 1) translateY(var(--fa-bounce-rebound, -0.125em));
|
||||
transform: scale(1, 1) translateY(var(--fa-bounce-rebound, -0.125em));
|
||||
}
|
||||
64% {
|
||||
-webkit-transform: scale(1, 1) translateY(0);
|
||||
transform: scale(1, 1) translateY(0);
|
||||
}
|
||||
100% {
|
||||
-webkit-transform: scale(1, 1) translateY(0);
|
||||
transform: scale(1, 1) translateY(0);
|
||||
}
|
||||
}
|
||||
@-webkit-keyframes fa-fade {
|
||||
50% {
|
||||
opacity: var(--fa-fade-opacity, 0.4);
|
||||
}
|
||||
}
|
||||
@keyframes fa-fade {
|
||||
50% {
|
||||
opacity: var(--fa-fade-opacity, 0.4);
|
||||
}
|
||||
}
|
||||
@-webkit-keyframes fa-beat-fade {
|
||||
0%, 100% {
|
||||
opacity: var(--fa-beat-fade-opacity, 0.4);
|
||||
-webkit-transform: scale(1);
|
||||
transform: scale(1);
|
||||
}
|
||||
50% {
|
||||
opacity: 1;
|
||||
-webkit-transform: scale(var(--fa-beat-fade-scale, 1.125));
|
||||
transform: scale(var(--fa-beat-fade-scale, 1.125));
|
||||
}
|
||||
}
|
||||
@keyframes fa-beat-fade {
|
||||
0%, 100% {
|
||||
opacity: var(--fa-beat-fade-opacity, 0.4);
|
||||
-webkit-transform: scale(1);
|
||||
transform: scale(1);
|
||||
}
|
||||
50% {
|
||||
opacity: 1;
|
||||
-webkit-transform: scale(var(--fa-beat-fade-scale, 1.125));
|
||||
transform: scale(var(--fa-beat-fade-scale, 1.125));
|
||||
}
|
||||
}
|
||||
@-webkit-keyframes fa-flip {
|
||||
50% {
|
||||
-webkit-transform: rotate3d(var(--fa-flip-x, 0), var(--fa-flip-y, 1), var(--fa-flip-z, 0), var(--fa-flip-angle, -180deg));
|
||||
transform: rotate3d(var(--fa-flip-x, 0), var(--fa-flip-y, 1), var(--fa-flip-z, 0), var(--fa-flip-angle, -180deg));
|
||||
}
|
||||
}
|
||||
@keyframes fa-flip {
|
||||
50% {
|
||||
-webkit-transform: rotate3d(var(--fa-flip-x, 0), var(--fa-flip-y, 1), var(--fa-flip-z, 0), var(--fa-flip-angle, -180deg));
|
||||
transform: rotate3d(var(--fa-flip-x, 0), var(--fa-flip-y, 1), var(--fa-flip-z, 0), var(--fa-flip-angle, -180deg));
|
||||
}
|
||||
}
|
||||
@-webkit-keyframes fa-shake {
|
||||
0% {
|
||||
-webkit-transform: rotate(-15deg);
|
||||
transform: rotate(-15deg);
|
||||
}
|
||||
4% {
|
||||
-webkit-transform: rotate(15deg);
|
||||
transform: rotate(15deg);
|
||||
}
|
||||
8%, 24% {
|
||||
-webkit-transform: rotate(-18deg);
|
||||
transform: rotate(-18deg);
|
||||
}
|
||||
12%, 28% {
|
||||
-webkit-transform: rotate(18deg);
|
||||
transform: rotate(18deg);
|
||||
}
|
||||
16% {
|
||||
-webkit-transform: rotate(-22deg);
|
||||
transform: rotate(-22deg);
|
||||
}
|
||||
20% {
|
||||
-webkit-transform: rotate(22deg);
|
||||
transform: rotate(22deg);
|
||||
}
|
||||
32% {
|
||||
-webkit-transform: rotate(-12deg);
|
||||
transform: rotate(-12deg);
|
||||
}
|
||||
36% {
|
||||
-webkit-transform: rotate(12deg);
|
||||
transform: rotate(12deg);
|
||||
}
|
||||
40%, 100% {
|
||||
-webkit-transform: rotate(0deg);
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
}
|
||||
@keyframes fa-shake {
|
||||
0% {
|
||||
-webkit-transform: rotate(-15deg);
|
||||
transform: rotate(-15deg);
|
||||
}
|
||||
4% {
|
||||
-webkit-transform: rotate(15deg);
|
||||
transform: rotate(15deg);
|
||||
}
|
||||
8%, 24% {
|
||||
-webkit-transform: rotate(-18deg);
|
||||
transform: rotate(-18deg);
|
||||
}
|
||||
12%, 28% {
|
||||
-webkit-transform: rotate(18deg);
|
||||
transform: rotate(18deg);
|
||||
}
|
||||
16% {
|
||||
-webkit-transform: rotate(-22deg);
|
||||
transform: rotate(-22deg);
|
||||
}
|
||||
20% {
|
||||
-webkit-transform: rotate(22deg);
|
||||
transform: rotate(22deg);
|
||||
}
|
||||
32% {
|
||||
-webkit-transform: rotate(-12deg);
|
||||
transform: rotate(-12deg);
|
||||
}
|
||||
36% {
|
||||
-webkit-transform: rotate(12deg);
|
||||
transform: rotate(12deg);
|
||||
}
|
||||
40%, 100% {
|
||||
-webkit-transform: rotate(0deg);
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
}
|
||||
@-webkit-keyframes fa-spin {
|
||||
0% {
|
||||
-webkit-transform: rotate(0deg);
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
100% {
|
||||
-webkit-transform: rotate(360deg);
|
||||
transform: rotate(360deg);
|
||||
}
|
||||
}
|
||||
@keyframes fa-spin {
|
||||
0% {
|
||||
-webkit-transform: rotate(0deg);
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
100% {
|
||||
-webkit-transform: rotate(360deg);
|
||||
transform: rotate(360deg);
|
||||
}
|
||||
}
|
||||
.fa-rotate-90 {
|
||||
-webkit-transform: rotate(90deg);
|
||||
transform: rotate(90deg);
|
||||
}
|
||||
|
||||
.fa-rotate-180 {
|
||||
-webkit-transform: rotate(180deg);
|
||||
transform: rotate(180deg);
|
||||
}
|
||||
|
||||
.fa-rotate-270 {
|
||||
-webkit-transform: rotate(270deg);
|
||||
transform: rotate(270deg);
|
||||
}
|
||||
|
||||
.fa-flip-horizontal {
|
||||
-webkit-transform: scale(-1, 1);
|
||||
transform: scale(-1, 1);
|
||||
}
|
||||
|
||||
.fa-flip-vertical {
|
||||
-webkit-transform: scale(1, -1);
|
||||
transform: scale(1, -1);
|
||||
}
|
||||
|
||||
.fa-flip-both,
|
||||
.fa-flip-horizontal.fa-flip-vertical {
|
||||
-webkit-transform: scale(-1, -1);
|
||||
transform: scale(-1, -1);
|
||||
}
|
||||
|
||||
.fa-rotate-by {
|
||||
-webkit-transform: rotate(var(--fa-rotate-angle, 0));
|
||||
transform: rotate(var(--fa-rotate-angle, 0));
|
||||
}
|
||||
|
||||
.fa-stack {
|
||||
display: inline-block;
|
||||
vertical-align: middle;
|
||||
height: 2em;
|
||||
position: relative;
|
||||
width: 2.5em;
|
||||
}
|
||||
|
||||
.fa-stack-1x,
|
||||
.fa-stack-2x {
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
margin: auto;
|
||||
position: absolute;
|
||||
right: 0;
|
||||
top: 0;
|
||||
z-index: var(--fa-stack-z-index, auto);
|
||||
}
|
||||
|
||||
.svg-inline--fa.fa-stack-1x {
|
||||
height: 1em;
|
||||
width: 1.25em;
|
||||
}
|
||||
.svg-inline--fa.fa-stack-2x {
|
||||
height: 2em;
|
||||
width: 2.5em;
|
||||
}
|
||||
|
||||
.fa-inverse {
|
||||
color: var(--fa-inverse, #fff);
|
||||
}
|
||||
|
||||
.sr-only,
|
||||
.fa-sr-only {
|
||||
position: absolute;
|
||||
width: 1px;
|
||||
height: 1px;
|
||||
padding: 0;
|
||||
margin: -1px;
|
||||
overflow: hidden;
|
||||
clip: rect(0, 0, 0, 0);
|
||||
white-space: nowrap;
|
||||
border-width: 0;
|
||||
}
|
||||
|
||||
.sr-only-focusable:not(:focus),
|
||||
.fa-sr-only-focusable:not(:focus) {
|
||||
position: absolute;
|
||||
width: 1px;
|
||||
height: 1px;
|
||||
padding: 0;
|
||||
margin: -1px;
|
||||
overflow: hidden;
|
||||
clip: rect(0, 0, 0, 0);
|
||||
white-space: nowrap;
|
||||
border-width: 0;
|
||||
}
|
||||
|
||||
.svg-inline--fa .fa-primary {
|
||||
fill: var(--fa-primary-color, currentColor);
|
||||
opacity: var(--fa-primary-opacity, 1);
|
||||
}
|
||||
|
||||
.svg-inline--fa .fa-secondary {
|
||||
fill: var(--fa-secondary-color, currentColor);
|
||||
opacity: var(--fa-secondary-opacity, 0.4);
|
||||
}
|
||||
|
||||
.svg-inline--fa.fa-swap-opacity .fa-primary {
|
||||
opacity: var(--fa-secondary-opacity, 0.4);
|
||||
}
|
||||
|
||||
.svg-inline--fa.fa-swap-opacity .fa-secondary {
|
||||
opacity: var(--fa-primary-opacity, 1);
|
||||
}
|
||||
|
||||
.svg-inline--fa mask .fa-primary,
|
||||
.svg-inline--fa mask .fa-secondary {
|
||||
fill: black;
|
||||
}
|
||||
|
||||
.fad.fa-inverse,
|
||||
.fa-duotone.fa-inverse {
|
||||
color: var(--fa-inverse, #fff);
|
||||
}`;function Xg(){var e=Bg,t=Wg,n=Z.cssPrefix,r=Z.replacementClass,s=JI;if(n!==e||r!==t){var i=new RegExp("\\.".concat(e,"\\-"),"g"),o=new RegExp("\\--".concat(e,"\\-"),"g"),a=new RegExp("\\.".concat(t),"g");s=s.replace(i,".".concat(n,"-")).replace(o,"--".concat(n,"-")).replace(a,".".concat(r))}return s}var zd=!1;function xa(){Z.autoAddCss&&!zd&&(KI(Xg()),zd=!0)}var QI={mixout:function(){return{dom:{css:Xg,insertCss:xa}}},hooks:function(){return{beforeDOMElementCreation:function(){xa()},beforeI2svg:function(){xa()}}}},fn=Mn||{};fn[un]||(fn[un]={});fn[un].styles||(fn[un].styles={});fn[un].hooks||(fn[un].hooks={});fn[un].shims||(fn[un].shims=[]);var Dt=fn[un],Jg=[],ZI=function e(){Me.removeEventListener("DOMContentLoaded",e),mo=1,Jg.map(function(t){return t()})},mo=!1;pn&&(mo=(Me.documentElement.doScroll?/^loaded|^c/:/^loaded|^i|^c/).test(Me.readyState),mo||Me.addEventListener("DOMContentLoaded",ZI));function eP(e){pn&&(mo?setTimeout(e,0):Jg.push(e))}function ui(e){var t=e.tag,n=e.attributes,r=n===void 0?{}:n,s=e.children,i=s===void 0?[]:s;return typeof e=="string"?qg(e):"<".concat(t," ").concat(GI(r),">").concat(i.map(ui).join(""),"</").concat(t,">")}function Gd(e,t,n){if(e&&e[t]&&e[t][n])return{prefix:t,iconName:n,icon:e[t][n]}}var ka=function(t,n,r,s){var i=Object.keys(t),o=i.length,a=n,l,u,c;for(r===void 0?(l=1,c=t[i[0]]):(l=0,c=r);l<o;l++)u=i[l],c=a(c,t[u],u,t);return c};function tP(e){for(var t=[],n=0,r=e.length;n<r;){var s=e.charCodeAt(n++);if(s>=55296&&s<=56319&&n<r){var i=e.charCodeAt(n++);(i&64512)==56320?t.push(((s&1023)<<10)+(i&1023)+65536):(t.push(s),n--)}else t.push(s)}return t}function Ll(e){var t=tP(e);return t.length===1?t[0].toString(16):null}function nP(e,t){var n=e.length,r=e.charCodeAt(t),s;return r>=55296&&r<=56319&&n>t+1&&(s=e.charCodeAt(t+1),s>=56320&&s<=57343)?(r-55296)*1024+s-56320+65536:r}function qd(e){return Object.keys(e).reduce(function(t,n){var r=e[n],s=!!r.icon;return s?t[r.iconName]=r.icon:t[n]=r,t},{})}function Il(e,t){var n=arguments.length>2&&arguments[2]!==void 0?arguments[2]:{},r=n.skipHooks,s=r===void 0?!1:r,i=qd(t);typeof Dt.hooks.addPack=="function"&&!s?Dt.hooks.addPack(e,qd(t)):Dt.styles[e]=X(X({},Dt.styles[e]||{}),i),e==="fas"&&Il("fa",t)}var xi,ki,$i,$r=Dt.styles,rP=Dt.shims,sP=(xi={},qe(xi,$e,Object.values(Gs[$e])),qe(xi,Ve,Object.values(Gs[Ve])),xi),zc=null,Qg={},Zg={},e_={},t_={},n_={},iP=(ki={},qe(ki,$e,Object.keys(Ks[$e])),qe(ki,Ve,Object.keys(Ks[Ve])),ki);function oP(e){return~HI.indexOf(e)}function aP(e,t){var n=t.split("-"),r=n[0],s=n.slice(1).join("-");return r===e&&s!==""&&!oP(s)?s:null}var r_=function(){var t=function(i){return ka($r,function(o,a,l){return o[l]=ka(a,i,{}),o},{})};Qg=t(function(s,i,o){if(i[3]&&(s[i[3]]=o),i[2]){var a=i[2].filter(function(l){return typeof l=="number"});a.forEach(function(l){s[l.toString(16)]=o})}return s}),Zg=t(function(s,i,o){if(s[o]=o,i[2]){var a=i[2].filter(function(l){return typeof l=="string"});a.forEach(function(l){s[l]=o})}return s}),n_=t(function(s,i,o){var a=i[2];return s[o]=o,a.forEach(function(l){s[l]=o}),s});var n="far"in $r||Z.autoFetchSvg,r=ka(rP,function(s,i){var o=i[0],a=i[1],l=i[2];return a==="far"&&!n&&(a="fas"),typeof o=="string"&&(s.names[o]={prefix:a,iconName:l}),typeof o=="number"&&(s.unicodes[o.toString(16)]={prefix:a,iconName:l}),s},{names:{},unicodes:{}});e_=r.names,t_=r.unicodes,zc=qo(Z.styleDefault,{family:Z.familyDefault})};YI(function(e){zc=qo(e.styleDefault,{family:Z.familyDefault})});r_();function Gc(e,t){return(Qg[e]||{})[t]}function lP(e,t){return(Zg[e]||{})[t]}function or(e,t){return(n_[e]||{})[t]}function s_(e){return e_[e]||{prefix:null,iconName:null}}function cP(e){var t=t_[e],n=Gc("fas",e);return t||(n?{prefix:"fas",iconName:n}:null)||{prefix:null,iconName:null}}function Fn(){return zc}var qc=function(){return{prefix:null,iconName:null,rest:[]}};function qo(e){var t=arguments.length>1&&arguments[1]!==void 0?arguments[1]:{},n=t.family,r=n===void 0?$e:n,s=Ks[r][e],i=zs[r][e]||zs[r][s],o=e in Dt.styles?e:null;return i||o||null}var Xd=($i={},qe($i,$e,Object.keys(Gs[$e])),qe($i,Ve,Object.keys(Gs[Ve])),$i);function Xo(e){var t,n=arguments.length>1&&arguments[1]!==void 0?arguments[1]:{},r=n.skipLookups,s=r===void 0?!1:r,i=(t={},qe(t,$e,"".concat(Z.cssPrefix,"-").concat($e)),qe(t,Ve,"".concat(Z.cssPrefix,"-").concat(Ve)),t),o=null,a=$e;(e.includes(i[$e])||e.some(function(u){return Xd[$e].includes(u)}))&&(a=$e),(e.includes(i[Ve])||e.some(function(u){return Xd[Ve].includes(u)}))&&(a=Ve);var l=e.reduce(function(u,c){var f=aP(Z.cssPrefix,c);if($r[c]?(c=sP[a].includes(c)?$I[a][c]:c,o=c,u.prefix=c):iP[a].indexOf(c)>-1?(o=c,u.prefix=qo(c,{family:a})):f?u.iconName=f:c!==Z.replacementClass&&c!==i[$e]&&c!==i[Ve]&&u.rest.push(c),!s&&u.prefix&&u.iconName){var d=o==="fa"?s_(u.iconName):{},m=or(u.prefix,u.iconName);d.prefix&&(o=null),u.iconName=d.iconName||m||u.iconName,u.prefix=d.prefix||u.prefix,u.prefix==="far"&&!$r.far&&$r.fas&&!Z.autoFetchSvg&&(u.prefix="fas")}return u},qc());return(e.includes("fa-bran
Line truncated
|
||||
`);n.setAttribute(_r,""),n.innerHTML=o}};function tm(e){e()}function l_(e,t){var n=typeof t=="function"?t:Gi;if(e.length===0)n();else{var r=tm;Z.mutateApproach===xI&&(r=Mn.requestAnimationFrame||tm),r(function(){var s=OP(),i=Jc.begin("mutate");e.map(s),i(),n()})}}var Qc=!1;function c_(){Qc=!0}function Dl(){Qc=!1}var ho=null;function nm(e){if(Yd&&Z.observeMutations){var t=e.treeCallback,n=t===void 0?Gi:t,r=e.nodeCallback,s=r===void 0?Gi:r,i=e.pseudoElementsCallback,o=i===void 0?Gi:i,a=e.observeMutationsRoot,l=a===void 0?Me:a;ho=new Yd(function(u){if(!Qc){var c=Fn();ds(u).forEach(function(f){if(f.type==="childList"&&f.addedNodes.length>0&&!em(f.addedNodes[0])&&(Z.searchPseudoElements&&o(f.target),n(f.target)),f.type==="attributes"&&f.target.parentNode&&Z.searchPseudoElements&&o(f.target.parentNode),f.type==="attributes"&&em(f.target)&&~UI.indexOf(f.attributeName))if(f.attributeName==="class"&&AP(f.target)){var d=Xo(Yc(f.target)),m=d.prefix,p=d.iconName;f.target.setAttribute(Vc,m||c),p&&f.target.setAttribute(Bc,p)}else TP(f.target)&&s(f.target)})}}),pn&&ho.observe(l,{childList:!0,attributes:!0,characterData:!0,subtree:!0})}}function LP(){ho&&ho.disconnect()}function IP(e){var t=e.getAttribute("style"),n=[];return t&&(n=t.split(";").reduce(function(r,s){var i=s.split(":"),o=i[0],a=i.slice(1);return o&&a.length>0&&(r[o]=a.join(":").trim()),r},{})),n}function PP(e){var t=e.getAttribute("data-prefix"),n=e.getAttribute("data-icon"),r=e.innerText!==void 0?e.innerText.trim():"",s=Xo(Yc(e));return s.prefix||(s.prefix=Fn()),t&&n&&(s.prefix=t,s.iconName=n),s.iconName&&s.prefix||(s.prefix&&r.length>0&&(s.iconName=lP(s.prefix,e.innerText)||Gc(s.prefix,Ll(e.innerText))),!s.iconName&&Z.autoFetchSvg&&e.firstChild&&e.firstChild.nodeType===Node.TEXT_NODE&&(s.iconName=e.firstChild.data)),s}function RP(e){var t=ds(e.attributes).reduce(function(s,i){return s.name!=="class"&&s.name!=="style"&&(s[i.name]=i.value),s},{}),n=e.getAttribute("title"),r=e.getAttribute("data-fa-title-id");return Z.autoA11y&&(n?t["aria-labelledby"]="".concat(Z.replacementClass,"-title-").concat(r||Xs()):(t["aria-hidden"]="true",t.focusable="false")),t}function xP(){return{iconName:null,title:null,titleId:null,prefix:null,transform:zt,symbol:!1,mask:{iconName:null,prefix:null,rest:[]},maskId:null,extra:{classes:[],styles:{},attributes:{}}}}function rm(e){var t=arguments.length>1&&arguments[1]!==void 0?arguments[1]:{styleParser:!0},n=PP(e),r=n.iconName,s=n.prefix,i=n.rest,o=RP(e),a=Pl("parseNodeAttributes",{},e),l=t.styleParser?IP(e):[];return X({iconName:r,title:e.getAttribute("title"),titleId:e.getAttribute("data-fa-title-id"),prefix:s,transform:zt,mask:{iconName:null,prefix:null,rest:[]},maskId:null,symbol:!1,extra:{classes:i,styles:l,attributes:o}},a)}var kP=Dt.styles;function u_(e){var t=Z.autoReplaceSvg==="nest"?rm(e,{styleParser:!1}):rm(e);return~t.extra.classes.indexOf(Kg)?dn("generateLayersText",e,t):dn("generateSvgReplacementMutation",e,t)}var jn=new Set;Wc.map(function(e){jn.add("fa-".concat(e))});Object.keys(Ks[$e]).map(jn.add.bind(jn));Object.keys(Ks[Ve]).map(jn.add.bind(jn));jn=li(jn);function sm(e){var t=arguments.length>1&&arguments[1]!==void 0?arguments[1]:null;if(!pn)return Promise.resolve();var n=Me.documentElement.classList,r=function(f){return n.add("".concat(Kd,"-").concat(f))},s=function(f){return n.remove("".concat(Kd,"-").concat(f))},i=Z.autoFetchSvg?jn:Wc.map(function(c){return"fa-".concat(c)}).concat(Object.keys(kP));i.includes("fa")||i.push("fa");var o=[".".concat(Kg,":not([").concat(_r,"])")].concat(i.map(function(c){return".".concat(c,":not([").concat(_r,"])")})).join(", ");if(o.length===0)return Promise.resolve();var a=[];try{a=ds(e.querySelectorAll(o))}catch{}if(a.length>0)r("pending"),s("complete");else return Promise.resolve();var l=Jc.begin("onTree"),u=a.reduce(function(c,f){try{var d=u_(f);d&&c.push(d)}catch(m){Yg||m.name==="MissingIcon"&&console.error(m)}return c},[]);return new Promise(function(c,f){Promise.all(u).then(function(d){l_(d,function(){r("active"),r("complete"),s("pending"),typeof t=="function"&&t(),l(),c()})}).catch(function(d){l(),f(d)})})}function $P(e){var t=arguments.length>1&&arguments[1]!==void 0?arguments[1]:null;u_(e).then(function(n){n&&l_([n],t)})}function DP(e){return function(t){var n=arguments.length>1&&arguments[1]!==void 0?arguments[1]:{},r=(t||{}).icon?t:Rl(t||{}),s=n.mask;return s&&(s=(s||{}).icon?s:Rl(s||{})),e(r,X(X({},n),{},{mask:s}))}}var MP=function(t){var n=arguments.length>1&&arguments[1]!==void 0?arguments[1]:{},r=n.transform,s=r===void 0?zt:r,i=n.symbol,o=i===void 0?!1:i,a=n.mask,l=a===void 0?null:a,u=n.maskId,c=u===void 0?null:u,f=n.title,d=f===void 0?null:f,m=n.titleId,p=m===void 0?null:m,v=n.classes,y=v===void 0?[]:v,w=n.attributes,S=w===void 0?{}:w,E=n.styles,A=E===void 0?{}:E;if(t){var C=t.prefix,O=t.iconName,I=t.icon;return Jo(X({type:"icon"},t),function(){return vr("beforeDOMElementCreation",{iconDefinition:t,params:n}),Z.autoA11y&&(d?S["aria-labelledby"]="".concat(Z.replacem
Line truncated
|
||||
`),e.removeAttribute(n),r()}).catch(s)}else r()}else r()})}function WP(e){return Promise.all([om(e,"::before"),om(e,"::after")])}function YP(e){return e.parentNode!==document.head&&!~kI.indexOf(e.tagName.toUpperCase())&&!e.getAttribute(Nl)&&(!e.parentNode||e.parentNode.tagName!=="svg")}function am(e){if(pn)return new Promise(function(t,n){var r=ds(e.querySelectorAll("*")).filter(YP).map(WP),s=Jc.begin("searchPseudoElements");c_(),Promise.all(r).then(function(){s(),Dl(),t()}).catch(function(){s(),Dl(),n()})})}var KP={hooks:function(){return{mutationObserverCallbacks:function(n){return n.pseudoElementsCallback=am,n}}},provides:function(t){t.pseudoElements2svg=function(n){var r=n.node,s=r===void 0?Me:r;Z.searchPseudoElements&&am(s)}}},lm=!1,zP={mixout:function(){return{dom:{unwatch:function(){c_(),lm=!0}}}},hooks:function(){return{bootstrap:function(){nm(Pl("mutationObserverCallbacks",{}))},noAuto:function(){LP()},watch:function(n){var r=n.observeMutationsRoot;lm?Dl():nm(Pl("mutationObserverCallbacks",{observeMutationsRoot:r}))}}}},cm=function(t){var n={size:16,x:0,y:0,flipX:!1,flipY:!1,rotate:0};return t.toLowerCase().split(" ").reduce(function(r,s){var i=s.toLowerCase().split("-"),o=i[0],a=i.slice(1).join("-");if(o&&a==="h")return r.flipX=!0,r;if(o&&a==="v")return r.flipY=!0,r;if(a=parseFloat(a),isNaN(a))return r;switch(o){case"grow":r.size=r.size+a;break;case"shrink":r.size=r.size-a;break;case"left":r.x=r.x-a;break;case"right":r.x=r.x+a;break;case"up":r.y=r.y-a;break;case"down":r.y=r.y+a;break;case"rotate":r.rotate=r.rotate+a;break}return r},n)},GP={mixout:function(){return{parse:{transform:function(n){return cm(n)}}}},hooks:function(){return{parseNodeAttributes:function(n,r){var s=r.getAttribute("data-fa-transform");return s&&(n.transform=cm(s)),n}}},provides:function(t){t.generateAbstractTransformGrouping=function(n){var r=n.main,s=n.transform,i=n.containerWidth,o=n.iconWidth,a={transform:"translate(".concat(i/2," 256)")},l="translate(".concat(s.x*32,", ").concat(s.y*32,") "),u="scale(".concat(s.size/16*(s.flipX?-1:1),", ").concat(s.size/16*(s.flipY?-1:1),") "),c="rotate(".concat(s.rotate," 0 0)"),f={transform:"".concat(l," ").concat(u," ").concat(c)},d={transform:"translate(".concat(o/2*-1," -256)")},m={outer:a,inner:f,path:d};return{tag:"g",attributes:X({},m.outer),children:[{tag:"g",attributes:X({},m.inner),children:[{tag:r.icon.tag,children:r.icon.children,attributes:X(X({},r.icon.attributes),m.path)}]}]}}}},Da={x:0,y:0,width:"100%",height:"100%"};function um(e){var t=arguments.length>1&&arguments[1]!==void 0?arguments[1]:!0;return e.attributes&&(e.attributes.fill||t)&&(e.attributes.fill="black"),e}function qP(e){return e.tag==="g"?e.children:[e]}var XP={hooks:function(){return{parseNodeAttributes:function(n,r){var s=r.getAttribute("data-fa-mask"),i=s?Xo(s.split(" ").map(function(o){return o.trim()})):qc();return i.prefix||(i.prefix=Fn()),n.mask=i,n.maskId=r.getAttribute("data-fa-mask-id"),n}}},provides:function(t){t.generateAbstractMask=function(n){var r=n.children,s=n.attributes,i=n.main,o=n.mask,a=n.maskId,l=n.transform,u=i.width,c=i.icon,f=o.width,d=o.icon,m=qI({transform:l,containerWidth:f,iconWidth:u}),p={tag:"rect",attributes:X(X({},Da),{},{fill:"white"})},v=c.children?{children:c.children.map(um)}:{},y={tag:"g",attributes:X({},m.inner),children:[um(X({tag:c.tag,attributes:X(X({},c.attributes),m.path)},v))]},w={tag:"g",attributes:X({},m.outer),children:[y]},S="mask-".concat(a||Xs()),E="clip-".concat(a||Xs()),A={tag:"mask",attributes:X(X({},Da),{},{id:S,maskUnits:"userSpaceOnUse",maskContentUnits:"userSpaceOnUse"}),children:[p,w]},C={tag:"defs",children:[{tag:"clipPath",attributes:{id:E},children:qP(d)},A]};return r.push(C,{tag:"rect",attributes:X({fill:"currentColor","clip-path":"url(#".concat(E,")"),mask:"url(#".concat(S,")")},Da)}),{children:r,attributes:s}}}},JP={provides:function(t){var n=!1;Mn.matchMedia&&(n=Mn.matchMedia("(prefers-reduced-motion: reduce)").matches),t.missingIconAbstract=function(){var r=[],s={fill:"currentColor"},i={attributeType:"XML",repeatCount:"indefinite",dur:"2s"};r.push({tag:"path",attributes:X(X({},s),{},{d:"M156.5,447.7l-12.6,29.5c-18.7-9.5-35.9-21.2-51.5-34.9l22.7-22.7C127.6,430.5,141.5,440,156.5,447.7z M40.6,272H8.5 c1.4,21.2,5.4,41.7,11.7,61.1L50,321.2C45.1,305.5,41.8,289,40.6,272z M40.6,240c1.4-18.8,5.2-37,11.1-54.1l-29.5-12.6 C14.7,194.3,10,216.7,8.5,240H40.6z M64.3,156.5c7.8-14.9,17.2-28.8,28.1-41.5L69.7,92.3c-13.7,15.6-25.5,32.8-34.9,51.5 L64.3,156.5z M397,419.6c-13.9,12-29.4,22.3-46.1,30.4l11.9,29.8c20.7-9.9,39.8-22.6,56.9-37.6L397,419.6z M115,92.4 c13.9-12,29.4-22.3,46.1-30.4l-11.9-29.8c-20.7,9.9-39.8,22.6-56.8,37.6L115,92.4z M447.7,355.5c-7.8,14.9-17.2,28.8-28.1,41.5 l22.7,22.7c13.7-15.6,25.5-32.9,34.9-51.5L447.7,355.5z M471.4,272c-1.4,18.8-5.2,37-11.1,54.1l29.5,12.6 c7.5-21.1,12.2-43.5,13.6-66.8H471.4z M321.2,462c-15.7,5-32.2,8.2-49.2,9.4v32.1c21.2-1.4,41.7-5.4,61.1-11.7L321.2,462z M240,471.4c-18.8-1.4-37-5.2-54.1-11.1l-12.6,29.5c21.1,7.5,43.5,12.2,66
Line truncated
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 4.2 KiB |
@@ -0,0 +1,14 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<link rel="icon" href="/favicon.ico">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Vite App</title>
|
||||
<script type="module" crossorigin src="/assets/index-CPLpx4lq.js"></script>
|
||||
<link rel="stylesheet" crossorigin href="/assets/index-21nzev1V.css">
|
||||
</head>
|
||||
<body>
|
||||
<div id="app"></div>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,14 @@
|
||||
/* eslint-env node */
|
||||
require('@rushstack/eslint-patch/modern-module-resolution')
|
||||
|
||||
module.exports = {
|
||||
root: true,
|
||||
'extends': [
|
||||
'plugin:vue/vue3-essential',
|
||||
'eslint:recommended',
|
||||
'@vue/eslint-config-typescript'
|
||||
],
|
||||
parserOptions: {
|
||||
ecmaVersion: 'latest'
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
# Logs
|
||||
logs
|
||||
*.log
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
pnpm-debug.log*
|
||||
lerna-debug.log*
|
||||
|
||||
node_modules
|
||||
.DS_Store
|
||||
dist
|
||||
dist-ssr
|
||||
coverage
|
||||
*.local
|
||||
|
||||
/cypress/videos/
|
||||
/cypress/screenshots/
|
||||
|
||||
# Editor directories and files
|
||||
.vscode/*
|
||||
!.vscode/extensions.json
|
||||
.idea
|
||||
*.suo
|
||||
*.ntvs*
|
||||
*.njsproj
|
||||
*.sln
|
||||
*.sw?
|
||||
|
||||
*.tsbuildinfo
|
||||
@@ -0,0 +1,45 @@
|
||||
# ReJeobeardy
|
||||
|
||||
This template should help get you started developing with Vue 3 in Vite.
|
||||
|
||||
## Recommended IDE Setup
|
||||
|
||||
[VSCode](https://code.visualstudio.com/) + [Volar](https://marketplace.visualstudio.com/items?itemName=Vue.volar) (and disable Vetur).
|
||||
|
||||
## Type Support for `.vue` Imports in TS
|
||||
|
||||
TypeScript cannot handle type information for `.vue` imports by default, so we replace the `tsc` CLI with `vue-tsc` for type checking. In editors, we need [Volar](https://marketplace.visualstudio.com/items?itemName=Vue.volar) to make the TypeScript language service aware of `.vue` types.
|
||||
|
||||
## Customize configuration
|
||||
|
||||
See [Vite Configuration Reference](https://vitejs.dev/config/).
|
||||
|
||||
## Project Setup
|
||||
|
||||
```sh
|
||||
npm install
|
||||
```
|
||||
|
||||
### Compile and Hot-Reload for Development
|
||||
|
||||
```sh
|
||||
npm run dev
|
||||
```
|
||||
|
||||
### Type-Check, Compile and Minify for Production
|
||||
|
||||
```sh
|
||||
npm run build
|
||||
```
|
||||
|
||||
### Run Unit Tests with [Vitest](https://vitest.dev/)
|
||||
|
||||
```sh
|
||||
npm run test:unit
|
||||
```
|
||||
|
||||
### Lint with [ESLint](https://eslint.org/)
|
||||
|
||||
```sh
|
||||
npm run lint
|
||||
```
|
||||
Vendored
+1
@@ -0,0 +1 @@
|
||||
/// <reference types="vite/client" />
|
||||
@@ -0,0 +1,13 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<link rel="icon" href="/favicon.ico">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Vite App</title>
|
||||
</head>
|
||||
<body>
|
||||
<div id="app"></div>
|
||||
<script type="module" src="/src/main.ts"></script>
|
||||
</body>
|
||||
</html>
|
||||
Generated
+6807
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,50 @@
|
||||
{
|
||||
"name": "rejeobeardy",
|
||||
"version": "0.1.0",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
"build": "run-p type-check \"build-only {@}\" --",
|
||||
"preview": "vite preview",
|
||||
"test:unit": "vitest",
|
||||
"build-only": "vite build",
|
||||
"type-check": "vue-tsc --build --force",
|
||||
"lint": "eslint . --ext .vue,.js,.jsx,.cjs,.mjs,.ts,.tsx,.cts,.mts --fix --ignore-path .gitignore"
|
||||
},
|
||||
"dependencies": {
|
||||
"@fortawesome/fontawesome-svg-core": "^6.5.2",
|
||||
"@fortawesome/free-solid-svg-icons": "^6.5.2",
|
||||
"@fortawesome/vue-fontawesome": "^3.0.8",
|
||||
"@popperjs/core": "^2.11.8",
|
||||
"@vuelidate/core": "^2.0.3",
|
||||
"@vuelidate/validators": "^2.0.4",
|
||||
"axios": "^1.7.2",
|
||||
"bootstrap": "^5.3.3",
|
||||
"pinia": "^2.1.7",
|
||||
"vue": "^3.4.21",
|
||||
"vue-i18n": "^9.13.1",
|
||||
"vue-router": "^4.3.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@rushstack/eslint-patch": "^1.8.0",
|
||||
"@tsconfig/node20": "^20.1.4",
|
||||
"@types/bootstrap": "^5.2.10",
|
||||
"@types/jsdom": "^21.1.6",
|
||||
"@types/node": "^20.12.5",
|
||||
"@vitejs/plugin-vue": "^5.0.4",
|
||||
"@vue/eslint-config-typescript": "^13.0.0",
|
||||
"@vue/test-utils": "^2.4.5",
|
||||
"@vue/tsconfig": "^0.5.1",
|
||||
"eslint": "^8.57.0",
|
||||
"eslint-plugin-vue": "^9.23.0",
|
||||
"jsdom": "^24.0.0",
|
||||
"npm-run-all2": "^6.1.2",
|
||||
"sass": "^1.77.6",
|
||||
"typescript": "~5.4.0",
|
||||
"vite": "^5.2.8",
|
||||
"vite-plugin-vue-devtools": "^7.0.25",
|
||||
"vitest": "^1.4.0",
|
||||
"vue-tsc": "^2.0.11"
|
||||
}
|
||||
}
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 4.2 KiB |
@@ -0,0 +1,37 @@
|
||||
<script setup lang="ts">
|
||||
import { RouterView } from 'vue-router';
|
||||
|
||||
import NavBar from '@/components/blocks/NavBar.vue';
|
||||
import FooterBlock from '@/components/blocks/FooterBlock.vue';
|
||||
import GenericInfoModal from '@/components/modals/GenericInfoModal.vue';
|
||||
import { provide, ref } from 'vue';
|
||||
import { infoModalShowFnKey } from './services/UtilService';
|
||||
|
||||
const infoModal = ref<InstanceType<typeof GenericInfoModal> | null>(null);
|
||||
|
||||
function showInfoModal(title: string, text: string): void{
|
||||
if( infoModal.value ){
|
||||
infoModal.value.modalTitle = title;
|
||||
infoModal.value.modalText = text;
|
||||
infoModal.value.show();
|
||||
} else {
|
||||
console.error('Modal not yet available');
|
||||
}
|
||||
}
|
||||
|
||||
provide(infoModalShowFnKey, showInfoModal);
|
||||
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="vh-100 overflow-y-scroll overflow-x-hidden">
|
||||
<NavBar />
|
||||
|
||||
<RouterView />
|
||||
|
||||
<!-- <FooterBlock /> -->
|
||||
<GenericInfoModal
|
||||
ref="infoModal"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
@@ -0,0 +1,8 @@
|
||||
const { VITE_API_BASE_URL, ...otherViteConfig } = import.meta.env;
|
||||
|
||||
export const ENV = {
|
||||
API_BASE_URL: VITE_API_BASE_URL as string,
|
||||
__vite__: otherViteConfig,
|
||||
};
|
||||
|
||||
console.debug(ENV);
|
||||
@@ -0,0 +1,3 @@
|
||||
.preserve-breaks {
|
||||
white-space: preserve-breaks;
|
||||
}
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 128 KiB |
@@ -0,0 +1,89 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
width="100mm"
|
||||
height="100mm"
|
||||
viewBox="0 0 100 100"
|
||||
version="1.1"
|
||||
id="svg1"
|
||||
inkscape:version="1.3 (0e150ed6c4, 2023-07-21)"
|
||||
sodipodi:docname="PFP_BearHead.svg"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<sodipodi:namedview
|
||||
id="namedview1"
|
||||
pagecolor="#505050"
|
||||
bordercolor="#ffffff"
|
||||
borderopacity="1"
|
||||
inkscape:showpageshadow="0"
|
||||
inkscape:pageopacity="0"
|
||||
inkscape:pagecheckerboard="1"
|
||||
inkscape:deskcolor="#d1d1d1"
|
||||
inkscape:document-units="mm"
|
||||
showguides="true"
|
||||
inkscape:zoom="0.7071068"
|
||||
inkscape:cx="48.790367"
|
||||
inkscape:cy="195.16147"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="1008"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="0"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="layer2" />
|
||||
<defs
|
||||
id="defs1" />
|
||||
<g
|
||||
inkscape:groupmode="layer"
|
||||
id="layer2"
|
||||
inkscape:label="Layer 2"
|
||||
transform="translate(0.01884618,-0.22140619)">
|
||||
<ellipse
|
||||
style="fill:#e86a92;fill-opacity:1;stroke:#ffffff;stroke-width:4.42699;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="ellipse9"
|
||||
ry="13.127905"
|
||||
rx="11.039931"
|
||||
cy="-10.383468"
|
||||
cx="-78.467972"
|
||||
transform="matrix(-0.88593467,-0.46381003,-0.43331387,0.90124309,0,0)" />
|
||||
<ellipse
|
||||
style="fill:#e86a92;fill-opacity:1;stroke:#ffffff;stroke-width:4.42699;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="ellipse8"
|
||||
ry="13.127905"
|
||||
rx="11.039931"
|
||||
cy="36.007061"
|
||||
cx="11.674847"
|
||||
transform="matrix(0.88593467,-0.46381003,0.43331387,0.90124309,0,0)" />
|
||||
<circle
|
||||
style="fill:#e86a92;fill-opacity:1;stroke:#ffffff;stroke-width:4.50669;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="path2"
|
||||
cx="50.009468"
|
||||
cy="51.98246"
|
||||
r="34.316185" />
|
||||
<path
|
||||
style="fill:#e86a92;fill-opacity:1;stroke:#ffffff;stroke-width:4.50669;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="m 43.246556,57.420114 c 0.75711,-2.163936 4.470201,-2.158401 6.762761,-2.158401 2.292561,0 6.005093,-0.0054 6.762762,2.158401 1.136946,3.246879 -3.319062,8.093347 -6.759248,8.094232 -3.441721,8.75e-4 -7.902893,-4.845611 -6.766275,-8.094232 z"
|
||||
id="path5"
|
||||
sodipodi:nodetypes="sssss" />
|
||||
<path
|
||||
style="display:inline;fill:none;fill-opacity:1;stroke:#ffffff;stroke-width:4.50669;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="m 49.984077,65.567745 c 0,4.590286 -0.329314,5.259871 -1.868084,6.148279 -2.521632,1.455864 -5.237785,-0.51905 -6.274968,-1.11787"
|
||||
id="path6"
|
||||
sodipodi:nodetypes="ccc" />
|
||||
<path
|
||||
style="display:inline;fill:none;fill-opacity:1;stroke:#ffffff;stroke-width:4.50669;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="m 49.938836,65.567745 c 0,4.590286 0.329314,5.259871 1.868083,6.148279 2.521632,1.455864 5.237784,-0.51905 6.274969,-1.11787"
|
||||
id="path7"
|
||||
sodipodi:nodetypes="ccc" />
|
||||
<path
|
||||
style="fill:none;fill-opacity:1;stroke:#ffffff;stroke-width:4.50669;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="m 59.773948,42.208084 4.779484,-4.779484 4.778202,4.778204"
|
||||
id="path9" />
|
||||
<path
|
||||
style="fill:none;fill-opacity:1;stroke:#ffffff;stroke-width:4.50669;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="m 29.729393,42.208084 4.779485,-4.779484 4.778201,4.778204"
|
||||
id="path10" />
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 3.8 KiB |
@@ -0,0 +1,113 @@
|
||||
// 1. Include functions first (so you can manipulate colors, SVGs, calc, etc)
|
||||
@import "bootstrap/scss/functions";
|
||||
|
||||
// 2. Include any default variable overrides here
|
||||
|
||||
/* Colors */
|
||||
//Accents
|
||||
$cyclamen: #e86a92ff;
|
||||
$light-coral: #eb8a90ff;
|
||||
$jungle-green: #419d78ff;
|
||||
$celestial-blue: #3e92ccff;
|
||||
|
||||
$raisin-black: #161925ff;
|
||||
$delft-blue: #23395bff;
|
||||
$ucla-blue: #406e8eff;
|
||||
$powder-blue: #8ea8c3ff;
|
||||
$mint-green: #cbf7edff;
|
||||
|
||||
$space-cadet: #2b2d42ff;
|
||||
$cool-gray: #8d99aeff;
|
||||
$anti-flash-white: #edf2f4ff;
|
||||
$rich-black: #2d3543;
|
||||
|
||||
/* Variable definitions */
|
||||
$primary-accent: $cyclamen;
|
||||
$primary-accent-dark: $cyclamen;
|
||||
|
||||
$secondary-accent: $celestial-blue;
|
||||
$secondary-accent-dark: $celestial-blue;
|
||||
// $secondary-accent: $jungle-green;
|
||||
// $secondary-accent-dark: $jungle-green;
|
||||
|
||||
/* Bootstrap Colors overrides */
|
||||
$primary: $primary-accent;
|
||||
$secondary: $secondary-accent;
|
||||
// $success: $green;
|
||||
// $info: $cyan;
|
||||
// $warning: $yellow;
|
||||
// $danger: $red;
|
||||
$light: $anti-flash-white;
|
||||
$light-accented: shade-color($anti-flash-white, 10%);
|
||||
$dark: $space-cadet;
|
||||
$dark-accented: shade-color($space-cadet, 15%);
|
||||
|
||||
|
||||
/* Bootstrap Variable overrides */
|
||||
|
||||
$body-bg-dark: $space-cadet;
|
||||
$body-secondary-bg-dark: $dark-accented;
|
||||
$body-bg: $anti-flash-white;
|
||||
$body-secondary-bg: $light-accented;
|
||||
|
||||
// $font-size-base: 1.5rem;
|
||||
|
||||
// 3. Include remainder of required Bootstrap stylesheets (including any separate color mode stylesheets)
|
||||
@import "bootstrap/scss/variables";
|
||||
@import "bootstrap/scss/variables-dark";
|
||||
|
||||
|
||||
|
||||
// $navbar-dark-active-color: $primary;
|
||||
// $navbar-light-active-color: $primary;
|
||||
|
||||
/* Bootstrap Color Map adjustments */
|
||||
$custom-colors: (
|
||||
"gray": $gray-500,
|
||||
"dark-accented": $dark-accented,
|
||||
"rich-black": $rich-black,
|
||||
);
|
||||
$theme-colors: map-merge($theme-colors, $custom-colors);
|
||||
|
||||
// 4. Include any default map overrides here
|
||||
|
||||
// 5. Include remainder of required parts
|
||||
@import "bootstrap/scss/bootstrap";
|
||||
// @import "bootstrap/scss/maps";
|
||||
// @import "bootstrap/scss/mixins";
|
||||
// @import "bootstrap/scss/root";
|
||||
|
||||
// 6. Optionally include any other parts as needed
|
||||
@import "bootstrap/scss/utilities";
|
||||
// @import "bootstrap/scss/reboot";
|
||||
// @import "bootstrap/scss/type";
|
||||
// @import "bootstrap/scss/images";
|
||||
// @import "bootstrap/scss/containers";
|
||||
// @import "bootstrap/scss/grid";
|
||||
// @import "bootstrap/scss/helpers";
|
||||
|
||||
$utilities: map-merge(
|
||||
$utilities,
|
||||
(
|
||||
"width": map-merge(
|
||||
map-get($utilities, "width"),
|
||||
(
|
||||
values: map-merge(
|
||||
map-get(map-get($utilities, "width"), "values"),
|
||||
(fit-content: fit-content),
|
||||
),
|
||||
),
|
||||
),
|
||||
)
|
||||
);
|
||||
|
||||
|
||||
// 7. Optionally include utilities API last to generate classes based on the Sass map in `_utilities.scss`
|
||||
@import "bootstrap/scss/utilities/api";
|
||||
|
||||
// 8. Add additional custom code here
|
||||
@import "./exotic_theme.scss";
|
||||
|
||||
@import "bootstrap/scss/bootstrap";
|
||||
|
||||
@import "../css/main.css";
|
||||
@@ -0,0 +1,23 @@
|
||||
[data-bs-theme="blue"] {
|
||||
--bs-body-color: var(--bs-pink);
|
||||
--bs-body-color-rgb: #{to-rgb($white)};
|
||||
--bs-body-bg: var(--bs-white);
|
||||
--bs-body-bg-rgb: #{to-rgb($blue)};
|
||||
--bs-tertiary-bg: #{$blue-600};
|
||||
|
||||
.dropdown-menu {
|
||||
--bs-dropdown-bg: #{mix($blue-500, $blue-600)};
|
||||
--bs-dropdown-link-active-bg: #{$blue-700};
|
||||
}
|
||||
|
||||
.btn-secondary {
|
||||
--bs-btn-bg: #{mix($gray-600, $blue-400, .5)};
|
||||
--bs-btn-border-color: #{rgba($white, .25)};
|
||||
--bs-btn-hover-bg: #{darken(mix($gray-600, $blue-400, .5), 5%)};
|
||||
--bs-btn-hover-border-color: #{rgba($white, .25)};
|
||||
--bs-btn-active-bg: #{darken(mix($gray-600, $blue-400, .5), 10%)};
|
||||
--bs-btn-active-border-color: #{rgba($white, .5)};
|
||||
--bs-btn-focus-border-color: #{rgba($white, .5)};
|
||||
--bs-btn-focus-box-shadow: 0 0 0 .25rem rgba(255, 255, 255, .2);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
// import { describe, it, expect } from 'vitest'
|
||||
|
||||
// import { mount } from '@vue/test-utils'
|
||||
// import HelloWorld from '../HelloWorld.vue'
|
||||
|
||||
// describe('HelloWorld', () => {
|
||||
// it('renders properly', () => {
|
||||
// const wrapper = mount(HelloWorld, { props: { msg: 'Hello Vitest' } })
|
||||
// expect(wrapper.text()).toContain('Hello Vitest')
|
||||
// })
|
||||
// })
|
||||
|
||||
|
||||
// Test Example
|
||||
@@ -0,0 +1,48 @@
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref } from 'vue';
|
||||
|
||||
const boards = ref([{
|
||||
id: 1,
|
||||
boardName: "mockBoard",
|
||||
},{
|
||||
id: 2,
|
||||
boardName: "test Mock",
|
||||
},{
|
||||
id: 3,
|
||||
boardName: "Mocka Board",
|
||||
},{
|
||||
id: 4,
|
||||
boardName: "Mocka Board 2",
|
||||
}]);
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="row">
|
||||
<template v-for="board in boards" :key="board.id">
|
||||
<div class="col-4 mb-3">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
{{ board.boardName }}
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<div class="d-flex justify-content-around align-items-center">
|
||||
<button class="btn btn-sm btn-primary">
|
||||
<font-awesome-icon :icon="['fas', 'edit']" />
|
||||
Edit
|
||||
</button>
|
||||
<button class="btn btn-sm btn-primary">
|
||||
<font-awesome-icon :icon="['fas', 'play']" />
|
||||
Play
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
</template>
|
||||
@@ -0,0 +1,23 @@
|
||||
<script setup lang="ts">
|
||||
import LocaleChanger from '@/components/blocks/LocaleChanger.vue';
|
||||
import ThemeChanger from '@/components/blocks/ThemeChanger.vue';
|
||||
import IconJeobeardy from '@/components/icons/IconJeobeardy.vue';
|
||||
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="container-fluid bg-body-secondary p-3 position-absolute bottom-0">
|
||||
<div class="container d-flex align-content-center justify-content-around">
|
||||
|
||||
<div class="d-flex gap-2">
|
||||
<LocaleChanger />
|
||||
<ThemeChanger />
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<IconJeobeardy height="2rem" width="4rem"/>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
@@ -0,0 +1,38 @@
|
||||
<script setup lang="ts">
|
||||
import { onMounted, watch } from 'vue';
|
||||
import { useI18n } from 'vue-i18n';
|
||||
|
||||
const localeLocalStorageKey = 'locale';
|
||||
|
||||
const i18n = useI18n();
|
||||
|
||||
onMounted( () => {
|
||||
const initialLocale = localStorage.getItem( localeLocalStorageKey );
|
||||
if( initialLocale !== null ) {
|
||||
i18n.locale.value = initialLocale;
|
||||
}
|
||||
} );
|
||||
|
||||
watch(
|
||||
() => i18n.locale.value,
|
||||
( newVal ) => {
|
||||
localStorage.setItem( localeLocalStorageKey, newVal );
|
||||
}
|
||||
);
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="dropdown">
|
||||
<button class="btn btn-sm btn-outline-primary dropdown-toggle" type="button" data-bs-toggle="dropdown" aria-expanded="false">
|
||||
{{ $t( `i18n.${$i18n.locale}.name` ) }}
|
||||
</button>
|
||||
<ul class="dropdown-menu">
|
||||
<li v-for=" locale in $i18n.availableLocales " :key="`locale-${locale}`" @click="$i18n.locale = locale"
|
||||
role="button">
|
||||
<a class="dropdown-item pointer" :class="[{ active: $i18n.locale === locale }]">
|
||||
{{ $t( `i18n.${locale}.name` ) }}
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</template>
|
||||
@@ -0,0 +1,75 @@
|
||||
<script setup lang="ts">
|
||||
import { RouterLink, useRoute } from 'vue-router';
|
||||
|
||||
import IconJeobeardy from '@/components/icons/IconJeobeardy.vue';
|
||||
import ThemeChanger from './ThemeChanger.vue';
|
||||
import LocaleChanger from './LocaleChanger.vue';
|
||||
import { useUserStore } from '@/stores/UserStore';
|
||||
|
||||
const navNames = {
|
||||
HOME: "home",
|
||||
ABOUT: "about",
|
||||
}
|
||||
|
||||
const route = useRoute();
|
||||
|
||||
const userStore = useUserStore();
|
||||
|
||||
const isActiveNav = ( navName: string ) => {
|
||||
switch( navName ){
|
||||
default:
|
||||
case navNames.HOME:
|
||||
return route.name === "home";
|
||||
case navNames.ABOUT:
|
||||
return route.name === "about";
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<nav class="navbar navbar-expand-lg bg-dark-accented">
|
||||
<div class="container px-5">
|
||||
|
||||
<div class="position-absolute start-0 top-50 translate-middle-y d-flex ms-3 gap-3">
|
||||
<ThemeChanger />
|
||||
<LocaleChanger />
|
||||
</div>
|
||||
|
||||
<a class="navbar-brand rounded rounded-circle d-block d-lg-none" href="#">
|
||||
<IconJeobeardy height="3.5rem" width="3.5rem" />
|
||||
</a>
|
||||
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarSupportedContent"
|
||||
aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
|
||||
<span class="navbar-toggler-icon"></span>
|
||||
</button>
|
||||
<div class="collapse navbar-collapse" id="navbarSupportedContent">
|
||||
<ul class="navbar-nav mb-2 mb-lg-0 d-flex align-items-center justify-content-center w-100">
|
||||
<li class="nav-item">
|
||||
<RouterLink to="/" class="nav-link text-light fs-3" :class="[{active: isActiveNav(navNames.HOME)}]" :aria-current="isActiveNav(navNames.HOME) ? 'page' : false">{{ $t( 'nav.home' ) }}</RouterLink>
|
||||
</li>
|
||||
<li class="nav-item px-5 mx-5 rounded-5 py-2">
|
||||
<RouterLink to="/" class="nav-link py-0">
|
||||
<IconJeobeardy height="3rem" width="4rem"/>
|
||||
</RouterLink>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<RouterLink to="/about" class="nav-link text-light fs-3" :class="[{active: isActiveNav(navNames.ABOUT)}]" :aria-current="isActiveNav(navNames.HOME) ? 'page' : false">{{ $t( 'nav.about' ) }}</RouterLink>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="position-absolute end-0 top-50 translate-middle-y d-flex me-3">
|
||||
<div v-if="userStore.loggedIn">
|
||||
{{ userStore.getUserOutput }}
|
||||
</div>
|
||||
<div v-else>
|
||||
<RouterLink to="/login" class="btn btn-sm btn-outline-primary">
|
||||
Login
|
||||
</RouterLink>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</nav>
|
||||
</template>
|
||||
@@ -0,0 +1,25 @@
|
||||
<script setup lang="ts">
|
||||
import { useBootstrapTheme } from '@/composables/colorTheme';
|
||||
|
||||
const { availableThemes, currentTheme } = useBootstrapTheme();
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="theme-changer">
|
||||
|
||||
<div class="dropdown">
|
||||
<button class="btn btn-sm btn-outline-primary dropdown-toggle" type="button" data-bs-toggle="dropdown" aria-expanded="false">
|
||||
<FontAwesomeIcon :icon="currentTheme.icon" />
|
||||
{{ $t( currentTheme.name ) }}
|
||||
</button>
|
||||
<ul class="dropdown-menu">
|
||||
<li v-for="theme in availableThemes" :key="`theme-${theme.bsName}`" @click="currentTheme = theme" role="button">
|
||||
<a class="dropdown-item pointer" :class="[{active: theme.bsName === currentTheme.bsName}]">
|
||||
<FontAwesomeIcon :icon="theme.icon" />
|
||||
{{ $t(theme.name) }}
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
@@ -0,0 +1,7 @@
|
||||
<template>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" fill="currentColor">
|
||||
<path
|
||||
d="M15 4a1 1 0 1 0 0 2V4zm0 11v-1a1 1 0 0 0-1 1h1zm0 4l-.707.707A1 1 0 0 0 16 19h-1zm-4-4l.707-.707A1 1 0 0 0 11 14v1zm-4.707-1.293a1 1 0 0 0-1.414 1.414l1.414-1.414zm-.707.707l-.707-.707.707.707zM9 11v-1a1 1 0 0 0-.707.293L9 11zm-4 0h1a1 1 0 0 0-1-1v1zm0 4H4a1 1 0 0 0 1.707.707L5 15zm10-9h2V4h-2v2zm2 0a1 1 0 0 1 1 1h2a3 3 0 0 0-3-3v2zm1 1v6h2V7h-2zm0 6a1 1 0 0 1-1 1v2a3 3 0 0 0 3-3h-2zm-1 1h-2v2h2v-2zm-3 1v4h2v-4h-2zm1.707 3.293l-4-4-1.414 1.414 4 4 1.414-1.414zM11 14H7v2h4v-2zm-4 0c-.276 0-.525-.111-.707-.293l-1.414 1.414C5.42 15.663 6.172 16 7 16v-2zm-.707 1.121l3.414-3.414-1.414-1.414-3.414 3.414 1.414 1.414zM9 12h4v-2H9v2zm4 0a3 3 0 0 0 3-3h-2a1 1 0 0 1-1 1v2zm3-3V3h-2v6h2zm0-6a3 3 0 0 0-3-3v2a1 1 0 0 1 1 1h2zm-3-3H3v2h10V0zM3 0a3 3 0 0 0-3 3h2a1 1 0 0 1 1-1V0zM0 3v6h2V3H0zm0 6a3 3 0 0 0 3 3v-2a1 1 0 0 1-1-1H0zm3 3h2v-2H3v2zm1-1v4h2v-4H4zm1.707 4.707l.586-.586-1.414-1.414-.586.586 1.414 1.414z"
|
||||
/>
|
||||
</svg>
|
||||
</template>
|
||||
@@ -0,0 +1,7 @@
|
||||
<template>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="17" fill="currentColor">
|
||||
<path
|
||||
d="M11 2.253a1 1 0 1 0-2 0h2zm-2 13a1 1 0 1 0 2 0H9zm.447-12.167a1 1 0 1 0 1.107-1.666L9.447 3.086zM1 2.253L.447 1.42A1 1 0 0 0 0 2.253h1zm0 13H0a1 1 0 0 0 1.553.833L1 15.253zm8.447.833a1 1 0 1 0 1.107-1.666l-1.107 1.666zm0-14.666a1 1 0 1 0 1.107 1.666L9.447 1.42zM19 2.253h1a1 1 0 0 0-.447-.833L19 2.253zm0 13l-.553.833A1 1 0 0 0 20 15.253h-1zm-9.553-.833a1 1 0 1 0 1.107 1.666L9.447 14.42zM9 2.253v13h2v-13H9zm1.553-.833C9.203.523 7.42 0 5.5 0v2c1.572 0 2.961.431 3.947 1.086l1.107-1.666zM5.5 0C3.58 0 1.797.523.447 1.42l1.107 1.666C2.539 2.431 3.928 2 5.5 2V0zM0 2.253v13h2v-13H0zm1.553 13.833C2.539 15.431 3.928 15 5.5 15v-2c-1.92 0-3.703.523-5.053 1.42l1.107 1.666zM5.5 15c1.572 0 2.961.431 3.947 1.086l1.107-1.666C9.203 13.523 7.42 13 5.5 13v2zm5.053-11.914C11.539 2.431 12.928 2 14.5 2V0c-1.92 0-3.703.523-5.053 1.42l1.107 1.666zM14.5 2c1.573 0 2.961.431 3.947 1.086l1.107-1.666C18.203.523 16.421 0 14.5 0v2zm3.5.253v13h2v-13h-2zm1.553 12.167C18.203 13.523 16.421 13 14.5 13v2c1.573 0 2.961.431 3.947 1.086l1.107-1.666zM14.5 13c-1.92 0-3.703.523-5.053 1.42l1.107 1.666C11.539 15.431 12.928 15 14.5 15v-2z"
|
||||
/>
|
||||
</svg>
|
||||
</template>
|
||||
@@ -0,0 +1,7 @@
|
||||
<template>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="18" height="20" fill="currentColor">
|
||||
<path
|
||||
d="M11.447 8.894a1 1 0 1 0-.894-1.789l.894 1.789zm-2.894-.789a1 1 0 1 0 .894 1.789l-.894-1.789zm0 1.789a1 1 0 1 0 .894-1.789l-.894 1.789zM7.447 7.106a1 1 0 1 0-.894 1.789l.894-1.789zM10 9a1 1 0 1 0-2 0h2zm-2 2.5a1 1 0 1 0 2 0H8zm9.447-5.606a1 1 0 1 0-.894-1.789l.894 1.789zm-2.894-.789a1 1 0 1 0 .894 1.789l-.894-1.789zm2 .789a1 1 0 1 0 .894-1.789l-.894 1.789zm-1.106-2.789a1 1 0 1 0-.894 1.789l.894-1.789zM18 5a1 1 0 1 0-2 0h2zm-2 2.5a1 1 0 1 0 2 0h-2zm-5.447-4.606a1 1 0 1 0 .894-1.789l-.894 1.789zM9 1l.447-.894a1 1 0 0 0-.894 0L9 1zm-2.447.106a1 1 0 1 0 .894 1.789l-.894-1.789zm-6 3a1 1 0 1 0 .894 1.789L.553 4.106zm2.894.789a1 1 0 1 0-.894-1.789l.894 1.789zm-2-.789a1 1 0 1 0-.894 1.789l.894-1.789zm1.106 2.789a1 1 0 1 0 .894-1.789l-.894 1.789zM2 5a1 1 0 1 0-2 0h2zM0 7.5a1 1 0 1 0 2 0H0zm8.553 12.394a1 1 0 1 0 .894-1.789l-.894 1.789zm-1.106-2.789a1 1 0 1 0-.894 1.789l.894-1.789zm1.106 1a1 1 0 1 0 .894 1.789l-.894-1.789zm2.894.789a1 1 0 1 0-.894-1.789l.894 1.789zM8 19a1 1 0 1 0 2 0H8zm2-2.5a1 1 0 1 0-2 0h2zm-7.447.394a1 1 0 1 0 .894-1.789l-.894 1.789zM1 15H0a1 1 0 0 0 .553.894L1 15zm1-2.5a1 1 0 1 0-2 0h2zm12.553 2.606a1 1 0 1 0 .894 1.789l-.894-1.789zM17 15l.447.894A1 1 0 0 0 18 15h-1zm1-2.5a1 1 0 1 0-2 0h2zm-7.447-5.394l-2 1 .894 1.789 2-1-.894-1.789zm-1.106 1l-2-1-.894 1.789 2 1 .894-1.789zM8 9v2.5h2V9H8zm8.553-4.894l-2 1 .894 1.789 2-1-.894-1.789zm.894 0l-2-1-.894 1.789 2 1 .894-1.789zM16 5v2.5h2V5h-2zm-4.553-3.894l-2-1-.894 1.789 2 1 .894-1.789zm-2.894-1l-2 1 .894 1.789 2-1L8.553.106zM1.447 5.894l2-1-.894-1.789-2 1 .894 1.789zm-.894 0l2 1 .894-1.789-2-1-.894 1.789zM0 5v2.5h2V5H0zm9.447 13.106l-2-1-.894 1.789 2 1 .894-1.789zm0 1.789l2-1-.894-1.789-2 1 .894 1.789zM10 19v-2.5H8V19h2zm-6.553-3.894l-2-1-.894 1.789 2 1 .894-1.789zM2 15v-2.5H0V15h2zm13.447 1.894l2-1-.894-1.789-2 1 .894 1.789zM18 15v-2.5h-2V15h2z"
|
||||
/>
|
||||
</svg>
|
||||
</template>
|
||||
@@ -0,0 +1,38 @@
|
||||
<script setup lang="ts">
|
||||
interface Props {
|
||||
height?: string,
|
||||
width?: string,
|
||||
bearColor?: string,
|
||||
questionmarkColor?: string,
|
||||
}
|
||||
|
||||
const props = withDefaults(defineProps<Props>(), {
|
||||
bearColor: '#e86a92ff',
|
||||
questionmarkColor: '#ffffff',
|
||||
})
|
||||
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
<svg :style="[{height: props.height}, {width: props.width}]" width="103.44236mm" height="80.726883mm" viewBox="0 0 103.44236 80.726882" version="1.1" id="svg5"
|
||||
xml:space="preserve" inkscape:version="1.3.2 (091e20ef0f, 2023-11-25, custom)"
|
||||
sodipodi:docname="jeobeardy_logo_min.svg" xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<defs id="defs2" />
|
||||
<g inkscape:label="Layer 1" inkscape:groupmode="layer" id="layer1" transform="translate(-51.241626,-83.781469)">
|
||||
<path
|
||||
:style="`opacity:1;fill:${props.bearColor};fill-opacity:1;stroke:${props.bearColor};stroke-width:5;stroke-linecap:round;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1;paint-order:stroke fill markers`"
|
||||
d="m 89.597943,161.46239 c 4.957603,-11.31418 10.365454,-13.95841 18.872727,-16.46612 l -0.969,2.23271 10.17543,-3.72589 -1.44748,2.89495 c 7.77057,-2.08212 9.96019,-3.12838 17.29351,-0.22855 8.26326,-4.46932 15.33088,-3.99272 18.58862,-16.15077 0.39797,-1.48523 0.47248,-3.46705 -16.76023,-13.25582 0.6718,-1.59948 -0.64483,-6.30424 -1.44747,-7.69446 -11.87841,-11.878406 -22.82609,-9.786559 -25.14034,-11.122693 -5.10133,-2.945257 -5.77849,-9.894901 -10.741782,-10.89415 -6.64933,-1.781683 -10.639666,-0.422382 -8.015124,7.302597 -4.755054,-0.07748 -19.311199,0.225543 -19.311199,0.225543 l 4.218975,2.479364 -10.418322,0.541411 4.479459,2.526958 c -6.00567,0.93796 -10.085508,3.02646 -13.849528,6.19633 l 3.879167,3.25675 c 11.896264,-8.5256 27.407274,-7.5637 31.986403,1.85066 8.053096,14.19441 -5.364775,20.05902 -11.44594,30.07143 1.070396,5.80331 1.412146,7.38337 3.627235,11.42304 1.414891,2.45066 5.193343,11.34733 6.424889,8.53671 z"
|
||||
id="path919" sodipodi:nodetypes="sccccccccccccccccccccs" />
|
||||
<path
|
||||
:style="`opacity:1;fill:none;stroke:${props.questionmarkColor};stroke-width:8;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1`"
|
||||
d="m 57.671788,111.83817 c 4.776043,-5.45079 12.940609,-7.24498 19.118918,-7.24498 13.656487,0 13.875779,8.51413 14.475615,10.75275 0,14.09963 -13.925936,15.13618 -10.506511,27.69217 0.653123,2.43749 0.932727,3.34729 2.242618,6.17334"
|
||||
id="path2566" sodipodi:nodetypes="ccccc" />
|
||||
<ellipse
|
||||
:style="`opacity:1;fill:${props.questionmarkColor};fill-opacity:1;stroke:${props.questionmarkColor};stroke-width:2.80661;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1`"
|
||||
id="path2620" cy="182.73756" cx="-0.050881278" rx="3.2998796" ry="3.4343019" transform="rotate(-29.11515)" />
|
||||
</g>
|
||||
</svg>
|
||||
</template>
|
||||
@@ -0,0 +1,7 @@
|
||||
<template>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" fill="currentColor">
|
||||
<path
|
||||
d="M10 3.22l-.61-.6a5.5 5.5 0 0 0-7.666.105 5.5 5.5 0 0 0-.114 7.665L10 18.78l8.39-8.4a5.5 5.5 0 0 0-.114-7.665 5.5 5.5 0 0 0-7.666-.105l-.61.61z"
|
||||
/>
|
||||
</svg>
|
||||
</template>
|
||||
@@ -0,0 +1,19 @@
|
||||
<!-- This icon is from <https://github.com/Templarian/MaterialDesign>, distributed under Apache 2.0 (https://www.apache.org/licenses/LICENSE-2.0) license-->
|
||||
<template>
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
aria-hidden="true"
|
||||
role="img"
|
||||
class="iconify iconify--mdi"
|
||||
width="24"
|
||||
height="24"
|
||||
preserveAspectRatio="xMidYMid meet"
|
||||
viewBox="0 0 24 24"
|
||||
>
|
||||
<path
|
||||
d="M20 18v-4h-3v1h-2v-1H9v1H7v-1H4v4h16M6.33 8l-1.74 4H7v-1h2v1h6v-1h2v1h2.41l-1.74-4H6.33M9 5v1h6V5H9m12.84 7.61c.1.22.16.48.16.8V18c0 .53-.21 1-.6 1.41c-.4.4-.85.59-1.4.59H4c-.55 0-1-.19-1.4-.59C2.21 19 2 18.53 2 18v-4.59c0-.32.06-.58.16-.8L4.5 7.22C4.84 6.41 5.45 6 6.33 6H7V5c0-.55.18-1 .57-1.41C7.96 3.2 8.44 3 9 3h6c.56 0 1.04.2 1.43.59c.39.41.57.86.57 1.41v1h.67c.88 0 1.49.41 1.83 1.22l2.34 5.39z"
|
||||
fill="currentColor"
|
||||
></path>
|
||||
</svg>
|
||||
</template>
|
||||
@@ -0,0 +1,66 @@
|
||||
<script setup lang="ts">
|
||||
import { Modal } from 'bootstrap';
|
||||
import { onMounted, onUnmounted, ref } from 'vue';
|
||||
import { useI18n } from 'vue-i18n';
|
||||
|
||||
const { t } = useI18n();
|
||||
|
||||
const modalRef = ref<null | Element>(null);
|
||||
let modalInstance: null | Modal;
|
||||
|
||||
onMounted( () => {
|
||||
modalInstance = Modal.getOrCreateInstance(modalRef.value as Element);
|
||||
});
|
||||
|
||||
onUnmounted( () => {
|
||||
modalInstance?.dispose();
|
||||
});
|
||||
|
||||
function show(){
|
||||
if( modalInstance ){
|
||||
modalInstance.show();
|
||||
} else {
|
||||
console.error("Modal was not properly created before showing");
|
||||
}
|
||||
}
|
||||
|
||||
function hide(){
|
||||
if( modalInstance ){
|
||||
modalInstance.hide();
|
||||
} else {
|
||||
console.error("Modal was not properly created before hiding");
|
||||
}
|
||||
}
|
||||
|
||||
const modalText = ref('');
|
||||
const modalTitle = ref('');
|
||||
const modalId = ref('');
|
||||
|
||||
defineExpose({
|
||||
show,
|
||||
hide,
|
||||
modalText,
|
||||
modalTitle,
|
||||
modalId,
|
||||
});
|
||||
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="modal" tabindex="-1" ref="modalRef" :id="modalId">
|
||||
<div class="modal-dialog modal-dialog-centered">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title">{{ modalTitle }}</h5>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
||||
</div>
|
||||
<div class="modal-body preserve-breaks">
|
||||
<p>{{ modalText }}</p>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-primary" data-bs-dismiss="modal">{{ t("common.buttons.close") }}</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
@@ -0,0 +1,12 @@
|
||||
<script setup lang="ts">
|
||||
import { useI18n } from 'vue-i18n';
|
||||
|
||||
const { t } = useI18n();
|
||||
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div>
|
||||
{{ t( 'about.whatis' ) }}
|
||||
</div>
|
||||
</template>
|
||||
@@ -0,0 +1,12 @@
|
||||
<script setup lang="ts">
|
||||
import { useI18n } from 'vue-i18n';
|
||||
|
||||
const { t } = useI18n();
|
||||
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div>
|
||||
{{ t( 'about.whatis' ) }}
|
||||
</div>
|
||||
</template>
|
||||
@@ -0,0 +1,123 @@
|
||||
<script setup lang="ts">
|
||||
import { ref, onMounted } from 'vue';
|
||||
import { userService } from '@/services/UserService';
|
||||
import IconJeobeardy from '../icons/IconJeobeardy.vue';
|
||||
|
||||
|
||||
const testResponse = ref( {} );
|
||||
|
||||
onMounted( () => {
|
||||
userService.getTest( 'ping', '42' )
|
||||
.then( ( response: any ) => {
|
||||
testResponse.value = response.data;
|
||||
} );
|
||||
} );
|
||||
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<div class="w-100 d-flex justify-content-center my-5">
|
||||
<h1>
|
||||
{{ $t( 'home.welcome' ) }}
|
||||
{{ testResponse }}
|
||||
</h1>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="container-fluid px-0 d-flex justify-content-center align-items-center flex-column">
|
||||
<div class="row w-100 border-top">
|
||||
<div class="col-md-6 col-12 px-0 bg-body-secondary">
|
||||
<div class="d-flex justify-content-center align-items-center h-100 w-100 flex-column">
|
||||
<h3 class="m-1">
|
||||
{{ $t("join.text") }}
|
||||
</h3>
|
||||
<p>
|
||||
{{ $t("join.alreadyHostedGome") }}
|
||||
</p>
|
||||
<p>
|
||||
{{ $t("join.textCode") }}
|
||||
</p>
|
||||
<div class="row">
|
||||
<div class="col-auto">
|
||||
<input type="text" class="form-control" placeholder="Code">
|
||||
</div>
|
||||
<div class="col-auto">
|
||||
<button class="btn btn-primary">{{ $t("join.button") }}</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6 col-12 px-0 mx-0">
|
||||
<img class="w-100" src="/src/assets/images/OldInGameBlurredRotated.jpeg"
|
||||
alt="Blurred, slightly tilted image of how the game looks like">
|
||||
</div>
|
||||
</div>
|
||||
<div class="row w-100 border-bottom">
|
||||
<div class="col-md-6 col-12 px-0 mx-0">
|
||||
<img class="w-100" src="/src/assets/images/OldInGameBlurredRotated.jpeg"
|
||||
alt="Blurred, slightly tilted image of how the game looks like">
|
||||
</div>
|
||||
<div class="col-md-6 col-12 px-0 mx-0 bg-body-secondary">
|
||||
<div class="h-100 w-100 d-flex justify-content-center align-items-center flex-column">
|
||||
<h3 class="m-1">
|
||||
{{ $t("host.text") }}
|
||||
</h3>
|
||||
<p>
|
||||
{{ $t("host.alreadyHostedGome") }}
|
||||
</p>
|
||||
<p>
|
||||
{{ $t("host.textCode") }}
|
||||
</p>
|
||||
<div class="row">
|
||||
<div class="col-auto">
|
||||
<input type="text" class="form-control" placeholder="Code">
|
||||
</div>
|
||||
<div class="col-auto">
|
||||
<button class="btn btn-primary">{{ $t("host.button") }}</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row w-100">
|
||||
<div class="col mt-5 mb-5">
|
||||
<div class="container mb-5 text-center">
|
||||
<h4>
|
||||
How does it work?
|
||||
</h4>
|
||||
<div class="row mt-5">
|
||||
<div class="col-4 d-flex justify-content-center align-items-center flex-column gap-3">
|
||||
<div class="border rounded-circle w-fit-content">
|
||||
<IconJeobeardy height="2rem" width="2rem" />
|
||||
</div>
|
||||
Create a Board
|
||||
</div>
|
||||
<div class="col-4 d-flex justify-content-center align-items-center flex-column gap-3">
|
||||
<div class="border rounded-circle w-fit-content">
|
||||
<IconJeobeardy height="2rem" width="2rem" />
|
||||
</div>
|
||||
Invite your friends
|
||||
</div>
|
||||
<div class="col-4 d-flex justify-content-center align-items-center flex-column gap-3">
|
||||
<div class="border rounded-circle w-fit-content">
|
||||
<IconJeobeardy height="2rem" width="2rem" />
|
||||
</div>
|
||||
Have fun playing
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.home-player-join-row {
|
||||
background-image: url("/src/assets/images/OldInGameBlurredRotated.jpeg");
|
||||
background-repeat: no-repeat;
|
||||
background-size: cover;
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,113 @@
|
||||
<script setup lang="ts">
|
||||
import type { LoginDto } from '@/models/dto/LoginDto';
|
||||
import type { User } from '@/models/user/User';
|
||||
import { authService } from '@/services/AuthService';
|
||||
import { infoModalShowFnKey } from '@/services/UtilService';
|
||||
import { useUserStore } from '@/stores/UserStore';
|
||||
import useVuelidate from '@vuelidate/core';
|
||||
import { createI18nMessage, required } from '@vuelidate/validators';
|
||||
import { computed, inject, ref } from 'vue';
|
||||
import { useI18n } from 'vue-i18n';
|
||||
import { RouterLink, useRouter } from 'vue-router';
|
||||
|
||||
const { t } = useI18n();
|
||||
const router = useRouter();
|
||||
|
||||
const userStore = useUserStore();
|
||||
|
||||
const showInfoModal = inject(infoModalShowFnKey);
|
||||
|
||||
const username = ref('');
|
||||
const password = ref('');
|
||||
|
||||
const errorMessage = ref('');
|
||||
|
||||
const loginInProgress = ref(false);
|
||||
function loginUser(){
|
||||
v$.value.$touch();
|
||||
if(v$.value.$error){
|
||||
errorMessage.value = t('forms.validate-fields');
|
||||
setTimeout(() => {
|
||||
errorMessage.value = '';
|
||||
}, 3000);
|
||||
return;
|
||||
} else {
|
||||
errorMessage.value = '';
|
||||
}
|
||||
const loginDto: LoginDto = { username: username.value, password: password.value };
|
||||
loginInProgress.value = true;
|
||||
authService.loginUser( loginDto )
|
||||
.then( ( response ) => {
|
||||
userStore.setUser(response as User);
|
||||
router.push({ name: 'profile'});
|
||||
})
|
||||
.catch( ( err ) => {
|
||||
console.error(err);
|
||||
const modalText = t('login.error.process');
|
||||
if( showInfoModal !== undefined ){
|
||||
showInfoModal(t('common.error.generic'), modalText);
|
||||
} else {
|
||||
alert(modalText);
|
||||
}
|
||||
})
|
||||
.finally( () => {
|
||||
loginInProgress.value = false;
|
||||
})
|
||||
}
|
||||
|
||||
const withI18nMessage = createI18nMessage({t: t});
|
||||
const inputRequired = withI18nMessage(required);
|
||||
const rules = computed( () => ({
|
||||
username: { inputRequired },
|
||||
password: { inputRequired },
|
||||
}));
|
||||
|
||||
const v$ = useVuelidate(rules, { username, password });
|
||||
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="container d-flex flex-column justify-content-center align-items-center">
|
||||
<div class="row mt-5">
|
||||
<div class="col">
|
||||
<div class="card">
|
||||
<div class="card-header bg-primary p-4">
|
||||
<h2 class="mb-0">
|
||||
{{ t( 'login.loginHeader' ) }}
|
||||
</h2>
|
||||
</div>
|
||||
<div class="card-body bg-body-secondary">
|
||||
<div class="d-flex flex-column gap-3 mt-3">
|
||||
<div class="mb-3">
|
||||
<label for="input-username">
|
||||
{{ t( 'login.username' ) }}
|
||||
<span v-if="v$.username.$error" class="text-danger ps-3">
|
||||
{{ v$.username.$errors[0].$message }}
|
||||
</span></label>
|
||||
<input v-model="username" type="text" id="input-username" class="form-control" :class="[{'border-danger': v$.username.$error}]" @blur="v$.username.$touch">
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label for="input-username">
|
||||
{{ t( 'login.password' ) }}
|
||||
<span v-if="v$.password.$error" class="text-danger ps-3">
|
||||
{{ v$.password.$errors[0].$message }}
|
||||
</span>
|
||||
</label>
|
||||
<input v-model="password" type="password" id="input-username" class="form-control" :class="[{'border-danger': v$.password.$error}]" @blur="v$.password.$touch">
|
||||
</div>
|
||||
<div class="mb-3 d-flex justify-content-between">
|
||||
<RouterLink to="/signup" class="btn btn-outline-primary">
|
||||
{{ t( "login.signupLinkButton" ) }}
|
||||
</RouterLink>
|
||||
<button class="btn btn-primary" @click="loginUser">
|
||||
{{ t( "login.loginButton" ) }}
|
||||
</button>
|
||||
</div>
|
||||
<div v-if="errorMessage" class="alert alert-danger" role="alert">{{ errorMessage }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
@@ -0,0 +1,47 @@
|
||||
<script setup lang="ts">
|
||||
import { useUserStore } from '@/stores/UserStore';
|
||||
import { computed } from 'vue';
|
||||
import { useI18n } from 'vue-i18n';
|
||||
import BoardSelector from '@/components/blocks/BoardSelector.vue';
|
||||
|
||||
const { t } = useI18n();
|
||||
|
||||
const userStore = useUserStore();
|
||||
|
||||
const pfpSource = computed( () => {
|
||||
return ( userStore.profilePicture === null ? "/src/assets/images/PFP_BearHead.svg" : userStore.profilePicture )
|
||||
})
|
||||
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="d-flex flex-column justify-content-center align-items-center mt-5">
|
||||
<h1>
|
||||
{{ $t('profile.yourProfile') }}
|
||||
</h1>
|
||||
<div class="ratio ratio-1x1 border rounded-5" style="width: 15rem;">
|
||||
<img :src="pfpSource" alt="Your Profile Picture" />
|
||||
</div>
|
||||
<p class="fs-3">
|
||||
{{ userStore.username }}
|
||||
</p>
|
||||
<div class="row bg-body-secondary w-100 py-4">
|
||||
<div class="col text-center">
|
||||
<h2>
|
||||
{{ $t('profile.yourBoards') }}
|
||||
</h2>
|
||||
<div class="container">
|
||||
<BoardSelector />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row w-100 py-4 mb-5">
|
||||
<div class="col text-center">
|
||||
<h2>
|
||||
{{ $t('settings.heading') }}
|
||||
</h2>
|
||||
<button class="btn btn-outline-primary">{{ $t('profile.gotoSettings') }}</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
@@ -0,0 +1,126 @@
|
||||
<script setup lang="ts">
|
||||
import { type LoginDto } from '@/models/dto/LoginDto';
|
||||
import type { User } from '@/models/user/User';
|
||||
import { authService } from '@/services/AuthService';
|
||||
import { infoModalShowFnKey } from '@/services/UtilService';
|
||||
import { useUserStore } from '@/stores/UserStore';
|
||||
import useVuelidate from '@vuelidate/core';
|
||||
import { createI18nMessage, minLength, required, sameAs } from '@vuelidate/validators';
|
||||
import { computed, inject, ref } from 'vue';
|
||||
import { useI18n } from 'vue-i18n';
|
||||
import { RouterLink, useRouter } from 'vue-router';
|
||||
|
||||
const { t } = useI18n();
|
||||
const router = useRouter();
|
||||
|
||||
const userStore = useUserStore();
|
||||
|
||||
const showInfoModal = inject(infoModalShowFnKey);
|
||||
|
||||
const username = ref('');
|
||||
const password = ref('');
|
||||
const passwordRepeat = ref('');
|
||||
|
||||
const errorMessage = ref('');
|
||||
|
||||
const signupInProgress = ref(false);
|
||||
function signupUser(){
|
||||
v$.value.$touch();
|
||||
if(v$.value.$error){
|
||||
errorMessage.value = t('forms.validate-fields');
|
||||
setTimeout(() => {
|
||||
errorMessage.value = '';
|
||||
}, 3000);
|
||||
return;
|
||||
} else {
|
||||
errorMessage.value = '';
|
||||
}
|
||||
const signupDto: LoginDto = { username: username.value, password: password.value };
|
||||
signupInProgress.value = true;
|
||||
authService.signupUser( signupDto )
|
||||
.then( ( response ) => {
|
||||
userStore.setUser(response as User);
|
||||
router.push({ name: 'profile'});
|
||||
})
|
||||
.catch( ( err ) => {
|
||||
console.error(err);
|
||||
const modalText = t('signup.error.process');
|
||||
if( showInfoModal !== undefined ){
|
||||
showInfoModal(t('common.error.generic'), modalText);
|
||||
} else {
|
||||
alert(modalText);
|
||||
}
|
||||
})
|
||||
.finally( () => {
|
||||
signupInProgress.value = false;
|
||||
})
|
||||
}
|
||||
|
||||
const withI18nMessage = createI18nMessage({t: t});
|
||||
const inputRequired = withI18nMessage(required);
|
||||
const rules = computed( () => ({
|
||||
username: { inputRequired },
|
||||
password: { inputRequired, minLength: withI18nMessage(minLength(10)) },
|
||||
passwordRepeat: { inputRequired, sameAs: withI18nMessage(sameAs(password.value, t('login.password'))) },
|
||||
}));
|
||||
|
||||
const v$ = useVuelidate(rules, { username, password, passwordRepeat });
|
||||
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="container d-flex flex-column justify-content-center align-items-center">
|
||||
<div class="row mt-5">
|
||||
<div class="col">
|
||||
<div class="card">
|
||||
<div class="card-header bg-primary p-4">
|
||||
<h2 class="mb-0">
|
||||
{{ t( 'signup.signupHeader' ) }}
|
||||
</h2>
|
||||
</div>
|
||||
<div class="card-body bg-body-secondary">
|
||||
<div class="d-flex flex-column gap-3 mt-3">
|
||||
<div class="mb-3">
|
||||
<label for="input-username">
|
||||
{{ t( 'login.username' ) }}
|
||||
<span v-if="v$.username.$error" class="text-danger ps-3">
|
||||
{{ v$.username.$errors[0].$message }}
|
||||
</span>
|
||||
</label>
|
||||
<input type="text" id="input-username" class="form-control" :class="[{'border-danger': v$.username.$error}]" v-model="username" @blur="v$.username.$touch">
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label for="input-username">
|
||||
{{ t( 'login.password' ) }}
|
||||
<span v-if="v$.password.$error" class="text-danger ps-3">
|
||||
{{ v$.password.$errors[0].$message }}
|
||||
</span>
|
||||
</label>
|
||||
<input type="password" id="input-username" class="form-control" :class="[{'border-danger': v$.password.$error}]" v-model="password" @blur="v$.password.$touch">
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label for="input-username-repeat">
|
||||
{{ t( 'signup.password-repeat' ) }}
|
||||
<span v-if="v$.passwordRepeat.$error" class="text-danger ps-3">
|
||||
{{ v$.passwordRepeat.$errors[0].$message }}
|
||||
</span>
|
||||
</label>
|
||||
<input type="password" id="input-username-repeat" class="form-control" :class="[{'border-danger': v$.passwordRepeat.$error}]" v-model="passwordRepeat" @blur="v$.passwordRepeat.$touch">
|
||||
</div>
|
||||
<div class="mb-3 d-flex justify-content-between">
|
||||
<RouterLink to="/login" class="btn btn-outline-primary">
|
||||
{{ t( "signup.loginLinkButton" ) }}
|
||||
</RouterLink>
|
||||
<button class="btn btn-primary" @click="signupUser" :disabled="signupInProgress">
|
||||
<font-awesome-icon v-if="signupInProgress" :icon="['fas', 'spinner']" spin/>
|
||||
{{ t( "signup.signupButton" ) }}
|
||||
</button>
|
||||
</div>
|
||||
<div v-if="errorMessage" class="alert alert-danger" role="alert">{{ errorMessage }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
@@ -0,0 +1,57 @@
|
||||
import { onMounted, ref, watch } from "vue";
|
||||
|
||||
const localStorageKey = "theme";
|
||||
|
||||
const darkTheme = {
|
||||
bsName: "dark",
|
||||
name: "theme.dark.name",
|
||||
icon: ["fas", "moon"],
|
||||
};
|
||||
const lightTheme = {
|
||||
bsName: "light",
|
||||
name: "theme.light.name",
|
||||
icon: ["fas", "sun"],
|
||||
};
|
||||
const highContrastTheme = {
|
||||
bsName: "high-contrast",
|
||||
name: "theme.high-contrast.name",
|
||||
icon: ["fas", "circle-half-stroke"],
|
||||
};
|
||||
|
||||
export function useBootstrapTheme() {
|
||||
|
||||
const availableThemes = ref( [
|
||||
darkTheme,
|
||||
lightTheme,
|
||||
highContrastTheme,
|
||||
] );
|
||||
|
||||
onMounted( () => {
|
||||
let initialThemeBsName: string | null = localStorage.getItem( localStorageKey );
|
||||
if( initialThemeBsName == null ) {
|
||||
localStorage.setItem( localStorageKey, "dark" );
|
||||
initialThemeBsName = "dark";
|
||||
}
|
||||
const initialTheme = availableThemes.value.findIndex( theme => theme.bsName === initialThemeBsName );
|
||||
if( initialTheme !== -1 ) {
|
||||
currentTheme.value = availableThemes.value[initialTheme];
|
||||
}
|
||||
const htmlElem = document.getElementsByTagName( 'html' );
|
||||
htmlElem[0].dataset.bsTheme = currentTheme.value.bsName;
|
||||
} );
|
||||
|
||||
const currentTheme = ref( darkTheme );
|
||||
|
||||
watch(
|
||||
currentTheme,
|
||||
( newVal ) => {
|
||||
document.getElementsByTagName( 'html' )[0].dataset.bsTheme = newVal.bsName;
|
||||
localStorage.setItem( localStorageKey, newVal.bsName );
|
||||
}
|
||||
);
|
||||
|
||||
return {
|
||||
availableThemes,
|
||||
currentTheme,
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
{
|
||||
"home": {
|
||||
"welcome": "Willkommen bei Jeobeardy!"
|
||||
},
|
||||
"about": {
|
||||
"whatis": "Was ist Jeobeardy?"
|
||||
},
|
||||
"login": {
|
||||
"loginHeader": "Logge dich mit deinem Jeobeardy Konto ein",
|
||||
"username": "Benutzername",
|
||||
"password": "Passwort"
|
||||
},
|
||||
"theme": {
|
||||
"dark": {
|
||||
"name": "Dunkel"
|
||||
},
|
||||
"light": {
|
||||
"name": "Hell"
|
||||
},
|
||||
"high-contrast": {
|
||||
"name": "Hoher Kontrast"
|
||||
}
|
||||
},
|
||||
"i18n": {
|
||||
"en": {
|
||||
"name": "Englisch",
|
||||
"shortName": "en"
|
||||
},
|
||||
"de": {
|
||||
"name": "Deutsch",
|
||||
"shortName": "de"
|
||||
}
|
||||
},
|
||||
"nav": {
|
||||
"home": "Home",
|
||||
"about": "Über"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,90 @@
|
||||
{
|
||||
"home": {
|
||||
"welcome": "Welcome to Jeobeardy!"
|
||||
},
|
||||
"about": {
|
||||
"whatis": "What is Jeobeardy?"
|
||||
},
|
||||
"login": {
|
||||
"loginHeader": "Login to your Jeobeardy Account",
|
||||
"loginButton": "Login",
|
||||
"signupLinkButton": "Sign up",
|
||||
"username": "Username",
|
||||
"password": "Password",
|
||||
"error": {
|
||||
"process": "An error occured during the login process"
|
||||
}
|
||||
},
|
||||
"signup": {
|
||||
"signupHeader": "Create a new Jeobeardy Account",
|
||||
"signupButton": "Sign Up",
|
||||
"loginLinkButton": "Back to Login",
|
||||
"password-repeat": "Repeat Password",
|
||||
"password-not-conform": "The password does not meet the required criteria",
|
||||
"password-criteria-length": "The password needs to be at least 10 characters long",
|
||||
"error": {
|
||||
"process": "An error occured during the signup process"
|
||||
}
|
||||
},
|
||||
"forms": {
|
||||
"validate-fields": "Make sure that all fields are valid"
|
||||
},
|
||||
"validations": {
|
||||
"inputRequired": "This field is required",
|
||||
"minLength": "Minimum of {min} characters required",
|
||||
"sameAs": "Must match {otherName}"
|
||||
},
|
||||
"profile": {
|
||||
"yourProfile": "Your Profile",
|
||||
"yourBoards": "Your Boards",
|
||||
"gotoSettings": "Go to Settings"
|
||||
},
|
||||
"settings": {
|
||||
"heading": "Settings"
|
||||
},
|
||||
"common": {
|
||||
"buttons": {
|
||||
"close": "Close"
|
||||
},
|
||||
"error": {
|
||||
"generic": "Error"
|
||||
}
|
||||
},
|
||||
"join": {
|
||||
"button": "Join",
|
||||
"text": "Join a Game",
|
||||
"alreadyHostedGome": "Someone else is already hosting a game?",
|
||||
"textCode": "Enter the code you get from your host and join the lobby."
|
||||
},
|
||||
"host": {
|
||||
"button": "Host",
|
||||
"text": "Host a Game",
|
||||
"alreadyHostedGome": "Wanna create a board and host a game yourself?",
|
||||
"textCode": "Wanna create a board and host a game yourself?"
|
||||
},
|
||||
"theme": {
|
||||
"dark": {
|
||||
"name": "Dark"
|
||||
},
|
||||
"light": {
|
||||
"name": "Light"
|
||||
},
|
||||
"highContrast": {
|
||||
"name": "High Contrast"
|
||||
}
|
||||
},
|
||||
"i18n": {
|
||||
"en": {
|
||||
"name": "English",
|
||||
"shortName": "en"
|
||||
},
|
||||
"de": {
|
||||
"name": "German",
|
||||
"shortName": "de"
|
||||
}
|
||||
},
|
||||
"nav": {
|
||||
"home": "Home",
|
||||
"about": "About"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
import { createApp } from 'vue';
|
||||
import { createPinia } from 'pinia';
|
||||
import { createI18n } from 'vue-i18n';
|
||||
|
||||
import App from './App.vue';
|
||||
import router from './router';
|
||||
|
||||
import '@/assets/scss/customized_bootstrap.scss';
|
||||
|
||||
// Importing bootstrap components which rely on js here
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
import { Dropdown } from 'bootstrap';
|
||||
|
||||
import { FontAwesomeIcon } from '@fortawesome/vue-fontawesome';
|
||||
import { library } from '@fortawesome/fontawesome-svg-core';
|
||||
import { faSun, faMoon, faCircleHalfStroke, faEdit, faPlay, faSpinner } from '@fortawesome/free-solid-svg-icons';
|
||||
|
||||
import enMessages from './locales/en.json';
|
||||
import deMessages from './locales/de.json';
|
||||
|
||||
const i18n = createI18n( {
|
||||
legacy: false,
|
||||
locale: 'en',
|
||||
fallbackLocale: 'en',
|
||||
messages: {
|
||||
en: enMessages,
|
||||
de: deMessages,
|
||||
}
|
||||
} );
|
||||
|
||||
library.add(
|
||||
faSun,
|
||||
faMoon,
|
||||
faCircleHalfStroke,
|
||||
faEdit,
|
||||
faPlay,
|
||||
faSpinner
|
||||
)
|
||||
|
||||
const app = createApp( App );
|
||||
|
||||
app.use( createPinia() );
|
||||
app.component( 'FontAwesomeIcon', FontAwesomeIcon );
|
||||
app.use( router );
|
||||
app.use( i18n );
|
||||
|
||||
app.mount( '#app' );
|
||||
@@ -0,0 +1,14 @@
|
||||
// export class LoginDto{
|
||||
// username: String;
|
||||
// password: String;
|
||||
|
||||
// constructor(username: String, password: String){
|
||||
// this.username = username;
|
||||
// this.password = password;
|
||||
// }
|
||||
// }
|
||||
|
||||
export type LoginDto = {
|
||||
username: String;
|
||||
password: String;
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
export type User = {
|
||||
username: string,
|
||||
password: string,
|
||||
profilePictureFilename: string | undefined,
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
import { createRouter, createWebHistory } from 'vue-router';
|
||||
import HomePage from '@/components/pages/HomePage.vue';
|
||||
import AboutPage from '@/components/pages/AboutPage.vue';
|
||||
import LoginPage from '@/components/pages/LoginPage.vue';
|
||||
import SignupPage from '@/components/pages/SignupPage.vue';
|
||||
import GamePage from '@/components/pages/GamePage.vue';
|
||||
import ProfilePage from '@/components/pages/ProfilePage.vue';
|
||||
|
||||
const router = createRouter( {
|
||||
history: createWebHistory( import.meta.env.BASE_URL ),
|
||||
routes: [
|
||||
{
|
||||
path: '/',
|
||||
name: 'home',
|
||||
component: HomePage,
|
||||
},
|
||||
{
|
||||
path: '/about',
|
||||
name: 'about',
|
||||
component: AboutPage,
|
||||
},
|
||||
{
|
||||
path: '/login',
|
||||
name: 'login',
|
||||
component: LoginPage,
|
||||
},
|
||||
{
|
||||
path: '/signup',
|
||||
name: 'signup',
|
||||
component: SignupPage,
|
||||
},
|
||||
{
|
||||
path: '/profile',
|
||||
name: 'profile',
|
||||
component: ProfilePage,
|
||||
},
|
||||
{
|
||||
path: '/game',
|
||||
name: 'Game',
|
||||
component: GamePage,
|
||||
},
|
||||
// {
|
||||
// path: '/about',
|
||||
// name: 'about',
|
||||
// // route level code-splitting
|
||||
// // this generates a separate chunk (About.[hash].js) for this route
|
||||
// // which is lazy-loaded when the route is visited.
|
||||
// component: () => import('../views/AboutView.vue')
|
||||
// }
|
||||
]
|
||||
} );
|
||||
|
||||
export default router;
|
||||
@@ -0,0 +1,61 @@
|
||||
import { ENV } from "@/Env";
|
||||
import type { LoginDto } from '@/models/dto/LoginDto';
|
||||
import axios from "axios";
|
||||
|
||||
|
||||
class AuthService {
|
||||
|
||||
signupUser( signupDto: LoginDto ) {
|
||||
return new Promise( ( resolve, reject ) => {
|
||||
axios.post( `${ENV.API_BASE_URL}/auth/signup`,
|
||||
signupDto,
|
||||
{
|
||||
withCredentials: true,
|
||||
},
|
||||
)
|
||||
.then( ( response ) => {
|
||||
resolve( response.data );
|
||||
} )
|
||||
.catch( ( error ) => {
|
||||
reject( error );
|
||||
} );
|
||||
} );
|
||||
}
|
||||
|
||||
loginUser( loginDto: LoginDto ) {
|
||||
return new Promise( ( resolve, reject ) => {
|
||||
axios.post( `${ENV.API_BASE_URL}/auth/login`,
|
||||
loginDto,
|
||||
{
|
||||
withCredentials: true,
|
||||
},
|
||||
)
|
||||
.then( ( response ) => {
|
||||
resolve( response );
|
||||
} )
|
||||
.catch( ( error ) => {
|
||||
reject( error );
|
||||
} );
|
||||
} );
|
||||
}
|
||||
|
||||
logoutUser() {
|
||||
return new Promise( ( resolve, reject ) => {
|
||||
axios.post( `${ENV.API_BASE_URL}/auth/logout`,
|
||||
null,
|
||||
{
|
||||
withCredentials: true,
|
||||
},
|
||||
)
|
||||
.then( ( response ) => {
|
||||
resolve( response );
|
||||
} )
|
||||
.catch( ( error ) => {
|
||||
reject( error );
|
||||
} );
|
||||
} );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export const authService = new AuthService();
|
||||
@@ -0,0 +1,26 @@
|
||||
import { ENV } from "@/Env";
|
||||
import axios from "axios";
|
||||
|
||||
class UserService {
|
||||
|
||||
getTest( pathVar: String, param: String ) {
|
||||
return new Promise( ( resolve, reject ) => {
|
||||
axios.get( `${ENV.API_BASE_URL}/user/test/${pathVar}`,
|
||||
{
|
||||
params: {
|
||||
"param1": param,
|
||||
},
|
||||
withCredentials: true,
|
||||
},
|
||||
)
|
||||
.then( ( response ) => {
|
||||
resolve( response );
|
||||
} )
|
||||
.catch( ( error ) => {
|
||||
reject( error );
|
||||
} );
|
||||
} );
|
||||
}
|
||||
}
|
||||
|
||||
export const userService = new UserService();
|
||||
@@ -0,0 +1,8 @@
|
||||
import type { InjectionKey } from 'vue';
|
||||
|
||||
class UtilService{
|
||||
|
||||
|
||||
}
|
||||
|
||||
export const infoModalShowFnKey = Symbol() as InjectionKey<Function>;
|
||||
@@ -0,0 +1,38 @@
|
||||
import { computed, ref } from "vue";
|
||||
import { defineStore } from "pinia";
|
||||
import type { User } from '@/models/user/User';
|
||||
|
||||
export const useUserStore = defineStore( 'user', () => {
|
||||
const username = ref( '' );
|
||||
const profilePicture = ref<undefined | string>( undefined );
|
||||
const loggedIn = ref(false);
|
||||
|
||||
const getUserOutput = computed(() => `${username.value}`);
|
||||
|
||||
function setUser(user: User){
|
||||
username.value = user.username;
|
||||
profilePicture.value = user.profilePictureFilename;
|
||||
loggedIn.value = true;
|
||||
sessionStorage.setItem() //???
|
||||
}
|
||||
|
||||
function unsetUser(){
|
||||
username.value = '';
|
||||
profilePicture.value = undefined;
|
||||
loggedIn.value = false;
|
||||
}
|
||||
|
||||
return {
|
||||
//Refs
|
||||
username,
|
||||
profilePicture,
|
||||
loggedIn,
|
||||
|
||||
//Getters
|
||||
getUserOutput,
|
||||
|
||||
//Functions
|
||||
setUser,
|
||||
unsetUser,
|
||||
};
|
||||
} );
|
||||
@@ -0,0 +1,14 @@
|
||||
{
|
||||
"extends": "@vue/tsconfig/tsconfig.dom.json",
|
||||
"include": ["env.d.ts", "src/**/**/*", "src/**/**/*.vue"],
|
||||
"exclude": ["src/**/__tests__/*"],
|
||||
"compilerOptions": {
|
||||
"composite": true,
|
||||
"tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo",
|
||||
"baseUrl": ".",
|
||||
"paths": {
|
||||
"@/*": ["./src/*"],
|
||||
},
|
||||
"resolveJsonModule": true,
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
{
|
||||
"files": [],
|
||||
"references": [
|
||||
{
|
||||
"path": "./tsconfig.node.json"
|
||||
},
|
||||
{
|
||||
"path": "./tsconfig.app.json"
|
||||
},
|
||||
{
|
||||
"path": "./tsconfig.vitest.json"
|
||||
}
|
||||
],
|
||||
"compilerOptions": {
|
||||
"module": "ES2022",
|
||||
"moduleResolution": "Node",
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
{
|
||||
"extends": "@tsconfig/node20/tsconfig.json",
|
||||
"include": [
|
||||
"vite.config.*",
|
||||
"vitest.config.*",
|
||||
"cypress.config.*",
|
||||
"nightwatch.conf.*",
|
||||
"playwright.config.*"
|
||||
],
|
||||
"compilerOptions": {
|
||||
"composite": true,
|
||||
"noEmit": true,
|
||||
"tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo",
|
||||
"module": "ESNext",
|
||||
"moduleResolution": "Bundler",
|
||||
"types": ["node"]
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"extends": "./tsconfig.app.json",
|
||||
"exclude": [],
|
||||
"compilerOptions": {
|
||||
"composite": true,
|
||||
"tsBuildInfoFile": "./node_modules/.tmp/tsconfig.vitest.tsbuildinfo",
|
||||
"lib": [],
|
||||
"types": ["node", "jsdom"]
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
import { fileURLToPath, URL } from 'node:url'
|
||||
|
||||
import { defineConfig } from 'vite'
|
||||
import vue from '@vitejs/plugin-vue'
|
||||
import VueDevTools from 'vite-plugin-vue-devtools'
|
||||
|
||||
// https://vitejs.dev/config/
|
||||
export default defineConfig({
|
||||
plugins: [
|
||||
vue(),
|
||||
VueDevTools(),
|
||||
],
|
||||
resolve: {
|
||||
alias: {
|
||||
'@': fileURLToPath(new URL('./src', import.meta.url))
|
||||
}
|
||||
},
|
||||
build:{
|
||||
outDir: '../resources/static',
|
||||
emptyOutDir: true,
|
||||
}
|
||||
});
|
||||
@@ -0,0 +1,14 @@
|
||||
import { fileURLToPath } from 'node:url'
|
||||
import { mergeConfig, defineConfig, configDefaults } from 'vitest/config'
|
||||
import viteConfig from './vite.config'
|
||||
|
||||
export default mergeConfig(
|
||||
viteConfig,
|
||||
defineConfig({
|
||||
test: {
|
||||
environment: 'jsdom',
|
||||
exclude: [...configDefaults.exclude, 'e2e/**'],
|
||||
root: fileURLToPath(new URL('./', import.meta.url))
|
||||
}
|
||||
})
|
||||
)
|
||||
Reference in new issue
Block a user