Browse Source

initial commit

master
mohammedThaqi 3 years ago
commit
02558aba7d
  1. 3
      .idea/.gitignore
  2. 18
      .idea/compiler.xml
  3. 6
      .idea/encodings.xml
  4. 20
      .idea/jarRepositories.xml
  5. 12
      .idea/misc.xml
  6. BIN
      .mvn/wrapper/maven-wrapper.jar
  7. 2
      .mvn/wrapper/maven-wrapper.properties
  8. 22
      HELP.md
  9. 308
      mvnw
  10. 205
      mvnw.cmd
  11. 54
      pom.xml
  12. 13
      src/main/java/com/election/lokshaba/LokshabaApplication.java
  13. 60
      src/main/java/com/election/lokshaba/component/UserSession.java
  14. 57
      src/main/java/com/election/lokshaba/component/UserSessionInterceptor.java
  15. 19
      src/main/java/com/election/lokshaba/configuration/WebConfig.java
  16. 33
      src/main/java/com/election/lokshaba/controller/MainController.java
  17. 47
      src/main/java/com/election/lokshaba/others/AppConfig.java
  18. 51
      src/main/resources/application.properties
  19. 65
      src/main/resources/static/assets/_js/main/app.js
  20. 1110
      src/main/resources/static/assets/_js/main/modules/helpers.js
  21. 802
      src/main/resources/static/assets/_js/main/modules/template.js
  22. 179
      src/main/resources/static/assets/_js/pages/be_comp_calendar.js
  23. 143
      src/main/resources/static/assets/_js/pages/be_comp_charts.js
  24. 156
      src/main/resources/static/assets/_js/pages/be_comp_chat.js
  25. 106
      src/main/resources/static/assets/_js/pages/be_comp_dialogs.js
  26. 88
      src/main/resources/static/assets/_js/pages/be_comp_image_cropper.js
  27. 154
      src/main/resources/static/assets/_js/pages/be_comp_maps_vector.js
  28. 47
      src/main/resources/static/assets/_js/pages/be_comp_nestable.js
  29. 41
      src/main/resources/static/assets/_js/pages/be_comp_onboarding.js
  30. 50
      src/main/resources/static/assets/_js/pages/be_comp_rating.js
  31. 124
      src/main/resources/static/assets/_js/pages/be_forms_validation.js
  32. 89
      src/main/resources/static/assets/_js/pages/be_pages_dashboard.js
  33. 225
      src/main/resources/static/assets/_js/pages/be_pages_dashboard_v1.js
  34. 104
      src/main/resources/static/assets/_js/pages/be_pages_ecom_dashboard.js
  35. 271
      src/main/resources/static/assets/_js/pages/be_pages_projects_tasks.js
  36. 45
      src/main/resources/static/assets/_js/pages/be_ui_animations.js
  37. 2184
      src/main/resources/static/assets/_js/pages/be_ui_icons.js
  38. 41
      src/main/resources/static/assets/_js/pages/be_ui_progress.js
  39. 73
      src/main/resources/static/assets/_js/pages/db_analytics.js
  40. 144
      src/main/resources/static/assets/_js/pages/db_corporate_slim.js
  41. 93
      src/main/resources/static/assets/_js/pages/db_crypto.js
  42. 42
      src/main/resources/static/assets/_js/pages/op_auth_lock.js
  43. 42
      src/main/resources/static/assets/_js/pages/op_auth_reminder.js
  44. 51
      src/main/resources/static/assets/_js/pages/op_auth_signin.js
  45. 69
      src/main/resources/static/assets/_js/pages/op_auth_signup.js
  46. 34
      src/main/resources/static/assets/_js/pages/op_coming_soon.js
  47. 78
      src/main/resources/static/assets/_js/pages/op_installation.js
  48. 149
      src/main/resources/static/assets/_scss/bootstrap/_accordion.scss
  49. 71
      src/main/resources/static/assets/_scss/bootstrap/_alert.scss
  50. 38
      src/main/resources/static/assets/_scss/bootstrap/_badge.scss
  51. 40
      src/main/resources/static/assets/_scss/bootstrap/_breadcrumb.scss
  52. 142
      src/main/resources/static/assets/_scss/bootstrap/_button-group.scss
  53. 207
      src/main/resources/static/assets/_scss/bootstrap/_buttons.scss
  54. 234
      src/main/resources/static/assets/_scss/bootstrap/_card.scss
  55. 226
      src/main/resources/static/assets/_scss/bootstrap/_carousel.scss
  56. 40
      src/main/resources/static/assets/_scss/bootstrap/_close.scss
  57. 41
      src/main/resources/static/assets/_scss/bootstrap/_containers.scss
  58. 249
      src/main/resources/static/assets/_scss/bootstrap/_dropdown.scss
  59. 9
      src/main/resources/static/assets/_scss/bootstrap/_forms.scss
  60. 302
      src/main/resources/static/assets/_scss/bootstrap/_functions.scss
  61. 33
      src/main/resources/static/assets/_scss/bootstrap/_grid.scss
  62. 10
      src/main/resources/static/assets/_scss/bootstrap/_helpers.scss
  63. 42
      src/main/resources/static/assets/_scss/bootstrap/_images.scss
  64. 192
      src/main/resources/static/assets/_scss/bootstrap/_list-group.scss
  65. 54
      src/main/resources/static/assets/_scss/bootstrap/_maps.scss
  66. 43
      src/main/resources/static/assets/_scss/bootstrap/_mixins.scss
  67. 237
      src/main/resources/static/assets/_scss/bootstrap/_modal.scss
  68. 172
      src/main/resources/static/assets/_scss/bootstrap/_nav.scss
  69. 278
      src/main/resources/static/assets/_scss/bootstrap/_navbar.scss
  70. 144
      src/main/resources/static/assets/_scss/bootstrap/_offcanvas.scss
  71. 109
      src/main/resources/static/assets/_scss/bootstrap/_pagination.scss
  72. 51
      src/main/resources/static/assets/_scss/bootstrap/_placeholders.scss
  73. 196
      src/main/resources/static/assets/_scss/bootstrap/_popover.scss
  74. 59
      src/main/resources/static/assets/_scss/bootstrap/_progress.scss
  75. 610
      src/main/resources/static/assets/_scss/bootstrap/_reboot.scss
  76. 73
      src/main/resources/static/assets/_scss/bootstrap/_root.scss
  77. 85
      src/main/resources/static/assets/_scss/bootstrap/_spinners.scss
  78. 164
      src/main/resources/static/assets/_scss/bootstrap/_tables.scss
  79. 73
      src/main/resources/static/assets/_scss/bootstrap/_toasts.scss
  80. 120
      src/main/resources/static/assets/_scss/bootstrap/_tooltip.scss
  81. 27
      src/main/resources/static/assets/_scss/bootstrap/_transitions.scss
  82. 106
      src/main/resources/static/assets/_scss/bootstrap/_type.scss
  83. 647
      src/main/resources/static/assets/_scss/bootstrap/_utilities.scss
  84. 1634
      src/main/resources/static/assets/_scss/bootstrap/_variables.scss
  85. 64
      src/main/resources/static/assets/_scss/bootstrap/bootstrap-grid.scss
  86. 9
      src/main/resources/static/assets/_scss/bootstrap/bootstrap-reboot.scss
  87. 18
      src/main/resources/static/assets/_scss/bootstrap/bootstrap-utilities.scss
  88. 51
      src/main/resources/static/assets/_scss/bootstrap/bootstrap.scss
  89. 75
      src/main/resources/static/assets/_scss/bootstrap/forms/_floating-labels.scss
  90. 175
      src/main/resources/static/assets/_scss/bootstrap/forms/_form-check.scss
  91. 194
      src/main/resources/static/assets/_scss/bootstrap/forms/_form-control.scss
  92. 91
      src/main/resources/static/assets/_scss/bootstrap/forms/_form-range.scss
  93. 71
      src/main/resources/static/assets/_scss/bootstrap/forms/_form-select.scss
  94. 11
      src/main/resources/static/assets/_scss/bootstrap/forms/_form-text.scss
  95. 132
      src/main/resources/static/assets/_scss/bootstrap/forms/_input-group.scss
  96. 36
      src/main/resources/static/assets/_scss/bootstrap/forms/_labels.scss
  97. 12
      src/main/resources/static/assets/_scss/bootstrap/forms/_validation.scss
  98. 3
      src/main/resources/static/assets/_scss/bootstrap/helpers/_clearfix.scss
  99. 10
      src/main/resources/static/assets/_scss/bootstrap/helpers/_color-bg.scss
  100. 12
      src/main/resources/static/assets/_scss/bootstrap/helpers/_colored-links.scss

3
.idea/.gitignore

@ -0,0 +1,3 @@
# Default ignored files
/shelf/
/workspace.xml

18
.idea/compiler.xml

@ -0,0 +1,18 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="CompilerConfiguration">
<annotationProcessing>
<profile name="Maven default annotation processors profile" enabled="true">
<sourceOutputDir name="target/generated-sources/annotations" />
<sourceTestOutputDir name="target/generated-test-sources/test-annotations" />
<outputRelativeToContentRoot value="true" />
<module name="lokshaba" />
</profile>
</annotationProcessing>
</component>
<component name="JavacSettings">
<option name="ADDITIONAL_OPTIONS_OVERRIDE">
<module name="lokshaba" options="-parameters" />
</option>
</component>
</project>

6
.idea/encodings.xml

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="Encoding">
<file url="file://$PROJECT_DIR$/src/main/java" charset="UTF-8" />
</component>
</project>

20
.idea/jarRepositories.xml

@ -0,0 +1,20 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="RemoteRepositoriesConfiguration">
<remote-repository>
<option name="id" value="central" />
<option name="name" value="Central Repository" />
<option name="url" value="https://repo.maven.apache.org/maven2" />
</remote-repository>
<remote-repository>
<option name="id" value="central" />
<option name="name" value="Maven Central repository" />
<option name="url" value="https://repo1.maven.org/maven2" />
</remote-repository>
<remote-repository>
<option name="id" value="jboss.community" />
<option name="name" value="JBoss Community repository" />
<option name="url" value="https://repository.jboss.org/nexus/content/repositories/public/" />
</remote-repository>
</component>
</project>

12
.idea/misc.xml

@ -0,0 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ExternalStorageConfigurationManager" enabled="true" />
<component name="MavenProjectsManager">
<option name="originalFiles">
<list>
<option value="$PROJECT_DIR$/pom.xml" />
</list>
</option>
</component>
<component name="ProjectRootManager" version="2" languageLevel="JDK_20" project-jdk-name="JavaSE-17" project-jdk-type="JavaSDK" />
</project>

BIN
.mvn/wrapper/maven-wrapper.jar

2
.mvn/wrapper/maven-wrapper.properties

@ -0,0 +1,2 @@
distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.5/apache-maven-3.9.5-bin.zip
wrapperUrl=https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar

22
HELP.md

@ -0,0 +1,22 @@
# Getting Started
### Reference Documentation
For further reference, please consider the following sections:
* [Official Apache Maven documentation](https://maven.apache.org/guides/index.html)
* [Spring Boot Maven Plugin Reference Guide](https://docs.spring.io/spring-boot/docs/3.2.3/maven-plugin/reference/html/)
* [Create an OCI image](https://docs.spring.io/spring-boot/docs/3.2.3/maven-plugin/reference/html/#build-image)
* [Spring Web](https://docs.spring.io/spring-boot/docs/3.2.3/reference/htmlsingle/index.html#web)
* [Thymeleaf](https://docs.spring.io/spring-boot/docs/3.2.3/reference/htmlsingle/index.html#web.servlet.spring-mvc.template-engines)
* [Spring Data JPA](https://docs.spring.io/spring-boot/docs/3.2.3/reference/htmlsingle/index.html#data.sql.jpa-and-spring-data)
### Guides
The following guides illustrate how to use some features concretely:
* [Building a RESTful Web Service](https://spring.io/guides/gs/rest-service/)
* [Serving Web Content with Spring MVC](https://spring.io/guides/gs/serving-web-content/)
* [Building REST services with Spring](https://spring.io/guides/tutorials/rest/)
* [Handling Form Submission](https://spring.io/guides/gs/handling-form-submission/)
* [Accessing data with MySQL](https://spring.io/guides/gs/accessing-data-mysql/)
* [Accessing Data with JPA](https://spring.io/guides/gs/accessing-data-jpa/)

308
mvnw

@ -0,0 +1,308 @@
#!/bin/sh
# ----------------------------------------------------------------------------
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# 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.
# ----------------------------------------------------------------------------
# ----------------------------------------------------------------------------
# Apache Maven Wrapper startup batch script, version 3.2.0
#
# Required ENV vars:
# ------------------
# JAVA_HOME - location of a JDK home dir
#
# Optional ENV vars
# -----------------
# MAVEN_OPTS - parameters passed to the Java VM when running Maven
# e.g. to debug Maven itself, use
# set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
# MAVEN_SKIP_RC - flag to disable loading of mavenrc files
# ----------------------------------------------------------------------------
if [ -z "$MAVEN_SKIP_RC" ] ; then
if [ -f /usr/local/etc/mavenrc ] ; then
. /usr/local/etc/mavenrc
fi
if [ -f /etc/mavenrc ] ; then
. /etc/mavenrc
fi
if [ -f "$HOME/.mavenrc" ] ; then
. "$HOME/.mavenrc"
fi
fi
# OS specific support. $var _must_ be set to either true or false.
cygwin=false;
darwin=false;
mingw=false
case "$(uname)" in
CYGWIN*) cygwin=true ;;
MINGW*) mingw=true;;
Darwin*) darwin=true
# Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home
# See https://developer.apple.com/library/mac/qa/qa1170/_index.html
if [ -z "$JAVA_HOME" ]; then
if [ -x "/usr/libexec/java_home" ]; then
JAVA_HOME="$(/usr/libexec/java_home)"; export JAVA_HOME
else
JAVA_HOME="/Library/Java/Home"; export JAVA_HOME
fi
fi
;;
esac
if [ -z "$JAVA_HOME" ] ; then
if [ -r /etc/gentoo-release ] ; then
JAVA_HOME=$(java-config --jre-home)
fi
fi
# For Cygwin, ensure paths are in UNIX format before anything is touched
if $cygwin ; then
[ -n "$JAVA_HOME" ] &&
JAVA_HOME=$(cygpath --unix "$JAVA_HOME")
[ -n "$CLASSPATH" ] &&
CLASSPATH=$(cygpath --path --unix "$CLASSPATH")
fi
# For Mingw, ensure paths are in UNIX format before anything is touched
if $mingw ; then
[ -n "$JAVA_HOME" ] && [ -d "$JAVA_HOME" ] &&
JAVA_HOME="$(cd "$JAVA_HOME" || (echo "cannot cd into $JAVA_HOME."; exit 1); pwd)"
fi
if [ -z "$JAVA_HOME" ]; then
javaExecutable="$(which javac)"
if [ -n "$javaExecutable" ] && ! [ "$(expr "\"$javaExecutable\"" : '\([^ ]*\)')" = "no" ]; then
# readlink(1) is not available as standard on Solaris 10.
readLink=$(which readlink)
if [ ! "$(expr "$readLink" : '\([^ ]*\)')" = "no" ]; then
if $darwin ; then
javaHome="$(dirname "\"$javaExecutable\"")"
javaExecutable="$(cd "\"$javaHome\"" && pwd -P)/javac"
else
javaExecutable="$(readlink -f "\"$javaExecutable\"")"
fi
javaHome="$(dirname "\"$javaExecutable\"")"
javaHome=$(expr "$javaHome" : '\(.*\)/bin')
JAVA_HOME="$javaHome"
export JAVA_HOME
fi
fi
fi
if [ -z "$JAVACMD" ] ; then
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
else
JAVACMD="$(\unset -f command 2>/dev/null; \command -v java)"
fi
fi
if [ ! -x "$JAVACMD" ] ; then
echo "Error: JAVA_HOME is not defined correctly." >&2
echo " We cannot execute $JAVACMD" >&2
exit 1
fi
if [ -z "$JAVA_HOME" ] ; then
echo "Warning: JAVA_HOME environment variable is not set."
fi
# traverses directory structure from process work directory to filesystem root
# first directory with .mvn subdirectory is considered project base directory
find_maven_basedir() {
if [ -z "$1" ]
then
echo "Path not specified to find_maven_basedir"
return 1
fi
basedir="$1"
wdir="$1"
while [ "$wdir" != '/' ] ; do
if [ -d "$wdir"/.mvn ] ; then
basedir=$wdir
break
fi
# workaround for JBEAP-8937 (on Solaris 10/Sparc)
if [ -d "${wdir}" ]; then
wdir=$(cd "$wdir/.." || exit 1; pwd)
fi
# end of workaround
done
printf '%s' "$(cd "$basedir" || exit 1; pwd)"
}
# concatenates all lines of a file
concat_lines() {
if [ -f "$1" ]; then
# Remove \r in case we run on Windows within Git Bash
# and check out the repository with auto CRLF management
# enabled. Otherwise, we may read lines that are delimited with
# \r\n and produce $'-Xarg\r' rather than -Xarg due to word
# splitting rules.
tr -s '\r\n' ' ' < "$1"
fi
}
log() {
if [ "$MVNW_VERBOSE" = true ]; then
printf '%s\n' "$1"
fi
}
BASE_DIR=$(find_maven_basedir "$(dirname "$0")")
if [ -z "$BASE_DIR" ]; then
exit 1;
fi
MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"}; export MAVEN_PROJECTBASEDIR
log "$MAVEN_PROJECTBASEDIR"
##########################################################################################
# Extension to allow automatically downloading the maven-wrapper.jar from Maven-central
# This allows using the maven wrapper in projects that prohibit checking in binary data.
##########################################################################################
wrapperJarPath="$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar"
if [ -r "$wrapperJarPath" ]; then
log "Found $wrapperJarPath"
else
log "Couldn't find $wrapperJarPath, downloading it ..."
if [ -n "$MVNW_REPOURL" ]; then
wrapperUrl="$MVNW_REPOURL/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar"
else
wrapperUrl="https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar"
fi
while IFS="=" read -r key value; do
# Remove '\r' from value to allow usage on windows as IFS does not consider '\r' as a separator ( considers space, tab, new line ('\n'), and custom '=' )
safeValue=$(echo "$value" | tr -d '\r')
case "$key" in (wrapperUrl) wrapperUrl="$safeValue"; break ;;
esac
done < "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.properties"
log "Downloading from: $wrapperUrl"
if $cygwin; then
wrapperJarPath=$(cygpath --path --windows "$wrapperJarPath")
fi
if command -v wget > /dev/null; then
log "Found wget ... using wget"
[ "$MVNW_VERBOSE" = true ] && QUIET="" || QUIET="--quiet"
if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then
wget $QUIET "$wrapperUrl" -O "$wrapperJarPath" || rm -f "$wrapperJarPath"
else
wget $QUIET --http-user="$MVNW_USERNAME" --http-password="$MVNW_PASSWORD" "$wrapperUrl" -O "$wrapperJarPath" || rm -f "$wrapperJarPath"
fi
elif command -v curl > /dev/null; then
log "Found curl ... using curl"
[ "$MVNW_VERBOSE" = true ] && QUIET="" || QUIET="--silent"
if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then
curl $QUIET -o "$wrapperJarPath" "$wrapperUrl" -f -L || rm -f "$wrapperJarPath"
else
curl $QUIET --user "$MVNW_USERNAME:$MVNW_PASSWORD" -o "$wrapperJarPath" "$wrapperUrl" -f -L || rm -f "$wrapperJarPath"
fi
else
log "Falling back to using Java to download"
javaSource="$MAVEN_PROJECTBASEDIR/.mvn/wrapper/MavenWrapperDownloader.java"
javaClass="$MAVEN_PROJECTBASEDIR/.mvn/wrapper/MavenWrapperDownloader.class"
# For Cygwin, switch paths to Windows format before running javac
if $cygwin; then
javaSource=$(cygpath --path --windows "$javaSource")
javaClass=$(cygpath --path --windows "$javaClass")
fi
if [ -e "$javaSource" ]; then
if [ ! -e "$javaClass" ]; then
log " - Compiling MavenWrapperDownloader.java ..."
("$JAVA_HOME/bin/javac" "$javaSource")
fi
if [ -e "$javaClass" ]; then
log " - Running MavenWrapperDownloader.java ..."
("$JAVA_HOME/bin/java" -cp .mvn/wrapper MavenWrapperDownloader "$wrapperUrl" "$wrapperJarPath") || rm -f "$wrapperJarPath"
fi
fi
fi
fi
##########################################################################################
# End of extension
##########################################################################################
# If specified, validate the SHA-256 sum of the Maven wrapper jar file
wrapperSha256Sum=""
while IFS="=" read -r key value; do
case "$key" in (wrapperSha256Sum) wrapperSha256Sum=$value; break ;;
esac
done < "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.properties"
if [ -n "$wrapperSha256Sum" ]; then
wrapperSha256Result=false
if command -v sha256sum > /dev/null; then
if echo "$wrapperSha256Sum $wrapperJarPath" | sha256sum -c > /dev/null 2>&1; then
wrapperSha256Result=true
fi
elif command -v shasum > /dev/null; then
if echo "$wrapperSha256Sum $wrapperJarPath" | shasum -a 256 -c > /dev/null 2>&1; then
wrapperSha256Result=true
fi
else
echo "Checksum validation was requested but neither 'sha256sum' or 'shasum' are available."
echo "Please install either command, or disable validation by removing 'wrapperSha256Sum' from your maven-wrapper.properties."
exit 1
fi
if [ $wrapperSha256Result = false ]; then
echo "Error: Failed to validate Maven wrapper SHA-256, your Maven wrapper might be compromised." >&2
echo "Investigate or delete $wrapperJarPath to attempt a clean download." >&2
echo "If you updated your Maven version, you need to update the specified wrapperSha256Sum property." >&2
exit 1
fi
fi
MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS"
# For Cygwin, switch paths to Windows format before running java
if $cygwin; then
[ -n "$JAVA_HOME" ] &&
JAVA_HOME=$(cygpath --path --windows "$JAVA_HOME")
[ -n "$CLASSPATH" ] &&
CLASSPATH=$(cygpath --path --windows "$CLASSPATH")
[ -n "$MAVEN_PROJECTBASEDIR" ] &&
MAVEN_PROJECTBASEDIR=$(cygpath --path --windows "$MAVEN_PROJECTBASEDIR")
fi
# Provide a "standardized" way to retrieve the CLI args that will
# work with both Windows and non-Windows executions.
MAVEN_CMD_LINE_ARGS="$MAVEN_CONFIG $*"
export MAVEN_CMD_LINE_ARGS
WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
# shellcheck disable=SC2086 # safe args
exec "$JAVACMD" \
$MAVEN_OPTS \
$MAVEN_DEBUG_OPTS \
-classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \
"-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \
${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@"

205
mvnw.cmd

@ -0,0 +1,205 @@
@REM ----------------------------------------------------------------------------
@REM Licensed to the Apache Software Foundation (ASF) under one
@REM or more contributor license agreements. See the NOTICE file
@REM distributed with this work for additional information
@REM regarding copyright ownership. The ASF licenses this file
@REM to you under the Apache License, Version 2.0 (the
@REM "License"); you may not use this file except in compliance
@REM with the License. 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,
@REM software distributed under the License is distributed on an
@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
@REM KIND, either express or implied. See the License for the
@REM specific language governing permissions and limitations
@REM under the License.
@REM ----------------------------------------------------------------------------
@REM ----------------------------------------------------------------------------
@REM Apache Maven Wrapper startup batch script, version 3.2.0
@REM
@REM Required ENV vars:
@REM JAVA_HOME - location of a JDK home dir
@REM
@REM Optional ENV vars
@REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands
@REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a keystroke before ending
@REM MAVEN_OPTS - parameters passed to the Java VM when running Maven
@REM e.g. to debug Maven itself, use
@REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
@REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files
@REM ----------------------------------------------------------------------------
@REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on'
@echo off
@REM set title of command window
title %0
@REM enable echoing by setting MAVEN_BATCH_ECHO to 'on'
@if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO%
@REM set %HOME% to equivalent of $HOME
if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%")
@REM Execute a user defined script before this one
if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre
@REM check for pre script, once with legacy .bat ending and once with .cmd ending
if exist "%USERPROFILE%\mavenrc_pre.bat" call "%USERPROFILE%\mavenrc_pre.bat" %*
if exist "%USERPROFILE%\mavenrc_pre.cmd" call "%USERPROFILE%\mavenrc_pre.cmd" %*
:skipRcPre
@setlocal
set ERROR_CODE=0
@REM To isolate internal variables from possible post scripts, we use another setlocal
@setlocal
@REM ==== START VALIDATION ====
if not "%JAVA_HOME%" == "" goto OkJHome
echo.
echo Error: JAVA_HOME not found in your environment. >&2
echo Please set the JAVA_HOME variable in your environment to match the >&2
echo location of your Java installation. >&2
echo.
goto error
:OkJHome
if exist "%JAVA_HOME%\bin\java.exe" goto init
echo.
echo Error: JAVA_HOME is set to an invalid directory. >&2
echo JAVA_HOME = "%JAVA_HOME%" >&2
echo Please set the JAVA_HOME variable in your environment to match the >&2
echo location of your Java installation. >&2
echo.
goto error
@REM ==== END VALIDATION ====
:init
@REM Find the project base dir, i.e. the directory that contains the folder ".mvn".
@REM Fallback to current working directory if not found.
set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR%
IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir
set EXEC_DIR=%CD%
set WDIR=%EXEC_DIR%
:findBaseDir
IF EXIST "%WDIR%"\.mvn goto baseDirFound
cd ..
IF "%WDIR%"=="%CD%" goto baseDirNotFound
set WDIR=%CD%
goto findBaseDir
:baseDirFound
set MAVEN_PROJECTBASEDIR=%WDIR%
cd "%EXEC_DIR%"
goto endDetectBaseDir
:baseDirNotFound
set MAVEN_PROJECTBASEDIR=%EXEC_DIR%
cd "%EXEC_DIR%"
:endDetectBaseDir
IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig
@setlocal EnableExtensions EnableDelayedExpansion
for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a
@endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS%
:endReadAdditionalConfig
SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe"
set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar"
set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
set WRAPPER_URL="https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar"
FOR /F "usebackq tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO (
IF "%%A"=="wrapperUrl" SET WRAPPER_URL=%%B
)
@REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central
@REM This allows using the maven wrapper in projects that prohibit checking in binary data.
if exist %WRAPPER_JAR% (
if "%MVNW_VERBOSE%" == "true" (
echo Found %WRAPPER_JAR%
)
) else (
if not "%MVNW_REPOURL%" == "" (
SET WRAPPER_URL="%MVNW_REPOURL%/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar"
)
if "%MVNW_VERBOSE%" == "true" (
echo Couldn't find %WRAPPER_JAR%, downloading it ...
echo Downloading from: %WRAPPER_URL%
)
powershell -Command "&{"^
"$webclient = new-object System.Net.WebClient;"^
"if (-not ([string]::IsNullOrEmpty('%MVNW_USERNAME%') -and [string]::IsNullOrEmpty('%MVNW_PASSWORD%'))) {"^
"$webclient.Credentials = new-object System.Net.NetworkCredential('%MVNW_USERNAME%', '%MVNW_PASSWORD%');"^
"}"^
"[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; $webclient.DownloadFile('%WRAPPER_URL%', '%WRAPPER_JAR%')"^
"}"
if "%MVNW_VERBOSE%" == "true" (
echo Finished downloading %WRAPPER_JAR%
)
)
@REM End of extension
@REM If specified, validate the SHA-256 sum of the Maven wrapper jar file
SET WRAPPER_SHA_256_SUM=""
FOR /F "usebackq tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO (
IF "%%A"=="wrapperSha256Sum" SET WRAPPER_SHA_256_SUM=%%B
)
IF NOT %WRAPPER_SHA_256_SUM%=="" (
powershell -Command "&{"^
"$hash = (Get-FileHash \"%WRAPPER_JAR%\" -Algorithm SHA256).Hash.ToLower();"^
"If('%WRAPPER_SHA_256_SUM%' -ne $hash){"^
" Write-Output 'Error: Failed to validate Maven wrapper SHA-256, your Maven wrapper might be compromised.';"^
" Write-Output 'Investigate or delete %WRAPPER_JAR% to attempt a clean download.';"^
" Write-Output 'If you updated your Maven version, you need to update the specified wrapperSha256Sum property.';"^
" exit 1;"^
"}"^
"}"
if ERRORLEVEL 1 goto error
)
@REM Provide a "standardized" way to retrieve the CLI args that will
@REM work with both Windows and non-Windows executions.
set MAVEN_CMD_LINE_ARGS=%*
%MAVEN_JAVA_EXE% ^
%JVM_CONFIG_MAVEN_PROPS% ^
%MAVEN_OPTS% ^
%MAVEN_DEBUG_OPTS% ^
-classpath %WRAPPER_JAR% ^
"-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" ^
%WRAPPER_LAUNCHER% %MAVEN_CONFIG% %*
if ERRORLEVEL 1 goto error
goto end
:error
set ERROR_CODE=1
:end
@endlocal & set ERROR_CODE=%ERROR_CODE%
if not "%MAVEN_SKIP_RC%"=="" goto skipRcPost
@REM check for post script, once with legacy .bat ending and once with .cmd ending
if exist "%USERPROFILE%\mavenrc_post.bat" call "%USERPROFILE%\mavenrc_post.bat"
if exist "%USERPROFILE%\mavenrc_post.cmd" call "%USERPROFILE%\mavenrc_post.cmd"
:skipRcPost
@REM pause the script if MAVEN_BATCH_PAUSE is set to 'on'
if "%MAVEN_BATCH_PAUSE%"=="on" pause
if "%MAVEN_TERMINATE_CMD%"=="on" exit %ERROR_CODE%
cmd /C exit /B %ERROR_CODE%

54
pom.xml

@ -0,0 +1,54 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.2.3</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.election</groupId>
<artifactId>lokshaba</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>lokshaba</name>
<description>The Application Developed by GCC</description>
<properties>
<java.version>17</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>com.mysql</groupId>
<artifactId>mysql-connector-j</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>

13
src/main/java/com/election/lokshaba/LokshabaApplication.java

@ -0,0 +1,13 @@
package com.election.lokshaba;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class LokshabaApplication {
public static void main(String[] args) {
SpringApplication.run(LokshabaApplication.class, args);
}
}

60
src/main/java/com/election/lokshaba/component/UserSession.java

@ -0,0 +1,60 @@
package com.election.lokshaba.component;
import org.springframework.context.annotation.Scope;
import org.springframework.context.annotation.ScopedProxyMode;
import org.springframework.stereotype.Component;
import org.springframework.web.context.WebApplicationContext;
@Component
@Scope(value = WebApplicationContext.SCOPE_SESSION, proxyMode = ScopedProxyMode.TARGET_CLASS)
public class UserSession {
private Integer userId;
private long mobNo;
private String userType;
private String dispayName;
private String zone;
public Integer getUserId() {
return userId;
}
public void setUserId(Integer userId) {
this.userId = userId;
}
public String getUserType() {
return userType;
}
public void setUserType(String userType) {
this.userType = userType;
}
public String getDispayName() {
return dispayName;
}
public void setDispayName(String dispayName) {
this.dispayName = dispayName;
}
public long getMobNo() {
return mobNo;
}
public void setMobNo(long mobNo) {
this.mobNo = mobNo;
}
public String getZone() {
return zone;
}
public void setZone(String zone) {
this.zone = zone;
}
}

57
src/main/java/com/election/lokshaba/component/UserSessionInterceptor.java

@ -0,0 +1,57 @@
package com.election.lokshaba.component;
import com.election.lokshaba.others.AppConfig;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import java.util.Arrays;
import java.util.List;
@Component
public class UserSessionInterceptor implements HandlerInterceptor {
@Autowired
private UserSession userSession;
@Autowired
private AppConfig appConfig;
private static final List<String> EXCLUDED_URLS = Arrays.asList("/login", "/");
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
// Get the current request URL
String requestUrl = request.getRequestURI();
// Exclude static resources from the check
if (requestUrl.startsWith("/assets/") || requestUrl.startsWith("/css/") || requestUrl.startsWith("/js/") || requestUrl.startsWith("/images/") || requestUrl.startsWith("/api/")) {
return true; // Allow the request to proceed without checking the login status
}
// Exclude the login page from the check
// Exclude specific URLs from the check
if (EXCLUDED_URLS.contains(requestUrl)) {
return true; // Allow the request to proceed without checking the login status
}
// Check if the user is logged in
// If logged in, add the userSession to the model
// Return true to allow the request to proceed
//if (isLoggedIn()) {
if(userSession.getUserId() != null && userSession.getUserType() != null) {
request.setAttribute("userSession", userSession);
} else {
request.setAttribute("title", "Login");
request.setAttribute("baseURL", appConfig.getBaseUrl());
response.sendRedirect("/login");
return false; // Stop further processing of the request
}
return true; // Allow the request to proceed
}
private boolean isLoggedIn() {
// Implement your login check logic here
// For example, check if the userSession contains the necessary information
return userSession.getUserId() != null && userSession.getUserType() != null;
}
}

19
src/main/java/com/election/lokshaba/configuration/WebConfig.java

@ -0,0 +1,19 @@
package com.election.lokshaba.configuration;
import com.election.lokshaba.component.UserSessionInterceptor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Autowired
private UserSessionInterceptor userSessionInterceptor;
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(userSessionInterceptor);
}
}

33
src/main/java/com/election/lokshaba/controller/MainController.java

@ -0,0 +1,33 @@
package com.election.lokshaba.controller;
import com.election.lokshaba.others.AppConfig;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import java.util.ArrayList;
import java.util.List;
@Controller
public class MainController {
@Autowired
private AppConfig appConfig;
@GetMapping(value = {"/","/index",""})
public String getIndex(Model model){
model.addAttribute("title","Login");
//model.addAttribute("baseURL", appConfig.getBaseUrl());
return "index";
}
@GetMapping("/login")
public String viewList(Model model) {
model.addAttribute("title", "list");
model.addAttribute("baseURL", appConfig.getBaseUrl());
List list = new ArrayList<>();
model.addAttribute("petlist",list);
return "login";
}
}

47
src/main/java/com/election/lokshaba/others/AppConfig.java

@ -0,0 +1,47 @@
package com.election.lokshaba.others;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
@Component
@ConfigurationProperties(prefix = "app")
public class AppConfig {
private String title;
private String baseUrl;
private String getOtpUrl;
private String erpUrl;
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getBaseUrl() {
return baseUrl;
}
public void setBaseUrl(String baseUrl) {
this.baseUrl = baseUrl;
}
public String getGetOtpUrl() {
return getOtpUrl;
}
public void setGetOtpUrl(String getOtpUrl) {
this.getOtpUrl = getOtpUrl;
}
public String getErpUrl() {
return erpUrl;
}
public void setErpUrl(String erpUrl) {
this.erpUrl = erpUrl;
}
}

51
src/main/resources/application.properties

@ -0,0 +1,51 @@
spring.application.name=lokshaba
# Database connection properties
spring.datasource.url=jdbc:mysql://localhost:3306/lokShabaElection
spring.datasource.username=root
#spring.datasource.password=gccroot
spring.datasource.password=root
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
server.port=8065
#server.port=8061
app.baseUrl=http://localhost:8065
#app.baseUrl=http://117.232.67.158:8065
#app.baseUrl=http://gccservices.chennaicorporation.gov.in:8061
app.erpUrl=https://erp.chennaicorporation.gov.in/pgr/external/mobileservice?
app.title=GREATER CHENNAI CORPORATION - Pet Registration
app.ptaxid=null
app.ptaxRegMobile=null
app.pusertype=nulls
#// Session Config
# Connection pool properties
spring.datasource.hikari.maximum-pool-size=5
spring.datasource.hikari.minimum-idle=2
spring.datasource.hikari.idle-timeout=30000
spring.datasource.hikari.connection-timeout=5000
# JPA properties
spring.jpa.hibernate.ddl-auto=update
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQLDialect
spring.jpa.properties.hibernate.jdbc.batch_size=50
spring.jpa.properties.hibernate.jdbc.fetch_size=1000
spring.jpa.properties.hibernate.jdbc.batch_versioned_data=true
spring.jpa.properties.hibernate.jdbc.batch_orders_inserts=true
logging.level.org.hibernate.SQL=debug
logging.level.org.hibernate.orm.jdbc.bind=trace
logging.level.org.hibernate.type.descriptor.sql=trace
server.error.include-stacktrace= on_param
#Auto Resert On file changes
spring.devtools.restart.enabled=true
app.getOtpUrl=https://api.onex-aura.com/api/sms?

65
src/main/resources/static/assets/_js/main/app.js

@ -0,0 +1,65 @@
/*
* Document : app.js
* Author : pixelcave
* Description: Main entry point
*
*/
// Import required modules
import Template from './modules/template';
// App extends Template
export default class App extends Template {
/*
* Auto called when creating a new instance
*
*/
constructor() {
super();
}
/*
* Here you can override or extend any function you want from Template class
* if you would like to change/extend/remove the default functionality.
*
* This way it will be easier for you to update the module files if a new update
* is released since all your changes will be in here overriding the original ones.
*
* Let's have a look at the _uiInit() function, the one that runs the first time
* we create an instance of Template class or App class which extends it. This function
* inits all vital functionality but you can change it to fit your own needs.
*
*/
/*
* EXAMPLE #1 - Removing default functionality by making it empty
*
*/
// _uiInit() {}
/*
* EXAMPLE #2 - Extending default functionality with additional code
*
*/
// _uiInit() {
// // Call original function
// super._uiInit();
//
// // Your extra JS code afterwards
// }
/*
* EXAMPLE #3 - Replacing default functionality by writing your own code
*
*/
// _uiInit() {
// // Your own JS code without ever calling the original function's code
// }
}
// Create a new instance of App
window.Dashmix = new App();

1110
src/main/resources/static/assets/_js/main/modules/helpers.js
File diff suppressed because it is too large
View File

802
src/main/resources/static/assets/_js/main/modules/template.js

@ -0,0 +1,802 @@
/*
* Document : template.js
* Author : pixelcave
* Description: UI Framework custom functionality
*
*/
// Imports
import * as bootstrap from 'bootstrap';
import SimpleBar from 'simplebar';
import Helpers from './helpers';
// Assignments
window.bootstrap = bootstrap;
window.SimpleBar = SimpleBar;
// Template
export default class Template {
/*
* Auto called when creating a new instance
*
*/
constructor() {
this.onLoad(() => this._uiInit());
}
/*
* Init all vital functionality
*
*/
_uiInit() {
// Layout variables
this._lHtml = document.documentElement;
this._lBody = document.body;
this._lpageLoader = document.getElementById('page-loader');
this._lPage = document.getElementById('page-container');
this._lSidebar = document.getElementById('sidebar');
this._lSidebarScrollCon = this._lSidebar && this._lSidebar.querySelector('.js-sidebar-scroll');
this._lSideOverlay = document.getElementById('side-overlay');
this._lResize = false;
this._lHeader = document.getElementById('page-header');
this._lHeaderSearch = document.getElementById('page-header-search');
this._lHeaderSearchInput = document.getElementById('page-header-search-input');
this._lHeaderLoader = document.getElementById('page-header-loader');
this._lMain = document.getElementById('main-container');
this._lFooter = document.getElementById('page-footer');
// Helper variables
this._lSidebarScroll = false;
this._lSideOverlayScroll = false;
// Base UI Init
this._uiHandleTheme();
this._uiHandleDarkMode();
this._uiHandleSidebars();
this._uiHandleHeader();
this._uiHandleNav();
// API Init
this._uiApiLayout();
this._uiApiBlocks();
// Init the following helpers by default
this.helpers([
'bs-tooltip',
'bs-popover',
'dm-toggle-class',
'dm-year-copy',
'dm-ripple',
]);
// Page Loader (hide it)
this._uiHandlePageLoader();
}
/*
* Handles sidebar and side overlay scrolling functionality/styles
*
*/
_uiHandleSidebars(mode = 'init') {
let self = this;
if (self._lSidebar || self._lSideOverlay) {
if (mode === 'init') {
// Add 'side-trans-enabled' class to #page-container (enables sidebar and side overlay transition on open/close)
// Fixes IE10, IE11 and Edge bug in which animation was executed on each page load
self._lPage.classList.add('side-trans-enabled');
// Remove side transitions on window resizing
window.addEventListener('resize', () => {
clearTimeout(self._lResize);
self._lPage.classList.remove('side-trans-enabled');
self._lResize = setTimeout(() => { self._lPage.classList.add('side-trans-enabled'); }, 500);
});
// Init custom scrolling
this._uiHandleSidebars('custom-scroll');
} else if (mode = 'custom-scroll') {
// If .side-scroll is added to #page-container, enable custom scrolling
if (self._lPage.classList.contains('side-scroll')) {
// Init custom scrolling on Sidebar
if ((self._lSidebar) && !self._lSidebarScroll) {
self._lSidebarScroll = new SimpleBar(self._lSidebarScrollCon);
}
// Init custom scrolling on Side Overlay
if ((self._lSideOverlay) && !self._lSideOverlayScroll) {
self._lSideOverlayScroll = new SimpleBar(self._lSideOverlay);
}
}
}
}
}
/*
* Handles header related classes
*
*/
_uiHandleHeader() {
let self = this;
// If the header is fixed and has the glass style, add the related class on scrolling to add a background color to the header
if (self._lPage.classList.contains('page-header-glass') && self._lPage.classList.contains('page-header-fixed')) {
window.addEventListener('scroll', e => {
if (window.scrollY > 60) {
self._lPage.classList.add('page-header-scroll');
} else {
self._lPage.classList.remove('page-header-scroll');
}
});
window.dispatchEvent(new CustomEvent('scroll'));
}
}
/*
* Toggle Submenu functionality
*
*/
_uiHandleNav() {
let links = document.querySelectorAll('[data-toggle="submenu"]');
// When a submenu link is clicked
if (links) {
links.forEach(link => {
link.addEventListener('click', e => {
e.preventDefault();
// Get main navigation
let mainNav = link.closest('.nav-main');
// Check if we are in horizontal navigation, large screen and hover is enabled
if (
!(
(window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth) > 991
&& mainNav.classList.contains('nav-main-horizontal')
&& mainNav.classList.contains('nav-main-hover')
)
) {
// Get link's parent
let parentLi = link.closest('li');
if (parentLi.classList.contains('open')) {
// If submenu is open, close it..
parentLi.classList.remove('open');
link.setAttribute('aria-expanded', 'false');
} else {
// .. else if submenu is closed, close all other (same level) submenus first before open it
Array.from(link.closest('ul').children).forEach(el => {
el.classList.remove('open');
});
parentLi.classList.add('open');
link.setAttribute('aria-expanded', 'true');
}
}
return false;
});
});
}
}
/*
* Page loading screen functionality
*
*/
_uiHandlePageLoader(mode = 'hide', colorClass) {
if (mode === 'show') {
if (this._lpageLoader) {
if (colorClass) {
this._lpageLoader.className = '';
this._lpageLoader.classList.add(colorClass);
}
this._lpageLoader.classList.add('show');
} else {
let pageLoader = document.createElement('div');
pageLoader.id = 'page-loader';
if (colorClass) {
pageLoader.classList.add(colorClass);
}
pageLoader.classList.add('show');
this._lPage.insertBefore(pageLoader, this._lPage.firstChild);
this._lpageLoader = document.getElementById('page-loader');
}
} else if (mode === 'hide') {
if (this._lpageLoader) {
this._lpageLoader.classList.remove('show');
}
}
}
/*
* Saves/Retrieves Dark Mode preference to local storage
*
*/
_uiHandleDarkMode(mode = 'init') {
let self = this;
// If dark mode is not enabled by default remember default sidebar
// and header style to return to after any possible dark mode disabling
if (mode === 'init' && !self._lPage.classList.contains('dark-mode')) {
if (self._lPage.classList.contains('sidebar-dark')) {
localStorage.setItem('dashmixDefaultsSidebarDark', true);
} else {
localStorage.removeItem('dashmixDefaultsSidebarDark');
}
if (self._lPage.classList.contains('page-header-dark')) {
localStorage.setItem('dashmixDefaultsPageHeaderDark', true);
} else {
localStorage.removeItem('dashmixDefaultsPageHeaderDark');
}
}
// If remember-theme class is added in #page-container
if (self._lPage.classList.contains('remember-theme')) {
let darkMode = localStorage.getItem('dashmixDarkMode') || false;
if (mode === 'init') {
if (darkMode) {
self._lPage.classList.add('sidebar-dark');
self._lPage.classList.add('page-header-dark');
self._lPage.classList.add('dark-mode');
} else if (mode === 'init') {
self._lPage.classList.remove('dark-mode');
}
} else if (mode === 'on') {
localStorage.setItem('dashmixDarkMode', true);
} else if (mode === 'off') {
localStorage.removeItem('dashmixDarkMode');
}
} else if (mode === 'init') {
localStorage.removeItem('dashmixDarkMode');
}
}
/*
* Set active color theme functionality
*
*/
_uiHandleTheme() {
let self = this;
let themeEl = document.getElementById('css-theme');
let rememberTheme = this._lPage.classList.contains('remember-theme') ? true : false;
// If remember theme is enabled
if (rememberTheme) {
let themeName = localStorage.getItem('dashmixThemeName') || false;
// Update color theme
if (themeName) {
self._uiUpdateTheme(themeEl, themeName);
}
// Update theme element
themeEl = document.getElementById('css-theme');
} else {
localStorage.removeItem('dashmixThemeName');
}
// Set the active color theme link as active
document.querySelectorAll('[data-toggle="theme"][data-theme="' + (themeEl ? themeEl.getAttribute('href') : 'default') + '"]').forEach(link => {
link.classList.add('active');
});
// When a color theme link is clicked
document.querySelectorAll('[data-toggle="theme"]').forEach(el => {
el.addEventListener('click', e => {
e.preventDefault();
// Get element's data
let themeName = el.dataset.theme;
// Set this color theme link as active
document.querySelectorAll('[data-toggle="theme"]').forEach(link => {
link.classList.remove('active');
});
document.querySelector('[data-toggle="theme"][data-theme="' + themeName + '"]').classList.add('active');
// Update color theme
self._uiUpdateTheme(themeEl, themeName);
// Update theme element
themeEl = document.getElementById('css-theme');
// If remember theme is enabled, save the new active color theme
if (rememberTheme) {
localStorage.setItem('dashmixThemeName', themeName);
}
});
});
}
/*
* Updates the color theme
*
*/
_uiUpdateTheme(themeEl, themeName) {
if (themeName === 'default') {
if (themeEl) {
themeEl.parentNode.removeChild(themeEl);
}
} else {
if (themeEl) {
themeEl.setAttribute('href', themeName);
} else {
let themeLink = document.createElement('link');
themeLink.id = 'css-theme';
themeLink.setAttribute('rel', 'stylesheet');
themeLink.setAttribute('href', themeName);
document.getElementById('css-main').insertAdjacentElement('afterend', themeLink);
}
}
}
/*
* Layout API
*
*/
_uiApiLayout(mode = 'init') {
let self = this;
// API with object literals
let layoutAPI = {
init: () => {
let buttons = document.querySelectorAll('[data-toggle="layout"]');
// Call layout API on button click
if (buttons) {
buttons.forEach(btn => {
btn.addEventListener('click', e => {
self._uiApiLayout(btn.dataset.action);
});
})
}
// Prepend Page Overlay div if enabled (used when Side Overlay opens)
if (self._lPage.classList.contains('enable-page-overlay')) {
let pageOverlay = document.createElement('div');
pageOverlay.id = 'page-overlay';
self._lPage.insertBefore(pageOverlay, self._lPage.firstChild);
document.getElementById('page-overlay').addEventListener('click', e => {
self._uiApiLayout('side_overlay_close');
});
}
},
sidebar_pos_toggle: () => {
self._lPage.classList.toggle('sidebar-r');
},
sidebar_pos_left: () => {
self._lPage.classList.remove('sidebar-r');
},
sidebar_pos_right: () => {
self._lPage.classList.add('sidebar-r');
},
sidebar_toggle: () => {
if (window.innerWidth > 991) {
self._lPage.classList.toggle('sidebar-o');
} else {
self._lPage.classList.toggle('sidebar-o-xs');
}
},
sidebar_open: () => {
if (window.innerWidth > 991) {
self._lPage.classList.add('sidebar-o');
} else {
self._lPage.classList.add('sidebar-o-xs');
}
},
sidebar_close: () => {
if (window.innerWidth > 991) {
self._lPage.classList.remove('sidebar-o');
} else {
self._lPage.classList.remove('sidebar-o-xs');
}
},
sidebar_mini_toggle: () => {
if (window.innerWidth > 991) {
self._lPage.classList.toggle('sidebar-mini');
}
},
sidebar_mini_on: () => {
if (window.innerWidth > 991) {
self._lPage.classList.add('sidebar-mini');
}
},
sidebar_mini_off: () => {
if (window.innerWidth > 991) {
self._lPage.classList.remove('sidebar-mini');
}
},
sidebar_style_toggle: () => {
if (self._lPage.classList.contains('sidebar-dark')) {
self._uiApiLayout('sidebar_style_light');
} else {
self._uiApiLayout('sidebar_style_dark');
}
},
sidebar_style_dark: () => {
self._lPage.classList.add('sidebar-dark');
localStorage.setItem('dashmixDefaultsSidebarDark', true);
},
sidebar_style_light: () => {
self._lPage.classList.remove('sidebar-dark');
self._lPage.classList.remove('dark-mode');
localStorage.removeItem('dashmixDefaultsSidebarDark');
},
side_overlay_toggle: () => {
if (self._lPage.classList.contains('side-overlay-o')) {
self._uiApiLayout('side_overlay_close');
} else {
self._uiApiLayout('side_overlay_open');
}
},
side_overlay_open: () => {
// When ESCAPE key is hit close the side overlay
document.addEventListener('keydown', e => {
if (e.key === 'Esc' || e.key === 'Escape') {
self._uiApiLayout('side_overlay_close');
}
});
self._lPage.classList.add('side-overlay-o');
},
side_overlay_close: () => {
self._lPage.classList.remove('side-overlay-o');
},
side_overlay_mode_hover_toggle: () => {
self._lPage.classList.toggle('side-overlay-hover');
},
side_overlay_mode_hover_on: () => {
self._lPage.classList.add('side-overlay-hover');
},
side_overlay_mode_hover_off: () => {
self._lPage.classList.remove('side-overlay-hover');
},
header_glass_toggle: () => {
self._lPage.classList.toggle('page-header-glass');
self._uiHandleHeader();
},
header_glass_on: () => {
self._lPage.classList.add('page-header-glass');
self._uiHandleHeader();
},
header_glass_off: () => {
self._lPage.classList.remove('page-header-glass');
self._uiHandleHeader();
},
header_mode_toggle: () => {
self._lPage.classList.toggle('page-header-fixed');
},
header_mode_static: () => {
self._lPage.classList.remove('page-header-fixed');
},
header_mode_fixed: () => {
self._lPage.classList.add('page-header-fixed');
},
header_style_toggle: () => {
if (self._lPage.classList.contains('page-header-dark')) {
self._uiApiLayout('header_style_light');
} else {
self._uiApiLayout('header_style_dark');
}
},
header_style_dark: () => {
self._lPage.classList.add('page-header-dark');
localStorage.setItem('dashmixDefaultsPageHeaderDark', true);
},
header_style_light: () => {
self._lPage.classList.remove('page-header-dark');
self._lPage.classList.remove('dark-mode');
localStorage.removeItem('dashmixDefaultsPageHeaderDark');
},
header_search_on: () => {
self._lHeaderSearch.classList.add('show');
self._lHeaderSearchInput.focus();
// When ESCAPE key is hit close the search section
document.addEventListener('keydown', e => {
if (e.key === 'Esc' || e.key === 'Escape') {
self._uiApiLayout('header_search_off');
}
});
},
header_search_off: () => {
self._lHeaderSearch.classList.remove('show');
self._lHeaderSearchInput.blur();
},
header_loader_on: () => {
self._lHeaderLoader.classList.add('show');
},
header_loader_off: () => {
self._lHeaderLoader.classList.remove('show');
},
dark_mode_toggle: () => {
if (self._lPage.classList.contains('dark-mode')) {
self._uiApiLayout('dark_mode_off');
} else {
self._uiApiLayout('dark_mode_on');
}
},
dark_mode_on: () => {
self._lPage.classList.add('sidebar-dark');
self._lPage.classList.add('page-header-dark');
self._lPage.classList.add('dark-mode');
this._uiHandleDarkMode('on');
},
dark_mode_off: () => {
if (!localStorage.getItem('dashmixDefaultsSidebarDark')) {
self._lPage.classList.remove('sidebar-dark');
}
if (!localStorage.getItem('dashmixDefaultsPageHeaderDark')) {
self._lPage.classList.remove('page-header-dark');
}
self._lPage.classList.remove('dark-mode');
this._uiHandleDarkMode('off');
},
content_layout_toggle: () => {
if (self._lPage.classList.contains('main-content-boxed')) {
self._uiApiLayout('content_layout_narrow');
} else if (self._lPage.classList.contains('main-content-narrow')) {
self._uiApiLayout('content_layout_full_width');
} else {
self._uiApiLayout('content_layout_boxed');
}
},
content_layout_boxed: () => {
self._lPage.classList.remove('main-content-narrow');
self._lPage.classList.add('main-content-boxed');
},
content_layout_narrow: () => {
self._lPage.classList.remove('main-content-boxed');
self._lPage.classList.add('main-content-narrow');
},
content_layout_full_width: () => {
self._lPage.classList.remove('main-content-boxed');
self._lPage.classList.remove('main-content-narrow');
}
};
// Call layout API
if (layoutAPI[mode]) {
layoutAPI[mode]();
}
}
/*
* Blocks API
*
*/
_uiApiBlocks(mode = 'init', block = false) {
let self = this;
// Helper variables
let elBlock, btnFullscreen, btnContentToggle;
// Set default icons for fullscreen and content toggle buttons
let iconBase = 'si';
let iconFullscreen = 'si-size-fullscreen';
let iconFullscreenActive = 'si-size-actual';
let iconContent = 'si-arrow-up';
let iconContentActive = 'si-arrow-down';
// API with object literals
let blockAPI = {
init: () => {
// Auto add the default toggle icons to fullscreen and content toggle buttons
document.querySelectorAll('[data-toggle="block-option"][data-action="fullscreen_toggle"]').forEach(btn => {
btn.innerHTML = '<i class="' + iconBase + ' ' + (btn.closest('.block').classList.contains('block-mode-fullscreen') ? iconFullscreenActive : iconFullscreen) + '"></i>';
});
document.querySelectorAll('[data-toggle="block-option"][data-action="content_toggle"]').forEach(btn => {
btn.innerHTML = '<i class="' + iconBase + ' ' + (btn.closest('.block').classList.contains('block-mode-hidden') ? iconContentActive : iconContent) + '"></i>';
});
// Call blocks API on option button click
document.querySelectorAll('[data-toggle="block-option"]').forEach(btn => {
btn.addEventListener('click', e => {
this._uiApiBlocks(btn.dataset.action, btn.closest('.block'));
});
});
},
fullscreen_toggle: () => {
elBlock.classList.remove('block-mode-pinned');
elBlock.classList.toggle('block-mode-fullscreen');
// Update block option icon
if (btnFullscreen) {
if (elBlock.classList.contains('block-mode-fullscreen')) {
btnFullscreen && btnFullscreen.querySelector('i').classList.replace(iconFullscreen, iconFullscreenActive);
} else {
btnFullscreen && btnFullscreen.querySelector('i').classList.replace(iconFullscreenActive, iconFullscreen);
}
}
},
fullscreen_on: () => {
elBlock.classList.remove('block-mode-pinned')
elBlock.classList.add('block-mode-fullscreen');
// Update block option icon
btnFullscreen && btnFullscreen.querySelector('i').classList.replace(iconFullscreen, iconFullscreenActive);
},
fullscreen_off: () => {
elBlock.classList.remove('block-mode-fullscreen');
// Update block option icon
btnFullscreen && btnFullscreen.querySelector('i').classList.replace(iconFullscreenActive, iconFullscreen);
},
content_toggle: () => {
elBlock.classList.toggle('block-mode-hidden');
// Update block option icon
if (btnContentToggle) {
if (elBlock.classList.contains('block-mode-hidden')) {
btnContentToggle.querySelector('i').classList.replace(iconContent, iconContentActive);
} else {
btnContentToggle.querySelector('i').classList.replace(iconContentActive, iconContent);
}
}
},
content_hide: () => {
elBlock.classList.add('block-mode-hidden');
// Update block option icon
btnContentToggle && btnContentToggle.querySelector('i').classList.replace(iconContent, iconContentActive);
},
content_show: () => {
elBlock.classList.remove('block-mode-hidden');
// Update block option icon
btnContentToggle && btnContentToggle.querySelector('i').classList.replace(iconContentActive, iconContent);
},
state_toggle: () => {
elBlock.classList.toggle('block-mode-loading');
// Return block to normal state if the demostration mode is on in the refresh option button - data-action-mode="demo"
if (elBlock.querySelector('[data-toggle="block-option"][data-action="state_toggle"][data-action-mode="demo"]')) {
setTimeout(() => {
elBlock.classList.remove('block-mode-loading');
}, 2000);
}
},
state_loading: () => {
elBlock.classList.add('block-mode-loading');
},
state_normal: () => {
elBlock.classList.remove('block-mode-loading');
},
pinned_toggle: () => {
elBlock.classList.remove('block-mode-fullscreen');
elBlock.classList.toggle('block-mode-pinned');
},
pinned_on: () => {
elBlock.classList.remove('block-mode-fullscreen');
elBlock.classList.add('block-mode-pinned');
},
pinned_off: () => {
elBlock.classList.remove('block-mode-pinned');
},
close: () => {
elBlock.classList.add('d-none');
},
open: () => {
elBlock.classList.remove('d-none');
}
};
if (mode === 'init') {
// Call Block API
blockAPI[mode]();
} else {
// Get block element
elBlock = (block instanceof Element) ? block : document.querySelector(`${block}`);
// If element exists, procceed with block functionality
if (elBlock) {
// Get block option buttons if exist (need them to update their icons)
btnFullscreen = elBlock.querySelector('[data-toggle="block-option"][data-action="fullscreen_toggle"]');
btnContentToggle = elBlock.querySelector('[data-toggle="block-option"][data-action="content_toggle"]');
// Call Block API
if (blockAPI[mode]) {
blockAPI[mode]();
}
}
}
}
/*
********************************************************************************************
*
* Helpers
*
*********************************************************************************************
*/
/*
* On DOM content loaded
*
*/
onLoad(fn) {
if (document.readyState != 'loading') {
fn();
} else {
document.addEventListener('DOMContentLoaded', fn);
}
}
/*
********************************************************************************************
*
* Create aliases for easier/quicker access to vital methods
*
*********************************************************************************************
*/
/*
* Init base functionality
*
*/
init() {
this._uiInit();
}
/*
* Layout API
*
*/
layout(mode) {
this._uiApiLayout(mode);
}
/*
* Blocks API
*
*/
block(mode, block) {
this._uiApiBlocks(mode, block);
}
/*
* Handle Page Loader
*
*/
loader(mode, colorClass) {
this._uiHandlePageLoader(mode, colorClass);
}
/*
* Run Helpers
*
*/
helpers(helpers, options = {}) {
Helpers.run(helpers, options);
}
/*
* Run Helpers on DOM content loaded
*
*/
helpersOnLoad(helpers, options = {}) {
this.onLoad(() => Helpers.run(helpers, options));
}
}

179
src/main/resources/static/assets/_js/pages/be_comp_calendar.js

@ -0,0 +1,179 @@
/*
* Document : be_comp_calendar.js
* Author : pixelcave
* Description: Custom JS code used in Calendar Page
*/
// Full Calendar, for more examples you can check out http://fullcalendar.io/
class pageCompCalendar {
/*
* Add event to the events list
*
*/
static addEvent() {
let eventInput = document.querySelector('.js-add-event');
let eventInputVal = '';
// When the add event form is submitted
document.querySelector('.js-form-add-event').addEventListener('submit', e => {
e.preventDefault();
// Get input value
eventInputVal = eventInput.value;
// Check if the user entered something
if (eventInputVal) {
let eventList = document.getElementById('js-events');
let newEvent = document.createElement('li');
let newEventDiv = document.createElement('div');
// Prepare new event div
newEventDiv.classList.add('js-event');
newEventDiv.classList.add('p-2');
newEventDiv.classList.add('fs-sm');
newEventDiv.classList.add('fw-medium');
newEventDiv.classList.add('rounded');
newEventDiv.classList.add('bg-info-light');
newEventDiv.classList.add('text-info');
newEventDiv.textContent = eventInputVal;
// Prepare new event li
newEvent.appendChild(newEventDiv);
// Add it to the events list
eventList.insertBefore(newEvent, eventList.firstChild);
// Clear input field
eventInput.value = '';
}
});
}
/*
* Init drag and drop event functionality
*
*/
static initEvents() {
new FullCalendar.Draggable(document.getElementById('js-events'), {
itemSelector: '.js-event',
eventData: function (eventEl) {
return {
title: eventEl.textContent,
backgroundColor: getComputedStyle(eventEl).color,
borderColor: getComputedStyle(eventEl).color
};
}
});
}
/*
* Init calendar demo functionality
*
*/
static initCalendar() {
let date = new Date();
let d = date.getDate();
let m = date.getMonth();
let y = date.getFullYear();
let calendar = new FullCalendar.Calendar(document.getElementById('js-calendar'), {
themeSystem: 'standard',
firstDay: 1,
editable: true,
droppable: true,
headerToolbar: {
left: 'title',
right: 'prev,next today dayGridMonth,timeGridWeek,timeGridDay,listWeek'
},
drop: function (info) {
info.draggedEl.parentNode.remove();
},
events: [
{
title: 'Gaming Day',
start: new Date(y, m, 1),
allDay: true
},
{
title: 'Skype Meeting',
start: new Date(y, m, 3)
},
{
title: 'Project X',
start: new Date(y, m, 9),
end: new Date(y, m, 12),
allDay: true,
color: '#e04f1a'
},
{
title: 'Work',
start: new Date(y, m, 17),
end: new Date(y, m, 19),
allDay: true,
color: '#82b54b'
},
{
id: 999,
title: 'Hiking (repeated)',
start: new Date(y, m, d - 1, 15, 0)
},
{
id: 999,
title: 'Hiking (repeated)',
start: new Date(y, m, d + 3, 15, 0)
},
{
title: 'Landing Template',
start: new Date(y, m, d - 3),
end: new Date(y, m, d - 3),
allDay: true,
color: '#ffb119'
},
{
title: 'Lunch',
start: new Date(y, m, d + 7, 15, 0),
color: '#82b54b'
},
{
title: 'Coding',
start: new Date(y, m, d, 8, 0),
end: new Date(y, m, d, 14, 0),
},
{
title: 'Trip',
start: new Date(y, m, 25),
end: new Date(y, m, 27),
allDay: true,
color: '#ffb119'
},
{
title: 'Reading',
start: new Date(y, m, d + 8, 20, 0),
end: new Date(y, m, d + 8, 22, 0)
},
{
title: 'Follow us on Twitter',
start: new Date(y, m, 22),
allDay: true,
url: 'http://twitter.com/pixelcave',
color: '#3c90df'
}
]
});
calendar.render();
}
/*
* Init functionality
*
*/
static init() {
this.addEvent();
this.initEvents();
this.initCalendar();
}
}
// Initialize when page loads
Dashmix.onLoad(() => pageCompCalendar.init());

143
src/main/resources/static/assets/_js/pages/be_comp_charts.js

@ -0,0 +1,143 @@
/*
* Document : be_comp_charts.js
* Author : pixelcave
* Description: Custom JS code used in Charts Page
*/
// Chart.js Charts, for more examples you can check out http://www.chartjs.org/docs
class pageCompCharts {
/*
* Init Charts
*
*/
static initChartsChartJS() {
// Set Global Chart.js configuration
Chart.defaults.color = '#818d96';
Chart.defaults.scale.grid.color = "rgba(0,0,0,.04)";
Chart.defaults.scale.grid.zeroLineColor = "rgba(0,0,0,.1)";
Chart.defaults.scale.beginAtZero = true;
Chart.defaults.elements.line.borderWidth = 2;
Chart.defaults.elements.point.radius = 5;
Chart.defaults.elements.point.hoverRadius = 7;
Chart.defaults.plugins.tooltip.radius = 3;
Chart.defaults.plugins.legend.labels.boxWidth = 12;
// Get Chart Containers
let chartLinesCon = document.getElementById('js-chartjs-lines');
let chartBarsCon = document.getElementById('js-chartjs-bars');
let chartRadarCon = document.getElementById('js-chartjs-radar');
let chartPolarCon = document.getElementById('js-chartjs-polar');
let chartPieCon = document.getElementById('js-chartjs-pie');
let chartDonutCon = document.getElementById('js-chartjs-donut');
// Set Chart and Chart Data variables
let chartLines, chartBars, chartRadar, chartPolar, chartPie, chartDonut;
let chartLinesBarsRadarData, chartPolarPieDonutData;
// Lines/Bar/Radar Chart Data
chartLinesBarsRadarData = {
labels: ['MON', 'TUE', 'WED', 'THU', 'FRI', 'SAT', 'SUN'],
datasets: [
{
label: 'This Week',
fill: true,
backgroundColor: 'rgba(6, 101, 208, .75)',
borderColor: 'rgba(6, 101, 208, 1)',
pointBackgroundColor: 'rgba(6, 101, 208, 1)',
pointBorderColor: '#fff',
pointHoverBackgroundColor: '#fff',
pointHoverBorderColor: 'rgba(6, 101, 208, 1)',
data: [34, 42, 62, 78, 39, 83, 98]
},
{
label: 'Last Week',
fill: true,
backgroundColor: 'rgba(108, 117, 125, .25)',
borderColor: 'rgba(108, 117, 125, .75)',
pointBackgroundColor: 'rgba(108, 117, 125, 1)',
pointBorderColor: '#fff',
pointHoverBackgroundColor: '#fff',
pointHoverBorderColor: 'rgba(108, 117, 125, 1)',
data: [130, 95, 125, 160, 187, 110, 143]
}
]
};
// Polar/Pie/Donut Data
chartPolarPieDonutData = {
labels: [
'Earnings',
'Sales',
'Tickets'
],
datasets: [{
data: [
65,
15,
20
],
backgroundColor: [
'rgba(141, 196, 81, 1)',
'rgba(255, 177, 25, 1)',
'rgba(224, 79, 26, 1)'
],
hoverBackgroundColor: [
'rgba(141, 196, 81, .5)',
'rgba(255, 177, 25, .5)',
'rgba(224, 79, 26, .5)'
]
}]
};
// Init Charts
if (chartLinesCon !== null) {
chartLines = new Chart(chartLinesCon, {type: 'line', data: chartLinesBarsRadarData, options: { responsive: true, maintainAspectRatio: false, tension: .4 }});
}
if (chartBarsCon !== null) {
chartBars = new Chart(chartBarsCon, {type: 'bar', data: chartLinesBarsRadarData, options: { responsive: true, maintainAspectRatio: false }});
}
if (chartRadarCon !== null) {
chartRadar = new Chart(chartRadarCon, {type: 'radar', data: chartLinesBarsRadarData, options: { responsive: true, maintainAspectRatio: false }});
}
if (chartPolarCon !== null) {
chartPolar = new Chart(chartPolarCon, {type: 'polarArea', data: chartPolarPieDonutData, options: { responsive: true, maintainAspectRatio: false }});
}
if (chartPieCon !== null) {
chartPie = new Chart(chartPieCon, {type: 'pie', data: chartPolarPieDonutData, options: { responsive: true, maintainAspectRatio: false }});
}
if (chartDonutCon !== null) {
chartDonut = new Chart(chartDonutCon, {type: 'doughnut', data: chartPolarPieDonutData, options: { responsive: true, maintainAspectRatio: false }});
}
}
/*
* Randomize Easy Pie Chart values
*
*/
static initRandomEasyPieChart() {
document.querySelectorAll('.js-pie-randomize').forEach(btn => {
btn.addEventListener('click', e => {
btn.closest('.block').querySelectorAll('.pie-chart').forEach(chart => {
jQuery(chart).data('easyPieChart').update(Math.floor((Math.random() * 100) + 1));
});
});
});
}
/*
* Init functionality
*
*/
static init() {
this.initChartsChartJS();
this.initRandomEasyPieChart();
}
}
// Initialize when page loads
Dashmix.onLoad(() => pageCompCharts.init());

156
src/main/resources/static/assets/_js/pages/be_comp_chat.js

@ -0,0 +1,156 @@
/*
* Document : be_comp_chat.js
* Author : pixelcave
* Description: Custom JS code used in Chat Page
*/
// Message Classes
let classesMsgBase = ['fs-sm', 'd-inline-block', 'fw-medium', 'animated', 'fadeIn', 'bg-body-light', 'border-3', 'px-3', 'py-2', 'mb-2', 'shadow-sm', 'mw-100'],
classesMsgSelf = ['border-end', 'border-primary', 'rounded-start', 'text-start'],
classesMsgOther = ['border-start', 'border-dark', 'rounded-end'],
classesMsgHeader = ['fs-sm', 'text-muted', 'animated', 'fadeIn', 'my-2'];
class pageCompChat {
/*
* Init chat
*
*/
static initChat() {
let self = this;
// Set variables
let chatForms = document.querySelectorAll('.js-chat-form form');
// Init form submission
chatForms.forEach(form => {
form.addEventListener('submit', e => {
// Stop form submission
e.preventDefault();
// Get chat input
let chatInput = e.currentTarget.querySelector('.js-chat-input');
// Add message
self.chatAddMessage(parseInt(chatInput.dataset.targetChatId), chatInput.value, 'self', chatInput);
});
});
}
/*
* Add a header message to a chat window
*
*/
static chatAddHeader(chatId, chatMsg, chatMsgLevel) {
// Get chat messages window
let chatWindow = document.querySelector('.js-chat-messages[data-chat-id="' + chatId + '"]');
// If header and chat window exists
if (chatMsg && chatWindow !== null) {
// Create new message elements and add the correct classes
let newChatMsgCon = document.createElement('div');
let newChatMsg = document.createElement('div');
classesMsgHeader.forEach(cls => {
newChatMsg.classList.add(cls);
});
if (chatMsgLevel === 'self') {
newChatMsg.classList.add('text-end');
newChatMsgCon.classList.add('ms-4');
} else {
newChatMsgCon.classList.add('me-4');
}
// Set text message
newChatMsg.innerText = chatMsg;
// Append message to chat window
newChatMsgCon.appendChild(newChatMsg);
chatWindow.appendChild(newChatMsgCon);
// Scroll the message list to the bottom
chatWindow.scrollTop = chatWindow.scrollHeight;
}
}
/*
* Add a message to a chat window
*
*/
static chatAddMessage(chatId, chatMsg, chatMsgLevel, chatInput) {
// Get chat messages window
let chatWindow = document.querySelector('.js-chat-messages[data-chat-id="' + chatId + '"]');
// If message and chat window exists
if (chatMsg && chatWindow !== null) {
// Create new message elements and add the correct classes
let newChatMsgCon = document.createElement('div');
let newChatMsg = document.createElement('div');
classesMsgBase.forEach(cls => {
newChatMsg.classList.add(cls);
});
if (chatMsgLevel === 'self') {
newChatMsgCon.classList.add('text-end');
newChatMsgCon.classList.add('ms-4');
classesMsgSelf.forEach(cls => {
newChatMsg.classList.add(cls);
});
} else {
newChatMsgCon.classList.add('me-4');
classesMsgOther.forEach(cls => {
newChatMsg.classList.add(cls);
});
}
// Set text message
newChatMsg.innerText = chatMsg;
// Append message to chat window
newChatMsgCon.appendChild(newChatMsg);
chatWindow.appendChild(newChatMsgCon);
// Scroll the message list to the bottom
chatWindow.scrollTop = chatWindow.scrollHeight;
// If input is set, reset it
if (chatInput !== null) {
chatInput.value = '';
}
}
}
/*
* Init functionality
*
*/
static init() {
this.initChat();
}
/*
* Add header
*
*/
static addHeader(chatId, chatMsg, chatMsgLevel = '') {
this.chatAddHeader(chatId, chatMsg, chatMsgLevel);
}
/*
* Add message
*
*/
static addMessage(chatId, chatMsg, chatMsgLevel = '') {
this.chatAddMessage(chatId, chatMsg, chatMsgLevel, null);
}
}
// Initialize when page loads
Dashmix.onLoad(() => {
pageCompChat.init();
window.Chat = pageCompChat;
});

106
src/main/resources/static/assets/_js/pages/be_comp_dialogs.js

@ -0,0 +1,106 @@
/*
* Document : be_comp_dialogs.js
* Author : pixelcave
* Description: Custom JS code used in Dialogs Page
*/
// SweetAlert2, for more examples you can check out https://github.com/sweetalert2/sweetalert2
class pageDialogs {
/*
* SweetAlert2 demo functionality
*
*/
static sweetAlert2() {
// Set default properties
let toast = Swal.mixin({
buttonsStyling: false,
target: '#page-container',
customClass: {
confirmButton: 'btn btn-success m-1',
cancelButton: 'btn btn-danger m-1',
input: 'form-control'
}
});
// Init a simple dialog on button click
document.querySelector('.js-swal-simple').addEventListener('click', e => {
toast.fire('Hi, this is just a simple message!');
});
// Init an success dialog on button click
document.querySelector('.js-swal-success').addEventListener('click', e => {
toast.fire('Success', 'Everything was updated perfectly!', 'success');
});
// Init an info dialog on button click
document.querySelector('.js-swal-info').addEventListener('click', e => {
toast.fire('Info', 'Just an informational message!', 'info');
});
// Init an warning dialog on button click
document.querySelector('.js-swal-warning').addEventListener('click', e => {
toast.fire('Warning', 'Something needs your attention!', 'warning');
});
// Init an error dialog on button click
document.querySelector('.js-swal-error').addEventListener('click', e => {
toast.fire('Oops...', 'Something went wrong!', 'error');
});
// Init an question dialog on button click
document.querySelector('.js-swal-question').addEventListener('click', e => {
toast.fire('Question', 'Are you sure about that?', 'question');
});
// Init an example confirm dialog on button click
document.querySelector('.js-swal-confirm').addEventListener('click', e => {
toast.fire({
title: 'Are you sure?',
text: 'You will not be able to recover this imaginary file!',
icon: 'warning',
showCancelButton: true,
customClass: {
confirmButton: 'btn btn-danger m-1',
cancelButton: 'btn btn-secondary m-1'
},
confirmButtonText: 'Yes, delete it!',
html: false,
preConfirm: e => {
return new Promise(resolve => {
setTimeout(() => {
resolve();
}, 50);
});
}
}).then(result => {
if (result.value) {
toast.fire('Deleted!', 'Your imaginary file has been deleted.', 'success');
// result.dismiss can be 'overlay', 'cancel', 'close', 'esc', 'timer'
} else if (result.dismiss === 'cancel') {
toast.fire('Cancelled', 'Your imaginary file is safe :)', 'error');
}
});
});
// Init an example confirm alert on button click
document.querySelector('.js-swal-custom-position').addEventListener('click', e => {
toast.fire({
position: 'top-end',
title: 'Perfect!',
text: 'Nice Position!',
icon: 'success'
});
});
}
/*
* Init functionality
*
*/
static init() {
this.sweetAlert2();
}
}
// Initialize when page loads
Dashmix.onLoad(() => pageDialogs.init());

88
src/main/resources/static/assets/_js/pages/be_comp_image_cropper.js

@ -0,0 +1,88 @@
/*
* Document : be_comp_image_cropper.js
* Author : pixelcave
* Description: Custom JS code used in Image Cropper Page
*/
// Image Cropper, for more examples you can check out https://fengyuanchen.github.io/cropperjs/
class pageCompImageCropper {
/*
* Init image cropper demo functionality
*
*/
static initImageCropper() {
// Get Image Container
let image = document.getElementById('js-img-cropper');
// Set Options
Cropper.setDefaults({
aspectRatio: 4 / 3,
preview: '.js-img-cropper-preview'
});
// Init Image Cropper
let cropper = new Cropper(image, {
crop: function (e) {
// e.detail contains all data required to crop the image server side
// You will have to send it to your custom server side script and crop the image there
// Since this event is fired each time you set the crop section, you could also use getData()
// method on demand. Please check out https://fengyuanchen.github.io/cropperjs/ for more info
// console.log(e.detail);
}
});
// Mini Cropper API
document.querySelectorAll('[data-toggle="cropper"]').forEach(btn => {
btn.addEventListener('click', e => {
let method = btn.dataset.method || false;
let option = btn.dataset.option || false;
// Method selection with object literals
let cropperAPI = {
zoom: () => {
cropper.zoom(option);
},
setDragMode: () => {
cropper.setDragMode(option);
},
rotate: () => {
cropper.rotate(option);
},
scaleX: () => {
cropper.scaleX(option);
btn.dataset.option = -(option);
},
scaleY: () => {
cropper.scaleY(option);
btn.dataset.option = -(option);
},
setAspectRatio: () => {
cropper.setAspectRatio(option);
},
crop: () => {
cropper.crop();
},
clear: () => {
cropper.clear();
}
};
// If method exists, execute it
if (cropperAPI[method]) {
cropperAPI[method]();
}
});
});
}
/*
* Init functionality
*
*/
static init() {
this.initImageCropper();
}
}
// Initialize when page loads
Dashmix.onLoad(() => pageCompImageCropper.init());

154
src/main/resources/static/assets/_js/pages/be_comp_maps_vector.js

@ -0,0 +1,154 @@
/*
* Document : be_comp_maps_vector.js
* Author : pixelcave
* Description: Custom JS code used in Vector Maps Page
*/
// Set default options for all maps
let mapOptions = {
map: '',
backgroundColor: '#ffffff',
regionStyle: {
initial: {
fill: '#1F75D5',
'fill-opacity': 1,
stroke: 'none',
'stroke-width': 0,
'stroke-opacity': 1
},
hover: {
'fill-opacity': .8,
cursor: 'pointer'
}
}
};
// jVectorMap, for more examples you can check out http://jvectormap.com/documentation/
class pageCompMapsVector {
/*
* Init World Map
*
*/
static initMapWorld() {
// Set Active Map
mapOptions['map'] = 'world_mill_en';
// Init Map
jQuery('.js-vector-map-world').vectorMap(mapOptions);
}
/*
* Init Europe Map
*
*/
static initMapEurope() {
// Set Active Map
mapOptions['map'] = 'europe_mill_en';
// Init Map
jQuery('.js-vector-map-europe').vectorMap(mapOptions);
}
/*
* Init USA Map
*
*/
static initMapUsa() {
// Set Active Map
mapOptions['map'] = 'us_aea_en';
// Init Map
jQuery('.js-vector-map-usa').vectorMap(mapOptions);
}
/*
* Init India Map
*
*/
static initMapIndia() {
// Set Active Map
mapOptions['map'] = 'in_mill_en';
// Init Map
jQuery('.js-vector-map-india').vectorMap(mapOptions);
}
/*
* Init China Map
*
*/
static initMapChina() {
// Set Active Map
mapOptions['map'] = 'cn_mill_en';
// Init Map
jQuery('.js-vector-map-china').vectorMap(mapOptions);
}
/*
* Init Australia Map
*
*/
static initMapAustralia() {
// Set Active Map
mapOptions['map'] = 'au_mill_en';
// Init Map
jQuery('.js-vector-map-australia').vectorMap(mapOptions);
}
/*
* Init South Africa Map
*
*/
static initMapSouthAfrica() {
// Set Active Map
mapOptions['map'] = 'za_mill_en';
// Init Map
jQuery('.js-vector-map-south-africa').vectorMap(mapOptions);
}
/*
* Init France Map
*
*/
static initMapFrance() {
// Set Active Map
mapOptions['map'] = 'fr_mill_en';
// Init Map
jQuery('.js-vector-map-france').vectorMap(mapOptions);
}
/*
* Init Germany Map
*
*/
static initMapGermany() {
// Set Active Map
mapOptions['map'] = 'de_mill_en';
// Init Map
jQuery('.js-vector-map-germany').vectorMap(mapOptions);
}
/*
* Init functionality
*
*/
static init() {
this.initMapWorld();
this.initMapEurope();
this.initMapUsa();
this.initMapIndia();
this.initMapChina();
this.initMapAustralia();
this.initMapSouthAfrica();
this.initMapFrance();
this.initMapGermany();
}
}
// Initialize when page loads
Dashmix.onLoad(() => pageCompMapsVector.init());

47
src/main/resources/static/assets/_js/pages/be_comp_nestable.js

@ -0,0 +1,47 @@
/*
* Document : be_comp_nestable.js
* Author : pixelcave
* Description: Custom JS code used in Nestable Page
*/
// Nestable2, for more examples you can check out https://github.com/RamonSmit/Nestable2
class pageCompNestable {
/*
* Nestable2 demo functionality
*
*/
static nestable2() {
// Init Connected Lists
jQuery('.js-nestable-connected-simple').
add('.js-nestable-connected-icons').
add('.js-nestable-connected-treeview').nestable({
group: 0
});
// Init Simple List
jQuery('.js-nestable-simple').nestable({
group: 1
});
// Init Icons List
jQuery('.js-nestable-icons').nestable({
group: 2
});
// Init Tree View List
jQuery('.js-nestable-treeview').nestable({
group: 3
});
}
/*
* Init functionality
*
*/
static init() {
this.nestable2();
}
}
// Initialize when page loads
Dashmix.onLoad(() => pageCompNestable.init());

41
src/main/resources/static/assets/_js/pages/be_comp_onboarding.js

@ -0,0 +1,41 @@
/*
* Document : be_comp_onboarding.js
* Author : pixelcave
* Description: Custom JS code used in Onboarding Page
*/
// Onboarding Modal using Bootstrap Modal and Slick slider
class pageCompOnboarding {
/*
* Init example onboarding modal functionality
*
*/
static initOnboardingModal() {
// Get onboarding modal
let modalEl = document.getElementById('modal-onboarding');
let modal = new bootstrap.Modal(modalEl);
// Show Onboarding Modal by default
modal.show();
// Re-init Slick Slider every time the modal is shown
modalEl.addEventListener('shown.bs.modal', e => {
// Remove enabled class added by the helper to prevent re-init
document.querySelector('#modal-onboarding .js-slider').classList.remove('js-slider-enabled');
// Re-init Slick Slider
Dashmix.helpers('jq-slick');
});
}
/*
* Init functionality
*
*/
static init() {
this.initOnboardingModal();
}
}
// Initialize when page loads
Dashmix.onLoad(() => pageCompOnboarding.init());

50
src/main/resources/static/assets/_js/pages/be_comp_rating.js

@ -0,0 +1,50 @@
/*
* Document : be_comp_rating.js
* Author : pixelcave
* Description: Custom JS code used in Rating Page
*/
// jQuery Raty, for more examples you can check out https://github.com/wbotelhos/raty
class pageCompRating {
/*
* Init demo rating functionality
*
*/
static initRating() {
// Init Raty on .js-rating class
jQuery('.js-rating').each((index, element) => {
let el = jQuery(element);
el.raty({
score: el.data('score') || 0,
number: el.data('number') || 5,
cancel: el.data('cancel') || false,
target: el.data('target') || false,
targetScore: el.data('target-score') || false,
precision: el.data('precision') || false,
cancelOff: el.data('cancel-off') || 'fa fa-fw fa-times-circle text-danger',
cancelOn: el.data('cancel-on') || 'fa fa-fw fa-times-circle',
starHalf: el.data('star-half') || 'fa fa-fw fa-star-half text-warning',
starOff: el.data('star-off') || 'fa fa-fw fa-star text-muted',
starOn: el.data('star-on') || 'fa fa-fw fa-star text-warning',
starType: 'i',
hints: ['Just Bad!', 'Almost There!', 'It’s ok!', 'That’s nice!', 'Incredible!'],
click: function (score, evt) {
// Here you could add your logic on rating click
// console.log('ID: ' + this.id + "\nscore: " + score + "\nevent: " + evt);
}
});
});
}
/*
* Init functionality
*
*/
static init() {
this.initRating();
}
}
// Initialize when page loads
Dashmix.onLoad(() => pageCompRating.init());

124
src/main/resources/static/assets/_js/pages/be_forms_validation.js

@ -0,0 +1,124 @@
/*
* Document : be_forms_validation.js
* Author : pixelcave
* Description: Custom JS code used in Forms Validation Page
*/
// Form Validation, for more examples you can check out https://github.com/jzaefferer/jquery-validation
class pageFormsValidation {
/*
* Init Validation functionality
*
*/
static initValidation() {
// Load default options for jQuery Validation plugin
Dashmix.helpers('jq-validation');
// Init Form Validation
jQuery('.js-validation').validate({
ignore: [],
rules: {
'val-username': {
required: true,
minlength: 3
},
'val-email': {
required: true,
emailWithDot: true
},
'val-password': {
required: true,
minlength: 5
},
'val-confirm-password': {
required: true,
equalTo: '#val-password'
},
'val-suggestions': {
required: true,
minlength: 5
},
'val-skill': {
required: true
},
'val-currency': {
required: true,
currency: ['$', true]
},
'val-website': {
required: true,
url: true
},
'val-phoneus': {
required: true,
phoneUS: true
},
'val-digits': {
required: true,
digits: true
},
'val-number': {
required: true,
number: true
},
'val-range': {
required: true,
range: [1, 5]
},
'val-terms': {
required: true
},
'val-select2': {
required: true
},
'val-select2-multiple': {
required: true,
minlength: 2
}
},
messages: {
'val-username': {
required: 'Please enter a username',
minlength: 'Your username must consist of at least 3 characters'
},
'val-email': 'Please enter a valid email address',
'val-password': {
required: 'Please provide a password',
minlength: 'Your password must be at least 5 characters long'
},
'val-confirm-password': {
required: 'Please provide a password',
minlength: 'Your password must be at least 5 characters long',
equalTo: 'Please enter the same password as above'
},
'val-select2': 'Please select a value!',
'val-select2-multiple': 'Please select at least 2 values!',
'val-suggestions': 'What can we do to become better?',
'val-skill': 'Please select a skill!',
'val-currency': 'Please enter a price!',
'val-website': 'Please enter your website!',
'val-phoneus': 'Please enter a US phone!',
'val-digits': 'Please enter only digits!',
'val-number': 'Please enter a number!',
'val-range': 'Please enter a number between 1 and 5!',
'val-terms': 'You must agree to the service terms!'
}
});
// Init Validation on Select2 change
jQuery('.js-select2').on('change', e => {
jQuery(e.currentTarget).valid();
});
}
/*
* Init functionality
*
*/
static init() {
this.initValidation();
}
}
// Initialize when page loads
Dashmix.onLoad(() => pageFormsValidation.init());

89
src/main/resources/static/assets/_js/pages/be_pages_dashboard.js

@ -0,0 +1,89 @@
/*
* Document : be_pages_dashboard.js
* Author : pixelcave
* Description: Custom JS code used in Default Dashboard Page
*/
// Chart.js Charts, for more examples you can check out http://www.chartjs.org/docs
class pageDashboard {
/*
* Init Charts
*
*/
static initChartsBars() {
// Set Global Chart.js configuration
Chart.defaults.color = '#818d96';
Chart.defaults.scale.grid.color = 'transparent';
Chart.defaults.scale.grid.zeroLineColor = 'transparent';
Chart.defaults.scale.beginAtZero = true;
Chart.defaults.elements.line.borderWidth = 1;
Chart.defaults.plugins.legend.labels.boxWidth = 12;
// Get Chart Containers
let chartBarsCon = document.getElementById('js-chartjs-analytics-bars');
// Set Chart and Chart Data variables
let chartBars, chartLinesBarsData;
// Bars Chart Data
chartLinesBarsData = {
labels: ['MON', 'TUE', 'WED', 'THU', 'FRI', 'SAT', 'SUN'],
datasets: [
{
label: 'This Week',
fill: true,
backgroundColor: 'rgba(6, 101, 208, .6)',
borderColor: 'transparent',
pointBackgroundColor: 'rgba(6, 101, 208, 1)',
pointBorderColor: '#fff',
pointHoverBackgroundColor: '#fff',
pointHoverBorderColor: 'rgba(6, 101, 208, 1)',
data: [73, 68, 69, 53, 60, 72, 82]
},
{
label: 'Last Week',
fill: true,
backgroundColor: 'rgba(6, 101, 208, .2)',
borderColor: 'transparent',
pointBackgroundColor: 'rgba(6, 101, 208, .2)',
pointBorderColor: '#fff',
pointHoverBackgroundColor: '#fff',
pointHoverBorderColor: 'rgba(6, 101, 208, .2)',
data: [62, 32, 59, 55, 52, 56, 73]
}
]
};
// Init Chart
if (chartBarsCon !== null) {
chartBars = new Chart(chartBarsCon, {
type: 'bar',
data: chartLinesBarsData,
options: {
responsive: true,
maintainAspectRatio: false,
plugins: {
tooltip: {
callbacks: {
label: function (context) {
return context.dataset.label + ': ' + context.parsed.y + ' Customers';
}
}
}
}
}
});
}
}
/*
* Init functionality
*
*/
static init() {
this.initChartsBars();
}
}
// Initialize when page loads
Dashmix.onLoad(() => pageDashboard.init());

225
src/main/resources/static/assets/_js/pages/be_pages_dashboard_v1.js

@ -0,0 +1,225 @@
/*
* Document : be_pages_dashboard.js
* Author : pixelcave
* Description: Custom JS code used in default Dashboard v1 Page
*/
// Chart.js Charts, for more examples you can check out http://www.chartjs.org/docs
class pageDashboardv1 {
/*
* Init Charts
*
*/
static initChartsMain() {
// Set Global Chart.js configuration
Chart.defaults.color = '#818d96';
Chart.defaults.scale.grid.color = 'transparent';
Chart.defaults.scale.grid.zeroLineColor = 'transparent';
Chart.defaults.scale.display = false;
Chart.defaults.scale.beginAtZero = true;
Chart.defaults.elements.point.radius = 0;
Chart.defaults.elements.point.hoverRadius = 0;
Chart.defaults.plugins.tooltip.radius = 3;
Chart.defaults.plugins.legend.labels.boxWidth = 12;
// Get Chart Containers
let chartMainCon = document.getElementById('js-chartjs-dashboard-earnings');
// Set Main Chart variables
let chartMain, chartMainOptions, chartMainData, chartMainDataYear, chartMainDataMonth, chartMainDataWeek;
// Main Chart Options
chartMainOptions = {
responsive: true,
maintainAspectRatio: false,
tension: .4,
scales: {
y: {
suggestedMin: 0,
suggestedMax: 260
}
},
interaction: {
intersect: false,
},
plugins: {
tooltip: {
callbacks: {
label: function (context) {
return ' ' + context.parsed.y + ' Sales';
}
}
}
}
};
// Main Chart Default Data
chartMainData = {
labels: ['JAN', 'FEB', 'MAR', 'APR', 'MAY', 'JUN', 'JUL', 'AUG', 'SEP', 'OCT', 'NOV', 'DEC'],
datasets: [
{
label: 'This Year',
fill: true,
backgroundColor: 'rgba(6, 101, 208, .5)',
borderColor: 'transparent',
pointBackgroundColor: 'rgba(6, 101, 208, 1)',
pointBorderColor: '#fff',
pointHoverBackgroundColor: '#fff',
pointHoverBorderColor: 'rgba(6, 101, 208, 1)',
data: [50, 210, 110, 90, 230, 130, 190, 75, 155, 120, 140, 230]
},
{
label: 'Last Year',
fill: true,
backgroundColor: 'rgba(6, 101, 208, .2)',
borderColor: 'transparent',
pointBackgroundColor: 'rgba(6, 101, 208, .2)',
pointBorderColor: '#fff',
pointHoverBackgroundColor: '#fff',
pointHoverBorderColor: 'rgba(6, 101, 208, .2)',
data: [210, 150, 90, 220, 150, 216, 143, 150, 240, 230, 136, 150]
}
]
};
// Main Chart for Year
chartMainDataYear = {
labels: ['JAN', 'FEB', 'MAR', 'APR', 'MAY', 'JUN', 'JUL', 'AUG', 'SEP', 'OCT', 'NOV', 'DEC'],
datasets: [
{
label: 'This Year',
fill: true,
backgroundColor: 'rgba(6, 101, 208, .5)',
borderColor: 'transparent',
pointBackgroundColor: 'rgba(6, 101, 208, 1)',
pointBorderColor: '#fff',
pointHoverBackgroundColor: '#fff',
pointHoverBorderColor: 'rgba(6, 101, 208, 1)',
data: [50, 210, 110, 90, 230, 130, 190, 75, 155, 120, 140, 230]
},
{
label: 'Last Year',
fill: true,
backgroundColor: 'rgba(6, 101, 208, .2)',
borderColor: 'transparent',
pointBackgroundColor: 'rgba(6, 101, 208, .2)',
pointBorderColor: '#fff',
pointHoverBackgroundColor: '#fff',
pointHoverBorderColor: 'rgba(6, 101, 208, .2)',
data: [210, 150, 90, 220, 150, 216, 143, 150, 240, 230, 136, 150]
}
]
};
// Set up month labels
let chartMainDataMonthLabels = [];
for (let i = 0; i < 30; i++) {
chartMainDataMonthLabels[i] = (i === 29) ? '1 day ago' : (30 - i) + ' days ago';
}
// Main Chart Data for Month
chartMainDataMonth = {
labels: chartMainDataMonthLabels,
datasets: [
{
label: 'This Month',
fill: true,
backgroundColor: 'rgba(6, 101, 208, .5)',
borderColor: 'transparent',
pointBackgroundColor: 'rgba(6, 101, 208, 1)',
pointBorderColor: '#fff',
pointHoverBackgroundColor: '#fff',
pointHoverBorderColor: 'rgba(6, 101, 208, 1)',
data: [50, 210, 110, 90, 230, 130, 190, 75, 155, 120, 140, 230, 50, 210, 110, 90, 230, 130, 155, 120, 140, 230, 50, 210, 110, 90, 230, 130, 190, 75]
},
{
label: 'Last Month',
fill: true,
backgroundColor: 'rgba(6, 101, 208, .2)',
borderColor: 'transparent',
pointBackgroundColor: 'rgba(6, 101, 208, .2)',
pointBorderColor: '#fff',
pointHoverBackgroundColor: '#fff',
pointHoverBorderColor: 'rgba(6, 101, 208, .2)',
data: [210, 150, 90, 220, 150, 216, 143, 150, 136, 150, 210, 150, 90, 220, 150, 216, 240, 230, 136, 150, 210, 150, 90, 220, 150, 216, 143, 150, 240, 230]
}
]
};
// Main Chart Data for Week
chartMainDataWeek = {
labels: ['MON', 'TUE', 'WED', 'THU', 'FRI', 'SAT', 'SUN'],
datasets: [
{
label: 'This Week',
fill: true,
backgroundColor: 'rgba(6, 101, 208, .5)',
borderColor: 'transparent',
pointBackgroundColor: 'rgba(6, 101, 208, 1)',
pointBorderColor: '#fff',
pointHoverBackgroundColor: '#fff',
pointHoverBorderColor: 'rgba(6, 101, 208, 1)',
data: [34, 42, 62, 78, 39, 83, 98]
},
{
label: 'Last Week',
fill: true,
backgroundColor: 'rgba(6, 101, 208, .2)',
borderColor: 'transparent',
pointBackgroundColor: 'rgba(6, 101, 208, .2)',
pointBorderColor: '#fff',
pointHoverBackgroundColor: '#fff',
pointHoverBorderColor: 'rgba(6, 101, 208, .2)',
data: [130, 95, 125, 160, 187, 110, 143]
}
]
};
// Init Main Chart
if (chartMainCon !== null) {
chartMain = new Chart(chartMainCon, {
type: 'line',
data: chartMainData,
options: chartMainOptions
});
}
// Toggle to Week data
document.querySelector('[data-toggle="dashboard-chart-set-week"]').addEventListener('click', () => {
chartMain.data.labels = chartMainDataWeek.labels;
chartMain.data.datasets[0] = chartMainDataWeek.datasets[0];
chartMain.data.datasets[1] = chartMainDataWeek.datasets[1];
chartMain.update();
});
// Toggle to Month data
document.querySelector('[data-toggle="dashboard-chart-set-month"]').addEventListener('click', () => {
chartMain.data.labels = chartMainDataMonth.labels;
chartMain.data.datasets[0] = chartMainDataMonth.datasets[0];
chartMain.data.datasets[1] = chartMainDataMonth.datasets[1];
chartMain.update();
});
// Toggle to Year data
document.querySelector('[data-toggle="dashboard-chart-set-year"]').addEventListener('click', () => {
chartMain.data.labels = chartMainDataYear.labels;
chartMain.data.datasets[0] = chartMainDataYear.datasets[0];
chartMain.data.datasets[1] = chartMainDataYear.datasets[1];
chartMain.update();
});
}
/*
* Init functionality
*
*/
static init() {
this.initChartsMain();
}
}
// Initialize when page loads
jQuery(() => {
pageDashboardv1.init();
});

104
src/main/resources/static/assets/_js/pages/be_pages_ecom_dashboard.js

@ -0,0 +1,104 @@
/*
* Document : be_pages_ecom_dashboard.js
* Author : pixelcave
* Description: Custom JS code used in eCommerce Dashboard Page
*/
// Chart.js Charts, for more examples you can check out http://www.chartjs.org/docs
class pageEcomDashboard {
/*
* Init Charts
*
*/
static initOverviewChart() {
// Set Global Chart.js configuration
Chart.defaults.color = '#818d96';
Chart.defaults.scale.grid.color = 'transparent';
Chart.defaults.scale.grid.zeroLineColor = 'transparent';
Chart.defaults.scale.beginAtZero = true;
Chart.defaults.elements.point.radius = 0;
Chart.defaults.elements.point.hoverRadius = 0;
Chart.defaults.plugins.tooltip.radius = 3;
Chart.defaults.plugins.legend.labels.boxWidth = 12;
// Get Chart Container
let chartOverviewCon = document.getElementById('js-chartjs-overview');
// Set Chart Variables
let chartOverview, chartOverviewOptions, chartOverviewData;
// Overview Chart Options
chartOverviewOptions = {
responsive: true,
maintainAspectRatio: false,
tension: .4,
scales: {
y: {
suggestedMin: 0,
suggestedMax: 600
}
},
interaction: {
intersect: false,
},
plugins: {
tooltip: {
callbacks: {
label: function (context) {
return '$ ' + context.parsed.y;
}
}
}
}
};
// Overview Chart Data
chartOverviewData = {
labels: ['MON', 'TUE', 'WED', 'THU', 'FRI', 'SAT', 'SUN'],
datasets: [
{
label: 'This Week',
fill: true,
backgroundColor: 'rgba(6, 101, 208, .5)',
borderColor: 'transparent',
pointBackgroundColor: 'rgba(6, 101, 208, 1)',
pointBorderColor: '#fff',
pointHoverBackgroundColor: '#fff',
pointHoverBorderColor: 'rgba(6, 101, 208, 1)',
data: [369, 255, 420, 330, 460, 160, 350]
},
{
label: 'Last Week',
fill: true,
backgroundColor: 'rgba(6, 101, 208, .2)',
borderColor: 'transparent',
pointBackgroundColor: 'rgba(6, 101, 208, .2)',
pointBorderColor: '#fff',
pointHoverBackgroundColor: '#fff',
pointHoverBorderColor: 'rgba(6, 101, 208, .2)',
data: [270, 460, 290, 231, 419, 450, 280]
}
]
};
// Init Overview Chart
if (chartOverviewCon !== null) {
chartOverview = new Chart(chartOverviewCon, {
type: 'line',
data: chartOverviewData,
options: chartOverviewOptions
});
}
}
/*
* Init functionality
*
*/
static init() {
this.initOverviewChart();
}
}
// Initialize when page loads
Dashmix.onLoad(() => pageEcomDashboard.init());

271
src/main/resources/static/assets/_js/pages/be_pages_projects_tasks.js

@ -0,0 +1,271 @@
/*
* Document : be_pages_projects_tasks.js
* Author : pixelcave
* Description: Custom JS code used in Project Tasks and Tasks Dashboard Page
*/
// Helper variables
let taskIdNext, tasks, taskForm, taskInput, taskInputVal,
taskList, taskListStarred, taskListCompleted,
taskBadge, taskBadgeStarred, taskBadgeCompleted;
class pageTasks {
/*
* Init Tasks
*
*/
static initTasks() {
let self = this;
// Set variables
tasks = jQuery('.js-tasks');
taskForm = jQuery('#js-task-form');
taskInput = jQuery('#js-task-input');
taskList = jQuery('.js-task-list');
taskListStarred = jQuery('.js-task-list-starred');
taskListCompleted = jQuery('.js-task-list-completed');
taskBadge = jQuery('.js-task-badge');
taskBadgeStarred = jQuery('.js-task-badge-starred');
taskBadgeCompleted = jQuery('.js-task-badge-completed');
// Set your own next new task id based on your database setup
taskIdNext = 10;
// Update badges
this.badgesUpdate();
// New task form submission
taskForm.on('submit', e => {
e.preventDefault();
// Get input value
taskInputVal = taskInput.prop('value');
// Check if the user entered something
if (taskInputVal) {
// Add Task
self.taskAdd(taskInputVal);
// Clear and focus input field
taskInput.prop('value', '').focus();
}
});
// Task status update on checkbox click
let stask, staskId;
tasks.on('click', '.js-task-status', e => {
stask = jQuery(e.currentTarget).closest('.js-task');
staskId = stask.data('task-id');
// Check task status and toggle it
if (stask.data('task-completed')) {
self.taskSetActive(staskId);
} else {
self.taskSetCompleted(staskId);
}
});
// Task starred status update on star click
let ftask, ftaskId;
tasks.on('click', '.js-task-star', e => {
ftask = jQuery(e.currentTarget).closest('.js-task');
ftaskId = ftask.data('task-id');
// Check task starred status and toggle it
if (ftask.data('task-starred')) {
self.taskStarRemove(ftaskId);
} else {
self.taskStarAdd(ftaskId);
}
});
// Remove task on remove button click
tasks.on('click', '.js-task-remove', e => {
ftask = jQuery(e.currentTarget).closest('.js-task');
ftaskId = ftask.data('task-id');
// Remove task
self.taskRemove(ftaskId);
});
}
/*
* Update Badges
*
*/
static badgesUpdate() {
taskBadge.text(taskList.children().length || '');
taskBadgeStarred.text(taskListStarred.children().length || '');
taskBadgeCompleted.text(taskListCompleted.children().length || '');
}
/*
* Add a new task
*
*/
static taskAdd(taskContent) {
// Add it to the task list
taskList.prepend(`
<div class="js-task block block-rounded mb-2 animated fadeIn" data-task-id="${taskIdNext}" data-task-completed="false" data-task-starred="false">
<table class="table table-borderless table-vcenter mb-0">
<tr>
<td class="text-center pe-0" style="width: 38px;">
<div class="js-task-status form-check">
<input type="checkbox" class="form-check-input" id="tasks-cb-id${taskIdNext}" name="tasks-cb-id${taskIdNext}">
<label class="form-check-label" for="tasks-cb-id${taskIdNext}"></label>
</div>
</td>
<td class="js-task-content fw-semibold ps-0">
${jQuery('<span />').text(taskContent).html()}
</td>
<td class="text-end" style="width: 100px;">
<button type="button" class="js-task-star btn btn-sm btn-link text-warning">
<i class="far fa-star fa-fw"></i>
</button>
<button type="button" class="js-task-remove btn btn-sm btn-link text-danger">
<i class="fa fa-times fa-fw"></i>
</button>
</td>
</tr>
</table>
</div>
`);
// Update badges
this.badgesUpdate();
// Save the task based on your database setup
// ..
// Update task next id
taskIdNext++;
}
/*
* Remove a task
*
*/
static taskRemove(taskId) {
jQuery('.js-task[data-task-id="' + taskId + '"]').remove();
// Update badges
this.badgesUpdate();
// Remove the task based on your database setup
// ..
}
/*
* Star a task
*
*/
static taskStarAdd(taskId) {
let task = jQuery('.js-task[data-task-id="' + taskId + '"]');
// Check if exists and update accordignly the markup
if (task.length > 0) {
task.data('task-starred', true);
task.find('.js-task-star > i').toggleClass('fa far');
if (!task.data('task-completed')) {
task.prependTo(taskListStarred);
}
// Update badges
this.badgesUpdate();
// Star the task based on your database setup
// ..
}
}
/*
* Unstar a task
*
*/
static taskStarRemove(taskId) {
let task = jQuery('.js-task[data-task-id="' + taskId + '"]');
// Check if exists and update accordignly the markup
if (task.length > 0) {
task.data('task-starred', false);
task.find('.js-task-star > i').toggleClass('fa far');
if (!task.data('task-completed')) {
task.prependTo(taskList);
}
// Update badges
this.badgesUpdate();
// Unstar the task based on your database setup
// ..
}
}
/*
* Set a task to active
*
*/
static taskSetActive(taskId) {
let task = jQuery('.js-task[data-task-id="' + taskId + '"]');
// Check if exists and update accordignly
if (task.length > 0) {
task.data('task-completed', false);
task.find('.table').toggleClass('bg-body');
task.find('.js-task-status > input').prop('checked', false);
task.find('.js-task-content > del').contents().unwrap();
if (task.data('task-starred')) {
task.prependTo(taskListStarred);
} else {
task.prependTo(taskList);
}
// Update badges
this.badgesUpdate();
// Update task status based on your database setup
// ..
}
}
/*
* Set a task to completed
*
*/
static taskSetCompleted(taskId) {
let task = jQuery('.js-task[data-task-id="' + taskId + '"]');
// Check if exists and update accordignly
if (task.length > 0) {
task.data('task-completed', true);
task.find('.table').toggleClass('bg-body');
task.find('.js-task-status > input').prop('checked', true);
task.find('.js-task-content').wrapInner('<del></del>');
task.prependTo(taskListCompleted);
// Update badges
this.badgesUpdate();
// Update task status based on your database setup
// ..
}
}
/*
* Init functionality
*
*/
static init() {
this.initTasks();
}
}
// Initialize when page loads
Dashmix.onLoad(() => pageTasks.init());

45
src/main/resources/static/assets/_js/pages/be_ui_animations.js

@ -0,0 +1,45 @@
/*
* Document : be_ui_animations.js
* Author : pixelcave
* Description: Custom JS code used in Animations Page
*/
class pageAnimations {
/*
* Animation toggle functionality
*
*/
static animationsToggle() {
let animationClass, animationButton, currentSection;
// On button click
document.querySelectorAll('.js-animation-section button').forEach(btn => {
btn.addEventListener('click', e => {
animationClass = btn.dataset.animationClass;
currentSection = btn.closest('.js-animation-section');
// Update class preview
currentSection.querySelector('.js-animation-preview').textContent = animationClass;
// Update animation object classes
let animationObject = currentSection.querySelector('.js-animation-object')
animationObject.classList = '';
animationObject.classList.add('js-animation-object');
animationObject.classList.add('animated');
animationObject.classList.add(animationClass);
});
});
}
/*
* Init functionality
*
*/
static init() {
this.animationsToggle();
}
}
// Initialize when page loads
Dashmix.onLoad(() => pageAnimations.init());

2184
src/main/resources/static/assets/_js/pages/be_ui_icons.js
File diff suppressed because it is too large
View File

41
src/main/resources/static/assets/_js/pages/be_ui_progress.js

@ -0,0 +1,41 @@
/*
* Document : be_ui_progress.js
* Author : pixelcave
* Description: Custom JS code used in Progress Page
*/
class pageProgress {
/*
* Bars randomize functionality
*
*/
static barsRandomize() {
document.querySelectorAll('.js-bar-randomize').forEach(item => {
item.addEventListener('click', e => {
item.closest('.block').querySelectorAll('.progress-bar').forEach(bar => {
let random = Math.floor((Math.random() * 91) + 10);
let content = bar.querySelector('span');
// Update progress width
bar.style.width = random + '%';
// Update progress label
if (content) {
content.textContent = random + '%';
}
});
});
});
}
/*
* Init functionality
*
*/
static init() {
this.barsRandomize();
}
}
// Initialize when page loads
Dashmix.onLoad(() => pageProgress.init());

73
src/main/resources/static/assets/_js/pages/db_analytics.js

@ -0,0 +1,73 @@
/*
* Document : db_analytics.js
* Author : pixelcave
* Description: Custom JS code used in Analytics Dashboard Page
*/
// Chart.js Charts, for more examples you can check out http://www.chartjs.org/docs
class pageDashboardAnalytics {
/*
* Init Charts
*
*/
static initChartsBars() {
// Set Global Chart.js configuration
Chart.defaults.color = '#818d96';
Chart.defaults.scale.grid.color = 'transparent';
Chart.defaults.scale.grid.zeroLineColor = 'transparent';
Chart.defaults.scale.beginAtZero = true;
Chart.defaults.elements.line.borderWidth = 1;
Chart.defaults.plugins.legend.labels.boxWidth = 12;
// Get Chart Containers
let chartBarsCon = document.getElementById('js-chartjs-analytics-bars');
// Set Chart and Chart Data variables
let chartBars, chartLinesBarsData;
// Bars Chart Data
chartLinesBarsData = {
labels: ['MON', 'TUE', 'WED', 'THU', 'FRI', 'SAT', 'SUN'],
datasets: [
{
label: 'This Week',
fill: true,
backgroundColor: 'rgba(103, 114, 229, .75)',
borderColor: 'rgba(103, 114, 229, 1)',
pointBackgroundColor: 'rgba(103, 114, 229, 1)',
pointBorderColor: '#fff',
pointHoverBackgroundColor: '#fff',
pointHoverBorderColor: 'rgba(103, 114, 229, 1)',
data: [500, 750, 650, 570, 582, 480, 680]
},
{
label: 'Last Week',
fill: true,
backgroundColor: 'rgba(108, 117, 125, .15)',
borderColor: 'rgba(108, 117, 125, .75)',
pointBackgroundColor: 'rgba(108, 117, 125, 1)',
pointBorderColor: '#fff',
pointHoverBackgroundColor: '#fff',
pointHoverBorderColor: 'rgba(108, 117, 125, 1)',
data: [352, 530, 541, 521, 410, 395, 460]
}
]
};
// Init Chart
if (chartBarsCon !== null) {
chartBars = new Chart(chartBarsCon, {type: 'bar', data: chartLinesBarsData, options: { responsive: true, maintainAspectRatio: false }});
}
}
/*
* Init functionality
*
*/
static init() {
this.initChartsBars();
}
}
// Initialize when page loads
Dashmix.onLoad(() => pageDashboardAnalytics.init());

144
src/main/resources/static/assets/_js/pages/db_corporate_slim.js

@ -0,0 +1,144 @@
/*
* Document : db_corporate_slim.js
* Author : pixelcave
* Description: Custom JS code used in Corporate Slim Dashboard Page
*/
// Chart.js Charts, for more examples you can check out http://www.chartjs.org/docs
class DbCorporateSlim {
/*
* Init Charts
*
*/
static initCorporateChartJS() {
// Set Global Chart.js configuration
Chart.defaults.color = '#7c7c7c';
Chart.defaults.scale.grid.color = "transparent";
Chart.defaults.scale.grid.zeroLineColor = "transparent";
Chart.defaults.scale.display = false;
Chart.defaults.scale.beginAtZero = true;
Chart.defaults.elements.line.borderWidth = 2;
Chart.defaults.elements.point.radius = 6;
Chart.defaults.elements.point.hoverRadius = 10;
Chart.defaults.plugins.tooltip.radius = 3;
Chart.defaults.plugins.legend.display = false;
// Chart Containers
let chartCorporateSlimProjectsCon = document.getElementById('js-chartjs-corporate-slim-projects');
let chartCorporateSlimTicketsCon = document.getElementById('js-chartjs-corporate-slim-tickets');
// Chart Variables
let chartCorporateSlimProjects, chartCorporateSlimTickets;
// Lines Charts Data
let chartCorporateSlimProjectsData = {
labels: ['MON', 'TUE', 'WED', 'THU', 'FRI', 'SAT', 'SUN'],
datasets: [
{
label: 'This Week',
fill: true,
backgroundColor: 'rgba(73, 80, 87, .1)',
borderColor: 'rgba(73, 80, 87, .35)',
pointBackgroundColor: 'rgba(73, 80, 87, .5)',
pointBorderColor: '#fff',
pointHoverBackgroundColor: '#fff',
pointHoverBorderColor: 'rgba(73, 80, 87, .5)',
data: [14, 16, 6, 14, 10, 19, 12]
}
]
};
let chartCorporateSlimProjectsOptions = {
responsive: true,
maintainAspectRatio: false,
tension: .4,
scales: {
y: {
suggestedMin: 0,
suggestedMax: 22
}
},
interaction: {
intersect: false,
},
plugins: {
tooltip: {
callbacks: {
label: function (context) {
return ' ' + context.parsed.y + ' Sales';
}
}
}
}
};
let chartCorporateSlimTicketsData = {
labels: ['MON', 'TUE', 'WED', 'THU', 'FRI', 'SAT', 'SUN'],
datasets: [
{
label: 'This Week',
fill: true,
backgroundColor: 'rgba(130, 181, 75, .1)',
borderColor: 'rgba(130, 181, 75, .35)',
pointBackgroundColor: 'rgba(130, 181, 75, .5)',
pointBorderColor: '#fff',
pointHoverBackgroundColor: '#fff',
pointHoverBorderColor: 'rgba(130, 181, 75, .5)',
data: [35, 20, 29, 20, 40, 34, 45]
}
]
};
let chartCorporateSlimTicketsOptions = {
responsive: true,
maintainAspectRatio: false,
tension: .4,
scales: {
y: {
suggestedMin: 0,
suggestedMax: 50
}
},
interaction: {
intersect: false,
},
plugins: {
tooltip: {
callbacks: {
label: function (context) {
return ' ' + context.parsed.y + ' Tickets';
}
}
}
}
};
// Init Charts
if (chartCorporateSlimProjectsCon !== null) {
chartCorporateSlimProjects = new Chart(chartCorporateSlimProjectsCon, {
type: 'line',
data: chartCorporateSlimProjectsData,
options: chartCorporateSlimProjectsOptions
});
}
if (chartCorporateSlimTicketsCon !== null) {
chartCorporateSlimTickets = new Chart(chartCorporateSlimTicketsCon, {
type: 'line',
data: chartCorporateSlimTicketsData,
options: chartCorporateSlimTicketsOptions
});
}
}
/*
* Init functionality
*
*/
static init() {
this.initCorporateChartJS();
}
}
// Initialize when page loads
Dashmix.onLoad(() => DbCorporateSlim.init());

93
src/main/resources/static/assets/_js/pages/db_crypto.js

@ -0,0 +1,93 @@
/*
* Document : db_crypto.js
* Author : pixelcave
* Description: Custom JS code used in Crypto Dashboard Page
*/
// Chart.js Charts, for more examples you can check out http://www.chartjs.org/docs
class pageDashboardCrypto {
/*
* Init Charts
*
*/
static initChartsBitcoin() {
// Set Global Chart.js configuration
Chart.defaults.color = '#818d96';
Chart.defaults.scale.grid.color = 'transparent';
Chart.defaults.scale.grid.zeroLineColor = 'transparent';
Chart.defaults.scale.beginAtZero = true;
Chart.defaults.elements.point.radius = 0;
Chart.defaults.elements.point.hoverRadius = 0;
Chart.defaults.plugins.tooltip.radius = 3;
Chart.defaults.plugins.legend.display = false;
// Get Chart Container
let chartBitcoinCon = document.getElementById('js-chartjs-bitcoin');
// Set up labels
let chartBitcoinlabels = [];
for (let i = 0; i < 30; i++) {
chartBitcoinlabels[i] = (i === 29) ? '1 day ago' : (30 - i) + ' days ago';
}
// Crypto Data
let chartBitcoinData = [10500, 10400, 9500, 8268, 10218, 8250, 8707, 9284, 9718, 9950, 9879, 10147, 10883, 11071, 11332, 11584, 11878, 13540, 16501, 16007, 15142, 14869, 16762, 17276, 16808, 16678, 16771, 12900, 13100, 14000];
// Init Chart
if (chartBitcoinCon !== null) {
let chartBitcoin = new Chart(chartBitcoinCon, {
type: 'line',
data: {
labels: chartBitcoinlabels,
datasets: [
{
label: 'Bitcoin Price',
fill: true,
backgroundColor: 'rgba(255,193,7,.25)',
borderColor: 'rgba(255,193,7,1)',
pointBackgroundColor: 'rgba(255,193,7,1)',
pointBorderColor: '#fff',
pointHoverBackgroundColor: '#fff',
pointHoverBorderColor: 'rgba(255,193,7,1)',
data: chartBitcoinData
}
]
},
options: {
responsive: true,
maintainAspectRatio: false,
tension: .4,
scales: {
y: {
suggestedMin: 6000,
suggestedMax: 20000
}
},
interaction: {
intersect: false,
},
plugins: {
tooltip: {
callbacks: {
label: function (context) {
return ' $' + context.parsed.y;
}
}
}
}
}
});
}
}
/*
* Init functionality
*
*/
static init() {
this.initChartsBitcoin();
}
}
// Initialize when page loads
Dashmix.onLoad(() => pageDashboardCrypto.init());

42
src/main/resources/static/assets/_js/pages/op_auth_lock.js

@ -0,0 +1,42 @@
/*
* Document : op_auth_lock.js
* Author : pixelcave
* Description: Custom JS code used in Lock Page
*/
class pageAuthLock {
/*
* Init Lock Form Validation, for more examples you can check out https://github.com/jzaefferer/jquery-validation
*
*/
static initValidation() {
// Load default options for jQuery Validation plugin
Dashmix.helpers('jq-validation');
// Init Form Validation
jQuery('.js-validation-lock').validate({
rules: {
'lock-password': {
required: true,
minlength: 3
}
},
messages: {
'lock-password': {
required: 'Please enter your valid password'
}
}
});
}
/*
* Init functionality
*
*/
static init() {
this.initValidation();
}
}
// Initialize when page loads
Dashmix.onLoad(() => pageAuthLock.init());

42
src/main/resources/static/assets/_js/pages/op_auth_reminder.js

@ -0,0 +1,42 @@
/*
* Document : op_auth_reminder.js
* Author : pixelcave
* Description: Custom JS code used in Password Reminder Page
*/
class pageAuthReminder {
/*
* Init Password Reminder Form Validation, for more examples you can check out https://github.com/jzaefferer/jquery-validation
*
*/
static initValidation() {
// Load default options for jQuery Validation plugin
Dashmix.helpers('jq-validation');
// Init Form Validation
jQuery('.js-validation-reminder').validate({
rules: {
'reminder-credential': {
required: true,
minlength: 3
}
},
messages: {
'reminder-credential': {
required: 'Please enter a valid credential'
}
}
});
}
/*
* Init functionality
*
*/
static init() {
this.initValidation();
}
}
// Initialize when page loads
Dashmix.onLoad(() => pageAuthReminder.init());

51
src/main/resources/static/assets/_js/pages/op_auth_signin.js

@ -0,0 +1,51 @@
/*
* Document : op_auth_signin.js
* Author : pixelcave
* Description: Custom JS code used in Sign In Page
*/
class pageAuthSignIn {
/*
* Init Sign In Form Validation, for more examples you can check out https://github.com/jzaefferer/jquery-validation
*
*/
static initValidation() {
// Load default options for jQuery Validation plugin
Dashmix.helpers('jq-validation');
// Init Form Validation
jQuery('.js-validation-signin').validate({
rules: {
'login-username': {
required: true,
minlength: 3
},
'login-password': {
required: true,
minlength: 5
}
},
messages: {
'login-username': {
required: 'Please enter a username',
minlength: 'Your username must consist of at least 3 characters'
},
'login-password': {
required: 'Please provide a password',
minlength: 'Your password must be at least 5 characters long'
}
}
});
}
/*
* Init functionality
*
*/
static init() {
this.initValidation();
}
}
// Initialize when page loads
Dashmix.onLoad(() => pageAuthSignIn.init());

69
src/main/resources/static/assets/_js/pages/op_auth_signup.js

@ -0,0 +1,69 @@
/*
* Document : op_auth_signup.js
* Author : pixelcave
* Description: Custom JS code used in Sign Up Page
*/
class pageAuthSignUp {
/*
* Init Sign Up Form Validation, for more examples you can check out https://github.com/jzaefferer/jquery-validation
*
*/
static initValidation() {
// Load default options for jQuery Validation plugin
Dashmix.helpers('jq-validation');
// Init Form Validation
jQuery('.js-validation-signup').validate({
rules: {
'signup-username': {
required: true,
minlength: 3
},
'signup-email': {
required: true,
emailWithDot: true
},
'signup-password': {
required: true,
minlength: 5
},
'signup-password-confirm': {
required: true,
equalTo: '#signup-password'
},
'signup-terms': {
required: true
}
},
messages: {
'signup-username': {
required: 'Please enter a username',
minlength: 'Your username must consist of at least 3 characters'
},
'signup-email': 'Please enter a valid email address',
'signup-password': {
required: 'Please provide a password',
minlength: 'Your password must be at least 5 characters long'
},
'signup-password-confirm': {
required: 'Please provide a password',
minlength: 'Your password must be at least 5 characters long',
equalTo: 'Please enter the same password as above'
},
'signup-terms': 'You must agree to the service terms!'
}
});
}
/*
* Init functionality
*
*/
static init() {
this.initValidation();
}
}
// Initialize when page loads
Dashmix.onLoad(() => pageAuthSignUp.init());

34
src/main/resources/static/assets/_js/pages/op_coming_soon.js

@ -0,0 +1,34 @@
/*
* Document : op_coming_soon.js
* Author : pixelcave
* Description: Custom JS code used in Coming Soon Page
*/
class pageComingSoon {
/*
* Init Countdown.js, for more examples you can check out https://github.com/hilios/jQuery.countdown
*
*/
static countdown() {
jQuery('.js-countdown').countdown((new Date().getFullYear() + 2) + '/02/01', e => {
jQuery(e.currentTarget).html(e.strftime('<div class="row items-push push text-center">'
+ '<div class="col-6 col-md-3"><div class="fs-1 fw-bold text-white">%-D</div><div class="fs-sm fw-bold text-muted">DAYS</div></div>'
+ '<div class="col-6 col-md-3"><div class="fs-1 fw-bold text-white">%H</div><div class="fs-sm fw-bold text-muted">HOURS</div></div>'
+ '<div class="col-6 col-md-3"><div class="fs-1 fw-bold text-white">%M</div><div class="fs-sm fw-bold text-muted">MINUTES</div></div>'
+ '<div class="col-6 col-md-3"><div class="fs-1 fw-bold text-white">%S</div><div class="fs-sm fw-bold text-muted">SECONDS</div></div>'
+ '</div>'
));
});
}
/*
* Init functionality
*
*/
static init() {
this.countdown();
}
}
// Initialize when page loads
Dashmix.onLoad(() => pageComingSoon.init());

78
src/main/resources/static/assets/_js/pages/op_installation.js

@ -0,0 +1,78 @@
/*
* Document : op_installation.js
* Author : pixelcave
* Description: Custom JS code used in Installation Page
*/
// Form Validation, for more examples you can check out https://github.com/jzaefferer/jquery-validation
class pageInstallation {
/*
* Init Installation Form Validation
*
*/
static initValidationInstallation() {
// Load default options for jQuery Validation plugin
Dashmix.helpers('jq-validation');
// Init Form Validation
jQuery('.js-validation-installation').validate({
rules: {
'install-db-name': {
required: true
},
'install-db-username': {
required: true
},
'install-db-password': {
required: true
},
'install-admin-email': {
required: true,
emailWithDot: true
},
'install-admin-password': {
required: true,
minlength: 5
},
'install-admin-password-confirm': {
required: true,
equalTo: '#install-admin-password'
}
},
messages: {
'install-db-name': {
required: 'Please provide the name of your database'
},
'install-db-username': {
required: 'Please provide the username with access to your database'
},
'install-db-password': {
required: 'Please provide the password of your database user'
},
'install-admin-email': {
required: 'Please enter your email'
},
'install-admin-password': {
required: 'Please provide a password',
minlength: 'Your password must be at least 5 characters long'
},
'install-admin-password-confirm': {
required: 'Please provide a password',
minlength: 'Your password must be at least 5 characters long',
equalTo: 'Please enter the same password as above'
}
}
});
}
/*
* Init functionality
*
*/
static init() {
this.initValidationInstallation();
}
}
// Initialize when page loads
Dashmix.onLoad(() => pageInstallation.init());

149
src/main/resources/static/assets/_scss/bootstrap/_accordion.scss

@ -0,0 +1,149 @@
//
// Base styles
//
.accordion {
// scss-docs-start accordion-css-vars
--#{$prefix}accordion-color: #{$accordion-color};
--#{$prefix}accordion-bg: #{$accordion-bg};
--#{$prefix}accordion-transition: #{$accordion-transition};
--#{$prefix}accordion-border-color: #{$accordion-border-color};
--#{$prefix}accordion-border-width: #{$accordion-border-width};
--#{$prefix}accordion-border-radius: #{$accordion-border-radius};
--#{$prefix}accordion-inner-border-radius: #{$accordion-inner-border-radius};
--#{$prefix}accordion-btn-padding-x: #{$accordion-button-padding-x};
--#{$prefix}accordion-btn-padding-y: #{$accordion-button-padding-y};
--#{$prefix}accordion-btn-color: #{$accordion-button-color};
--#{$prefix}accordion-btn-bg: #{$accordion-button-bg};
--#{$prefix}accordion-btn-icon: #{escape-svg($accordion-button-icon)};
--#{$prefix}accordion-btn-icon-width: #{$accordion-icon-width};
--#{$prefix}accordion-btn-icon-transform: #{$accordion-icon-transform};
--#{$prefix}accordion-btn-icon-transition: #{$accordion-icon-transition};
--#{$prefix}accordion-btn-active-icon: #{escape-svg($accordion-button-active-icon)};
--#{$prefix}accordion-btn-focus-border-color: #{$accordion-button-focus-border-color};
--#{$prefix}accordion-btn-focus-box-shadow: #{$accordion-button-focus-box-shadow};
--#{$prefix}accordion-body-padding-x: #{$accordion-body-padding-x};
--#{$prefix}accordion-body-padding-y: #{$accordion-body-padding-y};
--#{$prefix}accordion-active-color: #{$accordion-button-active-color};
--#{$prefix}accordion-active-bg: #{$accordion-button-active-bg};
// scss-docs-end accordion-css-vars
}
.accordion-button {
position: relative;
display: flex;
align-items: center;
width: 100%;
padding: var(--#{$prefix}accordion-btn-padding-y) var(--#{$prefix}accordion-btn-padding-x);
@include font-size($font-size-base);
color: var(--#{$prefix}accordion-btn-color);
text-align: left; // Reset button style
background-color: var(--#{$prefix}accordion-btn-bg);
border: 0;
@include border-radius(0);
overflow-anchor: none;
@include transition(var(--#{$prefix}accordion-transition));
&:not(.collapsed) {
color: var(--#{$prefix}accordion-active-color);
background-color: var(--#{$prefix}accordion-active-bg);
box-shadow: inset 0 calc(-1 * var(--#{$prefix}accordion-border-width)) 0 var(--#{$prefix}accordion-border-color); // stylelint-disable-line function-disallowed-list
&::after {
background-image: var(--#{$prefix}accordion-btn-active-icon);
transform: var(--#{$prefix}accordion-btn-icon-transform);
}
}
// Accordion icon
&::after {
flex-shrink: 0;
width: var(--#{$prefix}accordion-btn-icon-width);
height: var(--#{$prefix}accordion-btn-icon-width);
margin-left: auto;
content: "";
background-image: var(--#{$prefix}accordion-btn-icon);
background-repeat: no-repeat;
background-size: var(--#{$prefix}accordion-btn-icon-width);
@include transition(var(--#{$prefix}accordion-btn-icon-transition));
}
&:hover {
z-index: 2;
}
&:focus {
z-index: 3;
border-color: var(--#{$prefix}accordion-btn-focus-border-color);
outline: 0;
box-shadow: var(--#{$prefix}accordion-btn-focus-box-shadow);
}
}
.accordion-header {
margin-bottom: 0;
}
.accordion-item {
color: var(--#{$prefix}accordion-color);
background-color: var(--#{$prefix}accordion-bg);
border: var(--#{$prefix}accordion-border-width) solid var(--#{$prefix}accordion-border-color);
&:first-of-type {
@include border-top-radius(var(--#{$prefix}accordion-border-radius));
.accordion-button {
@include border-top-radius(var(--#{$prefix}accordion-inner-border-radius));
}
}
&:not(:first-of-type) {
border-top: 0;
}
// Only set a border-radius on the last item if the accordion is collapsed
&:last-of-type {
@include border-bottom-radius(var(--#{$prefix}accordion-border-radius));
.accordion-button {
&.collapsed {
@include border-bottom-radius(var(--#{$prefix}accordion-inner-border-radius));
}
}
.accordion-collapse {
@include border-bottom-radius(var(--#{$prefix}accordion-border-radius));
}
}
}
.accordion-body {
padding: var(--#{$prefix}accordion-body-padding-y) var(--#{$prefix}accordion-body-padding-x);
}
// Flush accordion items
//
// Remove borders and border-radius to keep accordion items edge-to-edge.
.accordion-flush {
.accordion-collapse {
border-width: 0;
}
.accordion-item {
border-right: 0;
border-left: 0;
@include border-radius(0);
&:first-child { border-top: 0; }
&:last-child { border-bottom: 0; }
.accordion-button {
&,
&.collapsed {
@include border-radius(0);
}
}
}
}

71
src/main/resources/static/assets/_scss/bootstrap/_alert.scss

@ -0,0 +1,71 @@
//
// Base styles
//
.alert {
// scss-docs-start alert-css-vars
--#{$prefix}alert-bg: transparent;
--#{$prefix}alert-padding-x: #{$alert-padding-x};
--#{$prefix}alert-padding-y: #{$alert-padding-y};
--#{$prefix}alert-margin-bottom: #{$alert-margin-bottom};
--#{$prefix}alert-color: inherit;
--#{$prefix}alert-border-color: transparent;
--#{$prefix}alert-border: #{$alert-border-width} solid var(--#{$prefix}alert-border-color);
--#{$prefix}alert-border-radius: #{$alert-border-radius};
// scss-docs-end alert-css-vars
position: relative;
padding: var(--#{$prefix}alert-padding-y) var(--#{$prefix}alert-padding-x);
margin-bottom: var(--#{$prefix}alert-margin-bottom);
color: var(--#{$prefix}alert-color);
background-color: var(--#{$prefix}alert-bg);
border: var(--#{$prefix}alert-border);
@include border-radius(var(--#{$prefix}alert-border-radius));
}
// Headings for larger alerts
.alert-heading {
// Specified to prevent conflicts of changing $headings-color
color: inherit;
}
// Provide class for links that match alerts
.alert-link {
font-weight: $alert-link-font-weight;
}
// Dismissible alerts
//
// Expand the right padding and account for the close button's positioning.
.alert-dismissible {
padding-right: $alert-dismissible-padding-r;
// Adjust close link position
.btn-close {
position: absolute;
top: 0;
right: 0;
z-index: $stretched-link-z-index + 1;
padding: $alert-padding-y * 1.25 $alert-padding-x;
}
}
// scss-docs-start alert-modifiers
// Generate contextual modifier classes for colorizing the alert.
@each $state, $value in $theme-colors {
$alert-background: shift-color($value, $alert-bg-scale);
$alert-border: shift-color($value, $alert-border-scale);
$alert-color: shift-color($value, $alert-color-scale);
@if (contrast-ratio($alert-background, $alert-color) < $min-contrast-ratio) {
$alert-color: mix($value, color-contrast($alert-background), abs($alert-color-scale));
}
.alert-#{$state} {
@include alert-variant($alert-background, $alert-border, $alert-color);
}
}
// scss-docs-end alert-modifiers

38
src/main/resources/static/assets/_scss/bootstrap/_badge.scss

@ -0,0 +1,38 @@
// Base class
//
// Requires one of the contextual, color modifier classes for `color` and
// `background-color`.
.badge {
// scss-docs-start badge-css-vars
--#{$prefix}badge-padding-x: #{$badge-padding-x};
--#{$prefix}badge-padding-y: #{$badge-padding-y};
@include rfs($badge-font-size, --#{$prefix}badge-font-size);
--#{$prefix}badge-font-weight: #{$badge-font-weight};
--#{$prefix}badge-color: #{$badge-color};
--#{$prefix}badge-border-radius: #{$badge-border-radius};
// scss-docs-end badge-css-vars
display: inline-block;
padding: var(--#{$prefix}badge-padding-y) var(--#{$prefix}badge-padding-x);
@include font-size(var(--#{$prefix}badge-font-size));
font-weight: var(--#{$prefix}badge-font-weight);
line-height: 1;
color: var(--#{$prefix}badge-color);
text-align: center;
white-space: nowrap;
vertical-align: baseline;
@include border-radius(var(--#{$prefix}badge-border-radius));
@include gradient-bg();
// Empty badges collapse automatically
&:empty {
display: none;
}
}
// Quick fix for badges in buttons
.btn .badge {
position: relative;
top: -1px;
}

40
src/main/resources/static/assets/_scss/bootstrap/_breadcrumb.scss

@ -0,0 +1,40 @@
.breadcrumb {
// scss-docs-start breadcrumb-css-vars
--#{$prefix}breadcrumb-padding-x: #{$breadcrumb-padding-x};
--#{$prefix}breadcrumb-padding-y: #{$breadcrumb-padding-y};
--#{$prefix}breadcrumb-margin-bottom: #{$breadcrumb-margin-bottom};
@include rfs($breadcrumb-font-size, --#{$prefix}breadcrumb-font-size);
--#{$prefix}breadcrumb-bg: #{$breadcrumb-bg};
--#{$prefix}breadcrumb-border-radius: #{$breadcrumb-border-radius};
--#{$prefix}breadcrumb-divider-color: #{$breadcrumb-divider-color};
--#{$prefix}breadcrumb-item-padding-x: #{$breadcrumb-item-padding-x};
--#{$prefix}breadcrumb-item-active-color: #{$breadcrumb-active-color};
// scss-docs-end breadcrumb-css-vars
display: flex;
flex-wrap: wrap;
padding: var(--#{$prefix}breadcrumb-padding-y) var(--#{$prefix}breadcrumb-padding-x);
margin-bottom: var(--#{$prefix}breadcrumb-margin-bottom);
@include font-size(var(--#{$prefix}breadcrumb-font-size));
list-style: none;
background-color: var(--#{$prefix}breadcrumb-bg);
@include border-radius(var(--#{$prefix}breadcrumb-border-radius));
}
.breadcrumb-item {
// The separator between breadcrumbs (by default, a forward-slash: "/")
+ .breadcrumb-item {
padding-left: var(--#{$prefix}breadcrumb-item-padding-x);
&::before {
float: left; // Suppress inline spacings and underlining of the separator
padding-right: var(--#{$prefix}breadcrumb-item-padding-x);
color: var(--#{$prefix}breadcrumb-divider-color);
content: var(--#{$prefix}breadcrumb-divider, escape-svg($breadcrumb-divider)) #{"/* rtl:"} var(--#{$prefix}breadcrumb-divider, escape-svg($breadcrumb-divider-flipped)) #{"*/"};
}
}
&.active {
color: var(--#{$prefix}breadcrumb-item-active-color);
}
}

142
src/main/resources/static/assets/_scss/bootstrap/_button-group.scss

@ -0,0 +1,142 @@
// Make the div behave like a button
.btn-group,
.btn-group-vertical {
position: relative;
display: inline-flex;
vertical-align: middle; // match .btn alignment given font-size hack above
> .btn {
position: relative;
flex: 1 1 auto;
}
// Bring the hover, focused, and "active" buttons to the front to overlay
// the borders properly
> .btn-check:checked + .btn,
> .btn-check:focus + .btn,
> .btn:hover,
> .btn:focus,
> .btn:active,
> .btn.active {
z-index: 1;
}
}
// Optional: Group multiple button groups together for a toolbar
.btn-toolbar {
display: flex;
flex-wrap: wrap;
justify-content: flex-start;
.input-group {
width: auto;
}
}
.btn-group {
@include border-radius($btn-border-radius);
// Prevent double borders when buttons are next to each other
> :not(.btn-check:first-child) + .btn,
> .btn-group:not(:first-child) {
margin-left: -$btn-border-width;
}
// Reset rounded corners
> .btn:not(:last-child):not(.dropdown-toggle),
> .btn.dropdown-toggle-split:first-child,
> .btn-group:not(:last-child) > .btn {
@include border-end-radius(0);
}
// The left radius should be 0 if the button is:
// - the "third or more" child
// - the second child and the previous element isn't `.btn-check` (making it the first child visually)
// - part of a btn-group which isn't the first child
> .btn:nth-child(n + 3),
> :not(.btn-check) + .btn,
> .btn-group:not(:first-child) > .btn {
@include border-start-radius(0);
}
}
// Sizing
//
// Remix the default button sizing classes into new ones for easier manipulation.
.btn-group-sm > .btn { @extend .btn-sm; }
.btn-group-lg > .btn { @extend .btn-lg; }
//
// Split button dropdowns
//
.dropdown-toggle-split {
padding-right: $btn-padding-x * .75;
padding-left: $btn-padding-x * .75;
&::after,
.dropup &::after,
.dropend &::after {
margin-left: 0;
}
.dropstart &::before {
margin-right: 0;
}
}
.btn-sm + .dropdown-toggle-split {
padding-right: $btn-padding-x-sm * .75;
padding-left: $btn-padding-x-sm * .75;
}
.btn-lg + .dropdown-toggle-split {
padding-right: $btn-padding-x-lg * .75;
padding-left: $btn-padding-x-lg * .75;
}
// The clickable button for toggling the menu
// Set the same inset shadow as the :active state
.btn-group.show .dropdown-toggle {
@include box-shadow($btn-active-box-shadow);
// Show no shadow for `.btn-link` since it has no other button styles.
&.btn-link {
@include box-shadow(none);
}
}
//
// Vertical button groups
//
.btn-group-vertical {
flex-direction: column;
align-items: flex-start;
justify-content: center;
> .btn,
> .btn-group {
width: 100%;
}
> .btn:not(:first-child),
> .btn-group:not(:first-child) {
margin-top: -$btn-border-width;
}
// Reset rounded corners
> .btn:not(:last-child):not(.dropdown-toggle),
> .btn-group:not(:last-child) > .btn {
@include border-bottom-radius(0);
}
> .btn ~ .btn,
> .btn-group:not(:first-child) > .btn {
@include border-top-radius(0);
}
}

207
src/main/resources/static/assets/_scss/bootstrap/_buttons.scss

@ -0,0 +1,207 @@
//
// Base styles
//
.btn {
// scss-docs-start btn-css-vars
--#{$prefix}btn-padding-x: #{$btn-padding-x};
--#{$prefix}btn-padding-y: #{$btn-padding-y};
--#{$prefix}btn-font-family: #{$btn-font-family};
@include rfs($btn-font-size, --#{$prefix}btn-font-size);
--#{$prefix}btn-font-weight: #{$btn-font-weight};
--#{$prefix}btn-line-height: #{$btn-line-height};
--#{$prefix}btn-color: #{$body-color};
--#{$prefix}btn-bg: transparent;
--#{$prefix}btn-border-width: #{$btn-border-width};
--#{$prefix}btn-border-color: transparent;
--#{$prefix}btn-border-radius: #{$btn-border-radius};
--#{$prefix}btn-hover-border-color: transparent;
--#{$prefix}btn-box-shadow: #{$btn-box-shadow};
--#{$prefix}btn-disabled-opacity: #{$btn-disabled-opacity};
--#{$prefix}btn-focus-box-shadow: 0 0 0 #{$btn-focus-width} rgba(var(--#{$prefix}btn-focus-shadow-rgb), .5);
// scss-docs-end btn-css-vars
display: inline-block;
padding: var(--#{$prefix}btn-padding-y) var(--#{$prefix}btn-padding-x);
font-family: var(--#{$prefix}btn-font-family);
@include font-size(var(--#{$prefix}btn-font-size));
font-weight: var(--#{$prefix}btn-font-weight);
line-height: var(--#{$prefix}btn-line-height);
color: var(--#{$prefix}btn-color);
text-align: center;
text-decoration: if($link-decoration == none, null, none);
white-space: $btn-white-space;
vertical-align: middle;
cursor: if($enable-button-pointers, pointer, null);
user-select: none;
border: var(--#{$prefix}btn-border-width) solid var(--#{$prefix}btn-border-color);
@include border-radius(var(--#{$prefix}btn-border-radius));
@include gradient-bg(var(--#{$prefix}btn-bg));
@include box-shadow(var(--#{$prefix}btn-box-shadow));
@include transition($btn-transition);
&:hover {
color: var(--#{$prefix}btn-hover-color);
text-decoration: if($link-hover-decoration == underline, none, null);
background-color: var(--#{$prefix}btn-hover-bg);
border-color: var(--#{$prefix}btn-hover-border-color);
}
.btn-check + &:hover {
// override for the checkbox/radio buttons
color: var(--#{$prefix}btn-color);
background-color: var(--#{$prefix}btn-bg);
border-color: var(--#{$prefix}btn-border-color);
}
&:focus-visible {
color: var(--#{$prefix}btn-hover-color);
@include gradient-bg(var(--#{$prefix}btn-hover-bg));
border-color: var(--#{$prefix}btn-hover-border-color);
outline: 0;
// Avoid using mixin so we can pass custom focus shadow properly
@if $enable-shadows {
box-shadow: var(--#{$prefix}btn-box-shadow), var(--#{$prefix}btn-focus-box-shadow);
} @else {
box-shadow: var(--#{$prefix}btn-focus-box-shadow);
}
}
.btn-check:focus-visible + & {
border-color: var(--#{$prefix}btn-hover-border-color);
outline: 0;
// Avoid using mixin so we can pass custom focus shadow properly
@if $enable-shadows {
box-shadow: var(--#{$prefix}btn-box-shadow), var(--#{$prefix}btn-focus-box-shadow);
} @else {
box-shadow: var(--#{$prefix}btn-focus-box-shadow);
}
}
.btn-check:checked + &,
:not(.btn-check) + &:active,
&:first-child:active,
&.active,
&.show {
color: var(--#{$prefix}btn-active-color);
background-color: var(--#{$prefix}btn-active-bg);
// Remove CSS gradients if they're enabled
background-image: if($enable-gradients, none, null);
border-color: var(--#{$prefix}btn-active-border-color);
@include box-shadow(var(--#{$prefix}btn-active-shadow));
&:focus-visible {
// Avoid using mixin so we can pass custom focus shadow properly
@if $enable-shadows {
box-shadow: var(--#{$prefix}btn-active-shadow), var(--#{$prefix}btn-focus-box-shadow);
} @else {
box-shadow: var(--#{$prefix}btn-focus-box-shadow);
}
}
}
&:disabled,
&.disabled,
fieldset:disabled & {
color: var(--#{$prefix}btn-disabled-color);
pointer-events: none;
background-color: var(--#{$prefix}btn-disabled-bg);
background-image: if($enable-gradients, none, null);
border-color: var(--#{$prefix}btn-disabled-border-color);
opacity: var(--#{$prefix}btn-disabled-opacity);
@include box-shadow(none);
}
}
//
// Alternate buttons
//
// scss-docs-start btn-variant-loops
@each $color, $value in $theme-colors {
.btn-#{$color} {
@if $color == "light" {
@include button-variant(
$value,
$value,
$hover-background: shade-color($value, $btn-hover-bg-shade-amount),
$hover-border: shade-color($value, $btn-hover-border-shade-amount),
$active-background: shade-color($value, $btn-active-bg-shade-amount),
$active-border: shade-color($value, $btn-active-border-shade-amount)
);
} @else if $color == "dark" {
@include button-variant(
$value,
$value,
$hover-background: tint-color($value, $btn-hover-bg-tint-amount),
$hover-border: tint-color($value, $btn-hover-border-tint-amount),
$active-background: tint-color($value, $btn-active-bg-tint-amount),
$active-border: tint-color($value, $btn-active-border-tint-amount)
);
} @else {
@include button-variant($value, $value);
}
}
}
@each $color, $value in $theme-colors {
.btn-outline-#{$color} {
@include button-outline-variant($value);
}
}
// scss-docs-end btn-variant-loops
//
// Link buttons
//
// Make a button look and behave like a link
.btn-link {
--#{$prefix}btn-font-weight: #{$font-weight-normal};
--#{$prefix}btn-color: #{$btn-link-color};
--#{$prefix}btn-bg: transparent;
--#{$prefix}btn-border-color: transparent;
--#{$prefix}btn-hover-color: #{$btn-link-hover-color};
--#{$prefix}btn-hover-border-color: transparent;
--#{$prefix}btn-active-color: #{$btn-link-hover-color};
--#{$prefix}btn-active-border-color: transparent;
--#{$prefix}btn-disabled-color: #{$btn-link-disabled-color};
--#{$prefix}btn-disabled-border-color: transparent;
--#{$prefix}btn-box-shadow: none;
--#{$prefix}btn-focus-shadow-rgb: #{to-rgb(mix(color-contrast($primary), $primary, 15%))};
text-decoration: $link-decoration;
@if $enable-gradients {
background-image: none;
}
&:hover,
&:focus-visible {
text-decoration: $link-hover-decoration;
}
&:focus-visible {
color: var(--#{$prefix}btn-color);
}
&:hover {
color: var(--#{$prefix}btn-hover-color);
}
// No need for an active state here
}
//
// Button Sizes
//
.btn-lg {
@include button-size($btn-padding-y-lg, $btn-padding-x-lg, $btn-font-size-lg, $btn-border-radius-lg);
}
.btn-sm {
@include button-size($btn-padding-y-sm, $btn-padding-x-sm, $btn-font-size-sm, $btn-border-radius-sm);
}

234
src/main/resources/static/assets/_scss/bootstrap/_card.scss

@ -0,0 +1,234 @@
//
// Base styles
//
.card {
// scss-docs-start card-css-vars
--#{$prefix}card-spacer-y: #{$card-spacer-y};
--#{$prefix}card-spacer-x: #{$card-spacer-x};
--#{$prefix}card-title-spacer-y: #{$card-title-spacer-y};
--#{$prefix}card-border-width: #{$card-border-width};
--#{$prefix}card-border-color: #{$card-border-color};
--#{$prefix}card-border-radius: #{$card-border-radius};
--#{$prefix}card-box-shadow: #{$card-box-shadow};
--#{$prefix}card-inner-border-radius: #{$card-inner-border-radius};
--#{$prefix}card-cap-padding-y: #{$card-cap-padding-y};
--#{$prefix}card-cap-padding-x: #{$card-cap-padding-x};
--#{$prefix}card-cap-bg: #{$card-cap-bg};
--#{$prefix}card-cap-color: #{$card-cap-color};
--#{$prefix}card-height: #{$card-height};
--#{$prefix}card-color: #{$card-color};
--#{$prefix}card-bg: #{$card-bg};
--#{$prefix}card-img-overlay-padding: #{$card-img-overlay-padding};
--#{$prefix}card-group-margin: #{$card-group-margin};
// scss-docs-end card-css-vars
position: relative;
display: flex;
flex-direction: column;
min-width: 0; // See https://github.com/twbs/bootstrap/pull/22740#issuecomment-305868106
height: var(--#{$prefix}card-height);
word-wrap: break-word;
background-color: var(--#{$prefix}card-bg);
background-clip: border-box;
border: var(--#{$prefix}card-border-width) solid var(--#{$prefix}card-border-color);
@include border-radius(var(--#{$prefix}card-border-radius));
@include box-shadow(var(--#{$prefix}card-box-shadow));
> hr {
margin-right: 0;
margin-left: 0;
}
> .list-group {
border-top: inherit;
border-bottom: inherit;
&:first-child {
border-top-width: 0;
@include border-top-radius(var(--#{$prefix}card-inner-border-radius));
}
&:last-child {
border-bottom-width: 0;
@include border-bottom-radius(var(--#{$prefix}card-inner-border-radius));
}
}
// Due to specificity of the above selector (`.card > .list-group`), we must
// use a child selector here to prevent double borders.
> .card-header + .list-group,
> .list-group + .card-footer {
border-top: 0;
}
}
.card-body {
// Enable `flex-grow: 1` for decks and groups so that card blocks take up
// as much space as possible, ensuring footers are aligned to the bottom.
flex: 1 1 auto;
padding: var(--#{$prefix}card-spacer-y) var(--#{$prefix}card-spacer-x);
color: var(--#{$prefix}card-color);
}
.card-title {
margin-bottom: var(--#{$prefix}card-title-spacer-y);
}
.card-subtitle {
margin-top: calc(-.5 * var(--#{$prefix}card-title-spacer-y)); // stylelint-disable-line function-disallowed-list
margin-bottom: 0;
}
.card-text:last-child {
margin-bottom: 0;
}
.card-link {
&:hover {
text-decoration: if($link-hover-decoration == underline, none, null);
}
+ .card-link {
margin-left: var(--#{$prefix}card-spacer-x);
}
}
//
// Optional textual caps
//
.card-header {
padding: var(--#{$prefix}card-cap-padding-y) var(--#{$prefix}card-cap-padding-x);
margin-bottom: 0; // Removes the default margin-bottom of <hN>
color: var(--#{$prefix}card-cap-color);
background-color: var(--#{$prefix}card-cap-bg);
border-bottom: var(--#{$prefix}card-border-width) solid var(--#{$prefix}card-border-color);
&:first-child {
@include border-radius(var(--#{$prefix}card-inner-border-radius) var(--#{$prefix}card-inner-border-radius) 0 0);
}
}
.card-footer {
padding: var(--#{$prefix}card-cap-padding-y) var(--#{$prefix}card-cap-padding-x);
color: var(--#{$prefix}card-cap-color);
background-color: var(--#{$prefix}card-cap-bg);
border-top: var(--#{$prefix}card-border-width) solid var(--#{$prefix}card-border-color);
&:last-child {
@include border-radius(0 0 var(--#{$prefix}card-inner-border-radius) var(--#{$prefix}card-inner-border-radius));
}
}
//
// Header navs
//
.card-header-tabs {
margin-right: calc(-.5 * var(--#{$prefix}card-cap-padding-x)); // stylelint-disable-line function-disallowed-list
margin-bottom: calc(-1 * var(--#{$prefix}card-cap-padding-y)); // stylelint-disable-line function-disallowed-list
margin-left: calc(-.5 * var(--#{$prefix}card-cap-padding-x)); // stylelint-disable-line function-disallowed-list
border-bottom: 0;
.nav-link.active {
background-color: var(--#{$prefix}card-bg);
border-bottom-color: var(--#{$prefix}card-bg);
}
}
.card-header-pills {
margin-right: calc(-.5 * var(--#{$prefix}card-cap-padding-x)); // stylelint-disable-line function-disallowed-list
margin-left: calc(-.5 * var(--#{$prefix}card-cap-padding-x)); // stylelint-disable-line function-disallowed-list
}
// Card image
.card-img-overlay {
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
padding: var(--#{$prefix}card-img-overlay-padding);
@include border-radius(var(--#{$prefix}card-inner-border-radius));
}
.card-img,
.card-img-top,
.card-img-bottom {
width: 100%; // Required because we use flexbox and this inherently applies align-self: stretch
}
.card-img,
.card-img-top {
@include border-top-radius(var(--#{$prefix}card-inner-border-radius));
}
.card-img,
.card-img-bottom {
@include border-bottom-radius(var(--#{$prefix}card-inner-border-radius));
}
//
// Card groups
//
.card-group {
// The child selector allows nested `.card` within `.card-group`
// to display properly.
> .card {
margin-bottom: var(--#{$prefix}card-group-margin);
}
@include media-breakpoint-up(sm) {
display: flex;
flex-flow: row wrap;
// The child selector allows nested `.card` within `.card-group`
// to display properly.
> .card {
// Flexbugs #4: https://github.com/philipwalton/flexbugs#flexbug-4
flex: 1 0 0%;
margin-bottom: 0;
+ .card {
margin-left: 0;
border-left: 0;
}
// Handle rounded corners
@if $enable-rounded {
&:not(:last-child) {
@include border-end-radius(0);
.card-img-top,
.card-header {
// stylelint-disable-next-line property-disallowed-list
border-top-right-radius: 0;
}
.card-img-bottom,
.card-footer {
// stylelint-disable-next-line property-disallowed-list
border-bottom-right-radius: 0;
}
}
&:not(:first-child) {
@include border-start-radius(0);
.card-img-top,
.card-header {
// stylelint-disable-next-line property-disallowed-list
border-top-left-radius: 0;
}
.card-img-bottom,
.card-footer {
// stylelint-disable-next-line property-disallowed-list
border-bottom-left-radius: 0;
}
}
}
}
}
}

226
src/main/resources/static/assets/_scss/bootstrap/_carousel.scss

@ -0,0 +1,226 @@
// Notes on the classes:
//
// 1. .carousel.pointer-event should ideally be pan-y (to allow for users to scroll vertically)
// even when their scroll action started on a carousel, but for compatibility (with Firefox)
// we're preventing all actions instead
// 2. The .carousel-item-start and .carousel-item-end is used to indicate where
// the active slide is heading.
// 3. .active.carousel-item is the current slide.
// 4. .active.carousel-item-start and .active.carousel-item-end is the current
// slide in its in-transition state. Only one of these occurs at a time.
// 5. .carousel-item-next.carousel-item-start and .carousel-item-prev.carousel-item-end
// is the upcoming slide in transition.
.carousel {
position: relative;
}
.carousel.pointer-event {
touch-action: pan-y;
}
.carousel-inner {
position: relative;
width: 100%;
overflow: hidden;
@include clearfix();
}
.carousel-item {
position: relative;
display: none;
float: left;
width: 100%;
margin-right: -100%;
backface-visibility: hidden;
@include transition($carousel-transition);
}
.carousel-item.active,
.carousel-item-next,
.carousel-item-prev {
display: block;
}
.carousel-item-next:not(.carousel-item-start),
.active.carousel-item-end {
transform: translateX(100%);
}
.carousel-item-prev:not(.carousel-item-end),
.active.carousel-item-start {
transform: translateX(-100%);
}
//
// Alternate transitions
//
.carousel-fade {
.carousel-item {
opacity: 0;
transition-property: opacity;
transform: none;
}
.carousel-item.active,
.carousel-item-next.carousel-item-start,
.carousel-item-prev.carousel-item-end {
z-index: 1;
opacity: 1;
}
.active.carousel-item-start,
.active.carousel-item-end {
z-index: 0;
opacity: 0;
@include transition(opacity 0s $carousel-transition-duration);
}
}
//
// Left/right controls for nav
//
.carousel-control-prev,
.carousel-control-next {
position: absolute;
top: 0;
bottom: 0;
z-index: 1;
// Use flex for alignment (1-3)
display: flex; // 1. allow flex styles
align-items: center; // 2. vertically center contents
justify-content: center; // 3. horizontally center contents
width: $carousel-control-width;
padding: 0;
color: $carousel-control-color;
text-align: center;
background: none;
border: 0;
opacity: $carousel-control-opacity;
@include transition($carousel-control-transition);
// Hover/focus state
&:hover,
&:focus {
color: $carousel-control-color;
text-decoration: none;
outline: 0;
opacity: $carousel-control-hover-opacity;
}
}
.carousel-control-prev {
left: 0;
background-image: if($enable-gradients, linear-gradient(90deg, rgba($black, .25), rgba($black, .001)), null);
}
.carousel-control-next {
right: 0;
background-image: if($enable-gradients, linear-gradient(270deg, rgba($black, .25), rgba($black, .001)), null);
}
// Icons for within
.carousel-control-prev-icon,
.carousel-control-next-icon {
display: inline-block;
width: $carousel-control-icon-width;
height: $carousel-control-icon-width;
background-repeat: no-repeat;
background-position: 50%;
background-size: 100% 100%;
}
/* rtl:options: {
"autoRename": true,
"stringMap":[ {
"name" : "prev-next",
"search" : "prev",
"replace" : "next"
} ]
} */
.carousel-control-prev-icon {
background-image: escape-svg($carousel-control-prev-icon-bg);
}
.carousel-control-next-icon {
background-image: escape-svg($carousel-control-next-icon-bg);
}
// Optional indicator pips/controls
//
// Add a container (such as a list) with the following class and add an item (ideally a focusable control,
// like a button) with data-bs-target for each slide your carousel holds.
.carousel-indicators {
position: absolute;
right: 0;
bottom: 0;
left: 0;
z-index: 2;
display: flex;
justify-content: center;
padding: 0;
// Use the .carousel-control's width as margin so we don't overlay those
margin-right: $carousel-control-width;
margin-bottom: 1rem;
margin-left: $carousel-control-width;
list-style: none;
[data-bs-target] {
box-sizing: content-box;
flex: 0 1 auto;
width: $carousel-indicator-width;
height: $carousel-indicator-height;
padding: 0;
margin-right: $carousel-indicator-spacer;
margin-left: $carousel-indicator-spacer;
text-indent: -999px;
cursor: pointer;
background-color: $carousel-indicator-active-bg;
background-clip: padding-box;
border: 0;
// Use transparent borders to increase the hit area by 10px on top and bottom.
border-top: $carousel-indicator-hit-area-height solid transparent;
border-bottom: $carousel-indicator-hit-area-height solid transparent;
opacity: $carousel-indicator-opacity;
@include transition($carousel-indicator-transition);
}
.active {
opacity: $carousel-indicator-active-opacity;
}
}
// Optional captions
//
//
.carousel-caption {
position: absolute;
right: (100% - $carousel-caption-width) * .5;
bottom: $carousel-caption-spacer;
left: (100% - $carousel-caption-width) * .5;
padding-top: $carousel-caption-padding-y;
padding-bottom: $carousel-caption-padding-y;
color: $carousel-caption-color;
text-align: center;
}
// Dark mode carousel
.carousel-dark {
.carousel-control-prev-icon,
.carousel-control-next-icon {
filter: $carousel-dark-control-icon-filter;
}
.carousel-indicators [data-bs-target] {
background-color: $carousel-dark-indicator-active-bg;
}
.carousel-caption {
color: $carousel-dark-caption-color;
}
}

40
src/main/resources/static/assets/_scss/bootstrap/_close.scss

@ -0,0 +1,40 @@
// Transparent background and border properties included for button version.
// iOS requires the button element instead of an anchor tag.
// If you want the anchor version, it requires `href="#"`.
// See https://developer.mozilla.org/en-US/docs/Web/Events/click#Safari_Mobile
.btn-close {
box-sizing: content-box;
width: $btn-close-width;
height: $btn-close-height;
padding: $btn-close-padding-y $btn-close-padding-x;
color: $btn-close-color;
background: transparent escape-svg($btn-close-bg) center / $btn-close-width auto no-repeat; // include transparent for button elements
border: 0; // for button elements
@include border-radius();
opacity: $btn-close-opacity;
// Override <a>'s hover style
&:hover {
color: $btn-close-color;
text-decoration: none;
opacity: $btn-close-hover-opacity;
}
&:focus {
outline: 0;
box-shadow: $btn-close-focus-shadow;
opacity: $btn-close-focus-opacity;
}
&:disabled,
&.disabled {
pointer-events: none;
user-select: none;
opacity: $btn-close-disabled-opacity;
}
}
.btn-close-white {
filter: $btn-close-white-filter;
}

41
src/main/resources/static/assets/_scss/bootstrap/_containers.scss

@ -0,0 +1,41 @@
// Container widths
//
// Set the container width, and override it for fixed navbars in media queries.
@if $enable-container-classes {
// Single container class with breakpoint max-widths
.container,
// 100% wide container at all breakpoints
.container-fluid {
@include make-container();
}
// Responsive containers that are 100% wide until a breakpoint
@each $breakpoint, $container-max-width in $container-max-widths {
.container-#{$breakpoint} {
@extend .container-fluid;
}
@include media-breakpoint-up($breakpoint, $grid-breakpoints) {
%responsive-container-#{$breakpoint} {
max-width: $container-max-width;
}
// Extend each breakpoint which is smaller or equal to the current breakpoint
$extend-breakpoint: true;
@each $name, $width in $grid-breakpoints {
@if ($extend-breakpoint) {
.container#{breakpoint-infix($name, $grid-breakpoints)} {
@extend %responsive-container-#{$breakpoint};
}
// Once the current breakpoint is reached, stop extending
@if ($breakpoint == $name) {
$extend-breakpoint: false;
}
}
}
}
}
}

249
src/main/resources/static/assets/_scss/bootstrap/_dropdown.scss

@ -0,0 +1,249 @@
// The dropdown wrapper (`<div>`)
.dropup,
.dropend,
.dropdown,
.dropstart,
.dropup-center,
.dropdown-center {
position: relative;
}
.dropdown-toggle {
white-space: nowrap;
// Generate the caret automatically
@include caret();
}
// The dropdown menu
.dropdown-menu {
// scss-docs-start dropdown-css-vars
--#{$prefix}dropdown-zindex: #{$zindex-dropdown};
--#{$prefix}dropdown-min-width: #{$dropdown-min-width};
--#{$prefix}dropdown-padding-x: #{$dropdown-padding-x};
--#{$prefix}dropdown-padding-y: #{$dropdown-padding-y};
--#{$prefix}dropdown-spacer: #{$dropdown-spacer};
@include rfs($dropdown-font-size, --#{$prefix}dropdown-font-size);
--#{$prefix}dropdown-color: #{$dropdown-color};
--#{$prefix}dropdown-bg: #{$dropdown-bg};
--#{$prefix}dropdown-border-color: #{$dropdown-border-color};
--#{$prefix}dropdown-border-radius: #{$dropdown-border-radius};
--#{$prefix}dropdown-border-width: #{$dropdown-border-width};
--#{$prefix}dropdown-inner-border-radius: #{$dropdown-inner-border-radius};
--#{$prefix}dropdown-divider-bg: #{$dropdown-divider-bg};
--#{$prefix}dropdown-divider-margin-y: #{$dropdown-divider-margin-y};
--#{$prefix}dropdown-box-shadow: #{$dropdown-box-shadow};
--#{$prefix}dropdown-link-color: #{$dropdown-link-color};
--#{$prefix}dropdown-link-hover-color: #{$dropdown-link-hover-color};
--#{$prefix}dropdown-link-hover-bg: #{$dropdown-link-hover-bg};
--#{$prefix}dropdown-link-active-color: #{$dropdown-link-active-color};
--#{$prefix}dropdown-link-active-bg: #{$dropdown-link-active-bg};
--#{$prefix}dropdown-link-disabled-color: #{$dropdown-link-disabled-color};
--#{$prefix}dropdown-item-padding-x: #{$dropdown-item-padding-x};
--#{$prefix}dropdown-item-padding-y: #{$dropdown-item-padding-y};
--#{$prefix}dropdown-header-color: #{$dropdown-header-color};
--#{$prefix}dropdown-header-padding-x: #{$dropdown-header-padding-x};
--#{$prefix}dropdown-header-padding-y: #{$dropdown-header-padding-y};
// scss-docs-end dropdown-css-vars
position: absolute;
z-index: var(--#{$prefix}dropdown-zindex);
display: none; // none by default, but block on "open" of the menu
min-width: var(--#{$prefix}dropdown-min-width);
padding: var(--#{$prefix}dropdown-padding-y) var(--#{$prefix}dropdown-padding-x);
margin: 0; // Override default margin of ul
@include font-size(var(--#{$prefix}dropdown-font-size));
color: var(--#{$prefix}dropdown-color);
text-align: left; // Ensures proper alignment if parent has it changed (e.g., modal footer)
list-style: none;
background-color: var(--#{$prefix}dropdown-bg);
background-clip: padding-box;
border: var(--#{$prefix}dropdown-border-width) solid var(--#{$prefix}dropdown-border-color);
@include border-radius(var(--#{$prefix}dropdown-border-radius));
@include box-shadow(var(--#{$prefix}dropdown-box-shadow));
&[data-bs-popper] {
top: 100%;
left: 0;
margin-top: var(--#{$prefix}dropdown-spacer);
}
@if $dropdown-padding-y == 0 {
> .dropdown-item:first-child,
> li:first-child .dropdown-item {
@include border-top-radius(var(--#{$prefix}dropdown-inner-border-radius));
}
> .dropdown-item:last-child,
> li:last-child .dropdown-item {
@include border-bottom-radius(var(--#{$prefix}dropdown-inner-border-radius));
}
}
}
// scss-docs-start responsive-breakpoints
// We deliberately hardcode the `bs-` prefix because we check
// this custom property in JS to determine Popper's positioning
@each $breakpoint in map-keys($grid-breakpoints) {
@include media-breakpoint-up($breakpoint) {
$infix: breakpoint-infix($breakpoint, $grid-breakpoints);
.dropdown-menu#{$infix}-start {
--bs-position: start;
&[data-bs-popper] {
right: auto;
left: 0;
}
}
.dropdown-menu#{$infix}-end {
--bs-position: end;
&[data-bs-popper] {
right: 0;
left: auto;
}
}
}
}
// scss-docs-end responsive-breakpoints
// Allow for dropdowns to go bottom up (aka, dropup-menu)
// Just add .dropup after the standard .dropdown class and you're set.
.dropup {
.dropdown-menu[data-bs-popper] {
top: auto;
bottom: 100%;
margin-top: 0;
margin-bottom: var(--#{$prefix}dropdown-spacer);
}
.dropdown-toggle {
@include caret(up);
}
}
.dropend {
.dropdown-menu[data-bs-popper] {
top: 0;
right: auto;
left: 100%;
margin-top: 0;
margin-left: var(--#{$prefix}dropdown-spacer);
}
.dropdown-toggle {
@include caret(end);
&::after {
vertical-align: 0;
}
}
}
.dropstart {
.dropdown-menu[data-bs-popper] {
top: 0;
right: 100%;
left: auto;
margin-top: 0;
margin-right: var(--#{$prefix}dropdown-spacer);
}
.dropdown-toggle {
@include caret(start);
&::before {
vertical-align: 0;
}
}
}
// Dividers (basically an `<hr>`) within the dropdown
.dropdown-divider {
height: 0;
margin: var(--#{$prefix}dropdown-divider-margin-y) 0;
overflow: hidden;
border-top: 1px solid var(--#{$prefix}dropdown-divider-bg);
opacity: 1; // Revisit in v6 to de-dupe styles that conflict with <hr> element
}
// Links, buttons, and more within the dropdown menu
//
// `<button>`-specific styles are denoted with `// For <button>s`
.dropdown-item {
display: block;
width: 100%; // For `<button>`s
padding: var(--#{$prefix}dropdown-item-padding-y) var(--#{$prefix}dropdown-item-padding-x);
clear: both;
font-weight: $font-weight-normal;
color: var(--#{$prefix}dropdown-link-color);
text-align: inherit; // For `<button>`s
text-decoration: if($link-decoration == none, null, none);
white-space: nowrap; // prevent links from randomly breaking onto new lines
background-color: transparent; // For `<button>`s
border: 0; // For `<button>`s
&:hover,
&:focus {
color: var(--#{$prefix}dropdown-link-hover-color);
text-decoration: if($link-hover-decoration == underline, none, null);
@include gradient-bg(var(--#{$prefix}dropdown-link-hover-bg));
}
&.active,
&:active {
color: var(--#{$prefix}dropdown-link-active-color);
text-decoration: none;
@include gradient-bg(var(--#{$prefix}dropdown-link-active-bg));
}
&.disabled,
&:disabled {
color: var(--#{$prefix}dropdown-link-disabled-color);
pointer-events: none;
background-color: transparent;
// Remove CSS gradients if they're enabled
background-image: if($enable-gradients, none, null);
}
}
.dropdown-menu.show {
display: block;
}
// Dropdown section headers
.dropdown-header {
display: block;
padding: var(--#{$prefix}dropdown-header-padding-y) var(--#{$prefix}dropdown-header-padding-x);
margin-bottom: 0; // for use with heading elements
@include font-size($font-size-sm);
color: var(--#{$prefix}dropdown-header-color);
white-space: nowrap; // as with > li > a
}
// Dropdown text
.dropdown-item-text {
display: block;
padding: var(--#{$prefix}dropdown-item-padding-y) var(--#{$prefix}dropdown-item-padding-x);
color: var(--#{$prefix}dropdown-link-color);
}
// Dark dropdowns
.dropdown-menu-dark {
// scss-docs-start dropdown-dark-css-vars
--#{$prefix}dropdown-color: #{$dropdown-dark-color};
--#{$prefix}dropdown-bg: #{$dropdown-dark-bg};
--#{$prefix}dropdown-border-color: #{$dropdown-dark-border-color};
--#{$prefix}dropdown-box-shadow: #{$dropdown-dark-box-shadow};
--#{$prefix}dropdown-link-color: #{$dropdown-dark-link-color};
--#{$prefix}dropdown-link-hover-color: #{$dropdown-dark-link-hover-color};
--#{$prefix}dropdown-divider-bg: #{$dropdown-dark-divider-bg};
--#{$prefix}dropdown-link-hover-bg: #{$dropdown-dark-link-hover-bg};
--#{$prefix}dropdown-link-active-color: #{$dropdown-dark-link-active-color};
--#{$prefix}dropdown-link-active-bg: #{$dropdown-dark-link-active-bg};
--#{$prefix}dropdown-link-disabled-color: #{$dropdown-dark-link-disabled-color};
--#{$prefix}dropdown-header-color: #{$dropdown-dark-header-color};
// scss-docs-end dropdown-dark-css-vars
}

9
src/main/resources/static/assets/_scss/bootstrap/_forms.scss

@ -0,0 +1,9 @@
@import "forms/labels";
@import "forms/form-text";
@import "forms/form-control";
@import "forms/form-select";
@import "forms/form-check";
@import "forms/form-range";
@import "forms/floating-labels";
@import "forms/input-group";
@import "forms/validation";

302
src/main/resources/static/assets/_scss/bootstrap/_functions.scss

@ -0,0 +1,302 @@
// Bootstrap functions
//
// Utility mixins and functions for evaluating source code across our variables, maps, and mixins.
// Ascending
// Used to evaluate Sass maps like our grid breakpoints.
@mixin _assert-ascending($map, $map-name) {
$prev-key: null;
$prev-num: null;
@each $key, $num in $map {
@if $prev-num == null or unit($num) == "%" or unit($prev-num) == "%" {
// Do nothing
} @else if not comparable($prev-num, $num) {
@warn "Potentially invalid value for #{$map-name}: This map must be in ascending order, but key '#{$key}' has value #{$num} whose unit makes it incomparable to #{$prev-num}, the value of the previous key '#{$prev-key}' !";
} @else if $prev-num >= $num {
@warn "Invalid value for #{$map-name}: This map must be in ascending order, but key '#{$key}' has value #{$num} which isn't greater than #{$prev-num}, the value of the previous key '#{$prev-key}' !";
}
$prev-key: $key;
$prev-num: $num;
}
}
// Starts at zero
// Used to ensure the min-width of the lowest breakpoint starts at 0.
@mixin _assert-starts-at-zero($map, $map-name: "$grid-breakpoints") {
@if length($map) > 0 {
$values: map-values($map);
$first-value: nth($values, 1);
@if $first-value != 0 {
@warn "First breakpoint in #{$map-name} must start at 0, but starts at #{$first-value}.";
}
}
}
// Colors
@function to-rgb($value) {
@return red($value), green($value), blue($value);
}
// stylelint-disable scss/dollar-variable-pattern
@function rgba-css-var($identifier, $target) {
@if $identifier == "body" and $target == "bg" {
@return rgba(var(--#{$prefix}#{$identifier}-bg-rgb), var(--#{$prefix}#{$target}-opacity));
} @if $identifier == "body" and $target == "text" {
@return rgba(var(--#{$prefix}#{$identifier}-color-rgb), var(--#{$prefix}#{$target}-opacity));
} @else {
@return rgba(var(--#{$prefix}#{$identifier}-rgb), var(--#{$prefix}#{$target}-opacity));
}
}
@function map-loop($map, $func, $args...) {
$_map: ();
@each $key, $value in $map {
// allow to pass the $key and $value of the map as an function argument
$_args: ();
@each $arg in $args {
$_args: append($_args, if($arg == "$key", $key, if($arg == "$value", $value, $arg)));
}
$_map: map-merge($_map, ($key: call(get-function($func), $_args...)));
}
@return $_map;
}
// stylelint-enable scss/dollar-variable-pattern
@function varify($list) {
$result: null;
@each $entry in $list {
$result: append($result, var(--#{$prefix}#{$entry}), space);
}
@return $result;
}
// Internal Bootstrap function to turn maps into its negative variant.
// It prefixes the keys with `n` and makes the value negative.
@function negativify-map($map) {
$result: ();
@each $key, $value in $map {
@if $key != 0 {
$result: map-merge($result, ("n" + $key: (-$value)));
}
}
@return $result;
}
// Get multiple keys from a sass map
@function map-get-multiple($map, $values) {
$result: ();
@each $key, $value in $map {
@if (index($values, $key) != null) {
$result: map-merge($result, ($key: $value));
}
}
@return $result;
}
// Merge multiple maps
@function map-merge-multiple($maps...) {
$merged-maps: ();
@each $map in $maps {
$merged-maps: map-merge($merged-maps, $map);
}
@return $merged-maps;
}
// Replace `$search` with `$replace` in `$string`
// Used on our SVG icon backgrounds for custom forms.
//
// @author Kitty Giraudel
// @param {String} $string - Initial string
// @param {String} $search - Substring to replace
// @param {String} $replace ('') - New value
// @return {String} - Updated string
@function str-replace($string, $search, $replace: "") {
$index: str-index($string, $search);
@if $index {
@return str-slice($string, 1, $index - 1) + $replace + str-replace(str-slice($string, $index + str-length($search)), $search, $replace);
}
@return $string;
}
// See https://codepen.io/kevinweber/pen/dXWoRw
//
// Requires the use of quotes around data URIs.
@function escape-svg($string) {
@if str-index($string, "data:image/svg+xml") {
@each $char, $encoded in $escaped-characters {
// Do not escape the url brackets
@if str-index($string, "url(") == 1 {
$string: url("#{str-replace(str-slice($string, 6, -3), $char, $encoded)}");
} @else {
$string: str-replace($string, $char, $encoded);
}
}
}
@return $string;
}
// Color contrast
// See https://github.com/twbs/bootstrap/pull/30168
// A list of pre-calculated numbers of pow(divide((divide($value, 255) + .055), 1.055), 2.4). (from 0 to 255)
// stylelint-disable-next-line scss/dollar-variable-default, scss/dollar-variable-pattern
$_luminance-list: .0008 .001 .0011 .0013 .0015 .0017 .002 .0022 .0025 .0027 .003 .0033 .0037 .004 .0044 .0048 .0052 .0056 .006 .0065 .007 .0075 .008 .0086 .0091 .0097 .0103 .011 .0116 .0123 .013 .0137 .0144 .0152 .016 .0168 .0176 .0185 .0194 .0203 .0212 .0222 .0232 .0242 .0252 .0262 .0273 .0284 .0296 .0307 .0319 .0331 .0343 .0356 .0369 .0382 .0395 .0409 .0423 .0437 .0452 .0467 .0482 .0497 .0513 .0529 .0545 .0561 .0578 .0595 .0612 .063 .0648 .0666 .0685 .0704 .0723 .0742 .0762 .0782 .0802 .0823 .0844 .0865 .0887 .0908 .0931 .0953 .0976 .0999 .1022 .1046 .107 .1095 .1119 .1144 .117 .1195 .1221 .1248 .1274 .1301 .1329 .1356 .1384 .1413 .1441 .147 .15 .1529 .1559 .159 .162 .1651 .1683 .1714 .1746 .1779 .1812 .1845 .1878 .1912 .1946 .1981 .2016 .2051 .2086 .2122 .2159 .2195 .2232 .227 .2307 .2346 .2384 .2423 .2462 .2502 .2542 .2582 .2623 .2664 .2705 .2747 .2789 .2831 .2874 .2918 .2961 .3005 .305 .3095 .314 .3185 .3231 .3278 .3325 .3372 .3419 .3467 .3515 .3564 .3613 .3663 .3712 .3763 .3813 .3864 .3916 .3968 .402 .4072 .4125 .4179 .4233 .4287 .4342 .4397 .4452 .4508 .4564 .4621 .4678 .4735 .4793 .4851 .491 .4969 .5029 .5089 .5149 .521 .5271 .5333 .5395 .5457 .552 .5583 .5647 .5711 .5776 .5841 .5906 .5972 .6038 .6105 .6172 .624 .6308 .6376 .6445 .6514 .6584 .6654 .6724 .6795 .6867 .6939 .7011 .7084 .7157 .7231 .7305 .7379 .7454 .7529 .7605 .7682 .7758 .7835 .7913 .7991 .807 .8148 .8228 .8308 .8388 .8469 .855 .8632 .8714 .8796 .8879 .8963 .9047 .9131 .9216 .9301 .9387 .9473 .956 .9647 .9734 .9823 .9911 1;
@function color-contrast($background, $color-contrast-dark: $color-contrast-dark, $color-contrast-light: $color-contrast-light, $min-contrast-ratio: $min-contrast-ratio) {
$foregrounds: $color-contrast-light, $color-contrast-dark, $white, $black;
$max-ratio: 0;
$max-ratio-color: null;
@each $color in $foregrounds {
$contrast-ratio: contrast-ratio($background, $color);
@if $contrast-ratio > $min-contrast-ratio {
@return $color;
} @else if $contrast-ratio > $max-ratio {
$max-ratio: $contrast-ratio;
$max-ratio-color: $color;
}
}
@warn "Found no color leading to #{$min-contrast-ratio}:1 contrast ratio against #{$background}...";
@return $max-ratio-color;
}
@function contrast-ratio($background, $foreground: $color-contrast-light) {
$l1: luminance($background);
$l2: luminance(opaque($background, $foreground));
@return if($l1 > $l2, divide($l1 + .05, $l2 + .05), divide($l2 + .05, $l1 + .05));
}
// Return WCAG2.1 relative luminance
// See https://www.w3.org/TR/WCAG/#dfn-relative-luminance
// See https://www.w3.org/TR/WCAG/#dfn-contrast-ratio
@function luminance($color) {
$rgb: (
"r": red($color),
"g": green($color),
"b": blue($color)
);
@each $name, $value in $rgb {
$value: if(divide($value, 255) < .03928, divide(divide($value, 255), 12.92), nth($_luminance-list, $value + 1));
$rgb: map-merge($rgb, ($name: $value));
}
@return (map-get($rgb, "r") * .2126) + (map-get($rgb, "g") * .7152) + (map-get($rgb, "b") * .0722);
}
// Return opaque color
// opaque(#fff, rgba(0, 0, 0, .5)) => #808080
@function opaque($background, $foreground) {
@return mix(rgba($foreground, 1), $background, opacity($foreground) * 100%);
}
// scss-docs-start color-functions
// Tint a color: mix a color with white
@function tint-color($color, $weight) {
@return mix(white, $color, $weight);
}
// Shade a color: mix a color with black
@function shade-color($color, $weight) {
@return mix(black, $color, $weight);
}
// Shade the color if the weight is positive, else tint it
@function shift-color($color, $weight) {
@return if($weight > 0, shade-color($color, $weight), tint-color($color, -$weight));
}
// scss-docs-end color-functions
// Return valid calc
@function add($value1, $value2, $return-calc: true) {
@if $value1 == null {
@return $value2;
}
@if $value2 == null {
@return $value1;
}
@if type-of($value1) == number and type-of($value2) == number and comparable($value1, $value2) {
@return $value1 + $value2;
}
@return if($return-calc == true, calc(#{$value1} + #{$value2}), $value1 + unquote(" + ") + $value2);
}
@function subtract($value1, $value2, $return-calc: true) {
@if $value1 == null and $value2 == null {
@return null;
}
@if $value1 == null {
@return -$value2;
}
@if $value2 == null {
@return $value1;
}
@if type-of($value1) == number and type-of($value2) == number and comparable($value1, $value2) {
@return $value1 - $value2;
}
@if type-of($value2) != number {
$value2: unquote("(") + $value2 + unquote(")");
}
@return if($return-calc == true, calc(#{$value1} - #{$value2}), $value1 + unquote(" - ") + $value2);
}
@function divide($dividend, $divisor, $precision: 10) {
$sign: if($dividend > 0 and $divisor > 0 or $dividend < 0 and $divisor < 0, 1, -1);
$dividend: abs($dividend);
$divisor: abs($divisor);
@if $dividend == 0 {
@return 0;
}
@if $divisor == 0 {
@error "Cannot divide by 0";
}
$remainder: $dividend;
$result: 0;
$factor: 10;
@while ($remainder > 0 and $precision >= 0) {
$quotient: 0;
@while ($remainder >= $divisor) {
$remainder: $remainder - $divisor;
$quotient: $quotient + 1;
}
$result: $result * 10 + $quotient;
$factor: $factor * .1;
$remainder: $remainder * 10;
$precision: $precision - 1;
@if ($precision < 0 and $remainder >= $divisor * 5) {
$result: $result + 1;
}
}
$result: $result * $factor * $sign;
$dividend-unit: unit($dividend);
$divisor-unit: unit($divisor);
$unit-map: (
"px": 1px,
"rem": 1rem,
"em": 1em,
"%": 1%
);
@if ($dividend-unit != $divisor-unit and map-has-key($unit-map, $dividend-unit)) {
$result: $result * map-get($unit-map, $dividend-unit);
}
@return $result;
}

33
src/main/resources/static/assets/_scss/bootstrap/_grid.scss

@ -0,0 +1,33 @@
// Row
//
// Rows contain your columns.
@if $enable-grid-classes {
.row {
@include make-row();
> * {
@include make-col-ready();
}
}
}
@if $enable-cssgrid {
.grid {
display: grid;
grid-template-rows: repeat(var(--#{$prefix}rows, 1), 1fr);
grid-template-columns: repeat(var(--#{$prefix}columns, #{$grid-columns}), 1fr);
gap: var(--#{$prefix}gap, #{$grid-gutter-width});
@include make-cssgrid();
}
}
// Columns
//
// Common styles for small and large grid columns
@if $enable-grid-classes {
@include make-grid-columns();
}

10
src/main/resources/static/assets/_scss/bootstrap/_helpers.scss

@ -0,0 +1,10 @@
@import "helpers/clearfix";
@import "helpers/color-bg";
@import "helpers/colored-links";
@import "helpers/ratio";
@import "helpers/position";
@import "helpers/stacks";
@import "helpers/visually-hidden";
@import "helpers/stretched-link";
@import "helpers/text-truncation";
@import "helpers/vr";

42
src/main/resources/static/assets/_scss/bootstrap/_images.scss

@ -0,0 +1,42 @@
// Responsive images (ensure images don't scale beyond their parents)
//
// This is purposefully opt-in via an explicit class rather than being the default for all `<img>`s.
// We previously tried the "images are responsive by default" approach in Bootstrap v2,
// and abandoned it in Bootstrap v3 because it breaks lots of third-party widgets (including Google Maps)
// which weren't expecting the images within themselves to be involuntarily resized.
// See also https://github.com/twbs/bootstrap/issues/18178
.img-fluid {
@include img-fluid();
}
// Image thumbnails
.img-thumbnail {
padding: $thumbnail-padding;
background-color: $thumbnail-bg;
border: $thumbnail-border-width solid $thumbnail-border-color;
@include border-radius($thumbnail-border-radius);
@include box-shadow($thumbnail-box-shadow);
// Keep them at most 100% wide
@include img-fluid();
}
//
// Figures
//
.figure {
// Ensures the caption's text aligns with the image.
display: inline-block;
}
.figure-img {
margin-bottom: $spacer * .5;
line-height: 1;
}
.figure-caption {
@include font-size($figure-caption-font-size);
color: $figure-caption-color;
}

192
src/main/resources/static/assets/_scss/bootstrap/_list-group.scss

@ -0,0 +1,192 @@
// Base class
//
// Easily usable on <ul>, <ol>, or <div>.
.list-group {
// scss-docs-start list-group-css-vars
--#{$prefix}list-group-color: #{$list-group-color};
--#{$prefix}list-group-bg: #{$list-group-bg};
--#{$prefix}list-group-border-color: #{$list-group-border-color};
--#{$prefix}list-group-border-width: #{$list-group-border-width};
--#{$prefix}list-group-border-radius: #{$list-group-border-radius};
--#{$prefix}list-group-item-padding-x: #{$list-group-item-padding-x};
--#{$prefix}list-group-item-padding-y: #{$list-group-item-padding-y};
--#{$prefix}list-group-action-color: #{$list-group-action-color};
--#{$prefix}list-group-action-hover-color: #{$list-group-action-hover-color};
--#{$prefix}list-group-action-hover-bg: #{$list-group-hover-bg};
--#{$prefix}list-group-action-active-color: #{$list-group-action-active-color};
--#{$prefix}list-group-action-active-bg: #{$list-group-action-active-bg};
--#{$prefix}list-group-disabled-color: #{$list-group-disabled-color};
--#{$prefix}list-group-disabled-bg: #{$list-group-disabled-bg};
--#{$prefix}list-group-active-color: #{$list-group-active-color};
--#{$prefix}list-group-active-bg: #{$list-group-active-bg};
--#{$prefix}list-group-active-border-color: #{$list-group-active-border-color};
// scss-docs-end list-group-css-vars
display: flex;
flex-direction: column;
// No need to set list-style: none; since .list-group-item is block level
padding-left: 0; // reset padding because ul and ol
margin-bottom: 0;
@include border-radius(var(--#{$prefix}list-group-border-radius));
}
.list-group-numbered {
list-style-type: none;
counter-reset: section;
> .list-group-item::before {
// Increments only this instance of the section counter
content: counters(section, ".") ". ";
counter-increment: section;
}
}
// Interactive list items
//
// Use anchor or button elements instead of `li`s or `div`s to create interactive
// list items. Includes an extra `.active` modifier class for selected items.
.list-group-item-action {
width: 100%; // For `<button>`s (anchors become 100% by default though)
color: var(--#{$prefix}list-group-action-color);
text-align: inherit; // For `<button>`s (anchors inherit)
// Hover state
&:hover,
&:focus {
z-index: 1; // Place hover/focus items above their siblings for proper border styling
color: var(--#{$prefix}list-group-action-hover-color);
text-decoration: none;
background-color: var(--#{$prefix}list-group-action-hover-bg);
}
&:active {
color: var(--#{$prefix}list-group-action-active-color);
background-color: var(--#{$prefix}list-group-action-active-bg);
}
}
// Individual list items
//
// Use on `li`s or `div`s within the `.list-group` parent.
.list-group-item {
position: relative;
display: block;
padding: var(--#{$prefix}list-group-item-padding-y) var(--#{$prefix}list-group-item-padding-x);
color: var(--#{$prefix}list-group-color);
text-decoration: if($link-decoration == none, null, none);
background-color: var(--#{$prefix}list-group-bg);
border: var(--#{$prefix}list-group-border-width) solid var(--#{$prefix}list-group-border-color);
&:first-child {
@include border-top-radius(inherit);
}
&:last-child {
@include border-bottom-radius(inherit);
}
&.disabled,
&:disabled {
color: var(--#{$prefix}list-group-disabled-color);
pointer-events: none;
background-color: var(--#{$prefix}list-group-disabled-bg);
}
// Include both here for `<a>`s and `<button>`s
&.active {
z-index: 2; // Place active items above their siblings for proper border styling
color: var(--#{$prefix}list-group-active-color);
background-color: var(--#{$prefix}list-group-active-bg);
border-color: var(--#{$prefix}list-group-active-border-color);
}
// stylelint-disable-next-line scss/selector-no-redundant-nesting-selector
& + .list-group-item {
border-top-width: 0;
&.active {
margin-top: calc(-1 * var(--#{$prefix}list-group-border-width)); // stylelint-disable-line function-disallowed-list
border-top-width: var(--#{$prefix}list-group-border-width);
}
}
}
// Horizontal
//
// Change the layout of list group items from vertical (default) to horizontal.
@each $breakpoint in map-keys($grid-breakpoints) {
@include media-breakpoint-up($breakpoint) {
$infix: breakpoint-infix($breakpoint, $grid-breakpoints);
.list-group-horizontal#{$infix} {
flex-direction: row;
> .list-group-item {
&:first-child:not(:last-child) {
@include border-bottom-start-radius(var(--#{$prefix}list-group-border-radius));
@include border-top-end-radius(0);
}
&:last-child:not(:first-child) {
@include border-top-end-radius(var(--#{$prefix}list-group-border-radius));
@include border-bottom-start-radius(0);
}
&.active {
margin-top: 0;
}
+ .list-group-item {
border-top-width: var(--#{$prefix}list-group-border-width);
border-left-width: 0;
&.active {
margin-left: calc(-1 * var(--#{$prefix}list-group-border-width)); // stylelint-disable-line function-disallowed-list
border-left-width: var(--#{$prefix}list-group-border-width);
}
}
}
}
}
}
// Flush list items
//
// Remove borders and border-radius to keep list group items edge-to-edge. Most
// useful within other components (e.g., cards).
.list-group-flush {
@include border-radius(0);
> .list-group-item {
border-width: 0 0 var(--#{$prefix}list-group-border-width);
&:last-child {
border-bottom-width: 0;
}
}
}
// scss-docs-start list-group-modifiers
// List group contextual variants
//
// Add modifier classes to change text and background color on individual items.
// Organizationally, this must come after the `:hover` states.
@each $state, $value in $theme-colors {
$list-group-variant-bg: shift-color($value, $list-group-item-bg-scale);
$list-group-variant-color: shift-color($value, $list-group-item-color-scale);
@if (contrast-ratio($list-group-variant-bg, $list-group-variant-color) < $min-contrast-ratio) {
$list-group-variant-color: mix($value, color-contrast($list-group-variant-bg), abs($list-group-item-color-scale));
}
@include list-group-item-variant($state, $list-group-variant-bg, $list-group-variant-color);
}
// scss-docs-end list-group-modifiers

54
src/main/resources/static/assets/_scss/bootstrap/_maps.scss

@ -0,0 +1,54 @@
// Re-assigned maps
//
// Placed here so that others can override the default Sass maps and see automatic updates to utilities and more.
// scss-docs-start theme-colors-rgb
$theme-colors-rgb: map-loop($theme-colors, to-rgb, "$value") !default;
// scss-docs-end theme-colors-rgb
// Utilities maps
//
// Extends the default `$theme-colors` maps to help create our utilities.
// Come v6, we'll de-dupe these variables. Until then, for backward compatibility, we keep them to reassign.
// scss-docs-start utilities-colors
$utilities-colors: $theme-colors-rgb !default;
// scss-docs-end utilities-colors
// scss-docs-start utilities-text-colors
$utilities-text: map-merge(
$utilities-colors,
(
"black": to-rgb($black),
"white": to-rgb($white),
"body": to-rgb($body-color)
)
) !default;
$utilities-text-colors: map-loop($utilities-text, rgba-css-var, "$key", "text") !default;
// scss-docs-end utilities-text-colors
// scss-docs-start utilities-bg-colors
$utilities-bg: map-merge(
$utilities-colors,
(
"black": to-rgb($black),
"white": to-rgb($white),
"body": to-rgb($body-bg)
)
) !default;
$utilities-bg-colors: map-loop($utilities-bg, rgba-css-var, "$key", "bg") !default;
// scss-docs-end utilities-bg-colors
// scss-docs-start utilities-border-colors
$utilities-border: map-merge(
$utilities-colors,
(
"white": to-rgb($white)
)
) !default;
$utilities-border-colors: map-loop($utilities-border, rgba-css-var, "$key", "border") !default;
// scss-docs-end utilities-border-colors
$negative-spacers: if($enable-negative-margins, negativify-map($spacers), null) !default;
$gutters: $spacers !default;

43
src/main/resources/static/assets/_scss/bootstrap/_mixins.scss

@ -0,0 +1,43 @@
// Toggles
//
// Used in conjunction with global variables to enable certain theme features.
// Vendor
@import "vendor/rfs";
// Deprecate
@import "mixins/deprecate";
// Helpers
@import "mixins/breakpoints";
@import "mixins/color-scheme";
@import "mixins/image";
@import "mixins/resize";
@import "mixins/visually-hidden";
@import "mixins/reset-text";
@import "mixins/text-truncate";
// Utilities
@import "mixins/utilities";
// Components
@import "mixins/alert";
@import "mixins/backdrop";
@import "mixins/buttons";
@import "mixins/caret";
@import "mixins/pagination";
@import "mixins/lists";
@import "mixins/list-group";
@import "mixins/forms";
@import "mixins/table-variants";
// Skins
@import "mixins/border-radius";
@import "mixins/box-shadow";
@import "mixins/gradients";
@import "mixins/transition";
// Layout
@import "mixins/clearfix";
@import "mixins/container";
@import "mixins/grid";

237
src/main/resources/static/assets/_scss/bootstrap/_modal.scss

@ -0,0 +1,237 @@
// stylelint-disable function-disallowed-list
// .modal-open - body class for killing the scroll
// .modal - container to scroll within
// .modal-dialog - positioning shell for the actual modal
// .modal-content - actual modal w/ bg and corners and stuff
// Container that the modal scrolls within
.modal {
// scss-docs-start modal-css-vars
--#{$prefix}modal-zindex: #{$zindex-modal};
--#{$prefix}modal-width: #{$modal-md};
--#{$prefix}modal-padding: #{$modal-inner-padding};
--#{$prefix}modal-margin: #{$modal-dialog-margin};
--#{$prefix}modal-color: #{$modal-content-color};
--#{$prefix}modal-bg: #{$modal-content-bg};
--#{$prefix}modal-border-color: #{$modal-content-border-color};
--#{$prefix}modal-border-width: #{$modal-content-border-width};
--#{$prefix}modal-border-radius: #{$modal-content-border-radius};
--#{$prefix}modal-box-shadow: #{$modal-content-box-shadow-xs};
--#{$prefix}modal-inner-border-radius: #{$modal-content-inner-border-radius};
--#{$prefix}modal-header-padding-x: #{$modal-header-padding-x};
--#{$prefix}modal-header-padding-y: #{$modal-header-padding-y};
--#{$prefix}modal-header-padding: #{$modal-header-padding}; // Todo in v6: Split this padding into x and y
--#{$prefix}modal-header-border-color: #{$modal-header-border-color};
--#{$prefix}modal-header-border-width: #{$modal-header-border-width};
--#{$prefix}modal-title-line-height: #{$modal-title-line-height};
--#{$prefix}modal-footer-gap: #{$modal-footer-margin-between};
--#{$prefix}modal-footer-bg: #{$modal-footer-bg};
--#{$prefix}modal-footer-border-color: #{$modal-footer-border-color};
--#{$prefix}modal-footer-border-width: #{$modal-footer-border-width};
// scss-docs-end modal-css-vars
position: fixed;
top: 0;
left: 0;
z-index: var(--#{$prefix}modal-zindex);
display: none;
width: 100%;
height: 100%;
overflow-x: hidden;
overflow-y: auto;
// Prevent Chrome on Windows from adding a focus outline. For details, see
// https://github.com/twbs/bootstrap/pull/10951.
outline: 0;
// We deliberately don't use `-webkit-overflow-scrolling: touch;` due to a
// gnarly iOS Safari bug: https://bugs.webkit.org/show_bug.cgi?id=158342
// See also https://github.com/twbs/bootstrap/issues/17695
}
// Shell div to position the modal with bottom padding
.modal-dialog {
position: relative;
width: auto;
margin: var(--#{$prefix}modal-margin);
// allow clicks to pass through for custom click handling to close modal
pointer-events: none;
// When fading in the modal, animate it to slide down
.modal.fade & {
@include transition($modal-transition);
transform: $modal-fade-transform;
}
.modal.show & {
transform: $modal-show-transform;
}
// When trying to close, animate focus to scale
.modal.modal-static & {
transform: $modal-scale-transform;
}
}
.modal-dialog-scrollable {
height: calc(100% - var(--#{$prefix}modal-margin) * 2);
.modal-content {
max-height: 100%;
overflow: hidden;
}
.modal-body {
overflow-y: auto;
}
}
.modal-dialog-centered {
display: flex;
align-items: center;
min-height: calc(100% - var(--#{$prefix}modal-margin) * 2);
}
// Actual modal
.modal-content {
position: relative;
display: flex;
flex-direction: column;
width: 100%; // Ensure `.modal-content` extends the full width of the parent `.modal-dialog`
// counteract the pointer-events: none; in the .modal-dialog
color: var(--#{$prefix}modal-color);
pointer-events: auto;
background-color: var(--#{$prefix}modal-bg);
background-clip: padding-box;
border: var(--#{$prefix}modal-border-width) solid var(--#{$prefix}modal-border-color);
@include border-radius(var(--#{$prefix}modal-border-radius));
@include box-shadow(var(--#{$prefix}modal-box-shadow));
// Remove focus outline from opened modal
outline: 0;
}
// Modal background
.modal-backdrop {
// scss-docs-start modal-backdrop-css-vars
--#{$prefix}backdrop-zindex: #{$zindex-modal-backdrop};
--#{$prefix}backdrop-bg: #{$modal-backdrop-bg};
--#{$prefix}backdrop-opacity: #{$modal-backdrop-opacity};
// scss-docs-end modal-backdrop-css-vars
@include overlay-backdrop(var(--#{$prefix}backdrop-zindex), var(--#{$prefix}backdrop-bg), var(--#{$prefix}backdrop-opacity));
}
// Modal header
// Top section of the modal w/ title and dismiss
.modal-header {
display: flex;
flex-shrink: 0;
align-items: center;
justify-content: space-between; // Put modal header elements (title and dismiss) on opposite ends
padding: var(--#{$prefix}modal-header-padding);
border-bottom: var(--#{$prefix}modal-header-border-width) solid var(--#{$prefix}modal-header-border-color);
@include border-top-radius(var(--#{$prefix}modal-inner-border-radius));
.btn-close {
padding: calc(var(--#{$prefix}modal-header-padding-y) * .5) calc(var(--#{$prefix}modal-header-padding-x) * .5);
margin: calc(-.5 * var(--#{$prefix}modal-header-padding-y)) calc(-.5 * var(--#{$prefix}modal-header-padding-x)) calc(-.5 * var(--#{$prefix}modal-header-padding-y)) auto;
}
}
// Title text within header
.modal-title {
margin-bottom: 0;
line-height: var(--#{$prefix}modal-title-line-height);
}
// Modal body
// Where all modal content resides (sibling of .modal-header and .modal-footer)
.modal-body {
position: relative;
// Enable `flex-grow: 1` so that the body take up as much space as possible
// when there should be a fixed height on `.modal-dialog`.
flex: 1 1 auto;
padding: var(--#{$prefix}modal-padding);
}
// Footer (for actions)
.modal-footer {
display: flex;
flex-shrink: 0;
flex-wrap: wrap;
align-items: center; // vertically center
justify-content: flex-end; // Right align buttons with flex property because text-align doesn't work on flex items
padding: calc(var(--#{$prefix}modal-padding) - var(--#{$prefix}modal-footer-gap) * .5);
background-color: var(--#{$prefix}modal-footer-bg);
border-top: var(--#{$prefix}modal-footer-border-width) solid var(--#{$prefix}modal-footer-border-color);
@include border-bottom-radius(var(--#{$prefix}modal-inner-border-radius));
// Place margin between footer elements
// This solution is far from ideal because of the universal selector usage,
// but is needed to fix https://github.com/twbs/bootstrap/issues/24800
> * {
margin: calc(var(--#{$prefix}modal-footer-gap) * .5); // Todo in v6: replace with gap on parent class
}
}
// Scale up the modal
@include media-breakpoint-up(sm) {
.modal {
--#{$prefix}modal-margin: #{$modal-dialog-margin-y-sm-up};
--#{$prefix}modal-box-shadow: #{$modal-content-box-shadow-sm-up};
}
// Automatically set modal's width for larger viewports
.modal-dialog {
max-width: var(--#{$prefix}modal-width);
margin-right: auto;
margin-left: auto;
}
.modal-sm {
--#{$prefix}modal-width: #{$modal-sm};
}
}
@include media-breakpoint-up(lg) {
.modal-lg,
.modal-xl {
--#{$prefix}modal-width: #{$modal-lg};
}
}
@include media-breakpoint-up(xl) {
.modal-xl {
--#{$prefix}modal-width: #{$modal-xl};
}
}
// scss-docs-start modal-fullscreen-loop
@each $breakpoint in map-keys($grid-breakpoints) {
$infix: breakpoint-infix($breakpoint, $grid-breakpoints);
$postfix: if($infix != "", $infix + "-down", "");
@include media-breakpoint-down($breakpoint) {
.modal-fullscreen#{$postfix} {
width: 100vw;
max-width: none;
height: 100%;
margin: 0;
.modal-content {
height: 100%;
border: 0;
@include border-radius(0);
}
.modal-header,
.modal-footer {
@include border-radius(0);
}
.modal-body {
overflow-y: auto;
}
}
}
}
// scss-docs-end modal-fullscreen-loop

172
src/main/resources/static/assets/_scss/bootstrap/_nav.scss

@ -0,0 +1,172 @@
// Base class
//
// Kickstart any navigation component with a set of style resets. Works with
// `<nav>`s, `<ul>`s or `<ol>`s.
.nav {
// scss-docs-start nav-css-vars
--#{$prefix}nav-link-padding-x: #{$nav-link-padding-x};
--#{$prefix}nav-link-padding-y: #{$nav-link-padding-y};
@include rfs($nav-link-font-size, --#{$prefix}nav-link-font-size);
--#{$prefix}nav-link-font-weight: #{$nav-link-font-weight};
--#{$prefix}nav-link-color: #{$nav-link-color};
--#{$prefix}nav-link-hover-color: #{$nav-link-hover-color};
--#{$prefix}nav-link-disabled-color: #{$nav-link-disabled-color};
// scss-docs-end nav-css-vars
display: flex;
flex-wrap: wrap;
padding-left: 0;
margin-bottom: 0;
list-style: none;
}
.nav-link {
display: block;
padding: var(--#{$prefix}nav-link-padding-y) var(--#{$prefix}nav-link-padding-x);
@include font-size(var(--#{$prefix}nav-link-font-size));
font-weight: var(--#{$prefix}nav-link-font-weight);
color: var(--#{$prefix}nav-link-color);
text-decoration: if($link-decoration == none, null, none);
@include transition($nav-link-transition);
&:hover,
&:focus {
color: var(--#{$prefix}nav-link-hover-color);
text-decoration: if($link-hover-decoration == underline, none, null);
}
// Disabled state lightens text
&.disabled {
color: var(--#{$prefix}nav-link-disabled-color);
pointer-events: none;
cursor: default;
}
}
//
// Tabs
//
.nav-tabs {
// scss-docs-start nav-tabs-css-vars
--#{$prefix}nav-tabs-border-width: #{$nav-tabs-border-width};
--#{$prefix}nav-tabs-border-color: #{$nav-tabs-border-color};
--#{$prefix}nav-tabs-border-radius: #{$nav-tabs-border-radius};
--#{$prefix}nav-tabs-link-hover-border-color: #{$nav-tabs-link-hover-border-color};
--#{$prefix}nav-tabs-link-active-color: #{$nav-tabs-link-active-color};
--#{$prefix}nav-tabs-link-active-bg: #{$nav-tabs-link-active-bg};
--#{$prefix}nav-tabs-link-active-border-color: #{$nav-tabs-link-active-border-color};
// scss-docs-end nav-tabs-css-vars
border-bottom: var(--#{$prefix}nav-tabs-border-width) solid var(--#{$prefix}nav-tabs-border-color);
.nav-link {
margin-bottom: calc(-1 * var(--#{$prefix}nav-tabs-border-width)); // stylelint-disable-line function-disallowed-list
background: none;
border: var(--#{$prefix}nav-tabs-border-width) solid transparent;
@include border-top-radius(var(--#{$prefix}nav-tabs-border-radius));
&:hover,
&:focus {
// Prevents active .nav-link tab overlapping focus outline of previous/next .nav-link
isolation: isolate;
border-color: var(--#{$prefix}nav-tabs-link-hover-border-color);
}
&.disabled,
&:disabled {
color: var(--#{$prefix}nav-link-disabled-color);
background-color: transparent;
border-color: transparent;
}
}
.nav-link.active,
.nav-item.show .nav-link {
color: var(--#{$prefix}nav-tabs-link-active-color);
background-color: var(--#{$prefix}nav-tabs-link-active-bg);
border-color: var(--#{$prefix}nav-tabs-link-active-border-color);
}
.dropdown-menu {
// Make dropdown border overlap tab border
margin-top: calc(-1 * var(--#{$prefix}nav-tabs-border-width)); // stylelint-disable-line function-disallowed-list
// Remove the top rounded corners here since there is a hard edge above the menu
@include border-top-radius(0);
}
}
//
// Pills
//
.nav-pills {
// scss-docs-start nav-pills-css-vars
--#{$prefix}nav-pills-border-radius: #{$nav-pills-border-radius};
--#{$prefix}nav-pills-link-active-color: #{$nav-pills-link-active-color};
--#{$prefix}nav-pills-link-active-bg: #{$nav-pills-link-active-bg};
// scss-docs-end nav-pills-css-vars
.nav-link {
background: none;
border: 0;
@include border-radius(var(--#{$prefix}nav-pills-border-radius));
&:disabled {
color: var(--#{$prefix}nav-link-disabled-color);
background-color: transparent;
border-color: transparent;
}
}
.nav-link.active,
.show > .nav-link {
color: var(--#{$prefix}nav-pills-link-active-color);
@include gradient-bg(var(--#{$prefix}nav-pills-link-active-bg));
}
}
//
// Justified variants
//
.nav-fill {
> .nav-link,
.nav-item {
flex: 1 1 auto;
text-align: center;
}
}
.nav-justified {
> .nav-link,
.nav-item {
flex-basis: 0;
flex-grow: 1;
text-align: center;
}
}
.nav-fill,
.nav-justified {
.nav-item .nav-link {
width: 100%; // Make sure button will grow
}
}
// Tabbable tabs
//
// Hide tabbable panes to start, show them when `.active`
.tab-content {
> .tab-pane {
display: none;
}
> .active {
display: block;
}
}

278
src/main/resources/static/assets/_scss/bootstrap/_navbar.scss

@ -0,0 +1,278 @@
// Navbar
//
// Provide a static navbar from which we expand to create full-width, fixed, and
// other navbar variations.
.navbar {
// scss-docs-start navbar-css-vars
--#{$prefix}navbar-padding-x: #{if($navbar-padding-x == null, 0, $navbar-padding-x)};
--#{$prefix}navbar-padding-y: #{$navbar-padding-y};
--#{$prefix}navbar-color: #{$navbar-light-color};
--#{$prefix}navbar-hover-color: #{$navbar-light-hover-color};
--#{$prefix}navbar-disabled-color: #{$navbar-light-disabled-color};
--#{$prefix}navbar-active-color: #{$navbar-light-active-color};
--#{$prefix}navbar-brand-padding-y: #{$navbar-brand-padding-y};
--#{$prefix}navbar-brand-margin-end: #{$navbar-brand-margin-end};
--#{$prefix}navbar-brand-font-size: #{$navbar-brand-font-size};
--#{$prefix}navbar-brand-color: #{$navbar-light-brand-color};
--#{$prefix}navbar-brand-hover-color: #{$navbar-light-brand-hover-color};
--#{$prefix}navbar-nav-link-padding-x: #{$navbar-nav-link-padding-x};
--#{$prefix}navbar-toggler-padding-y: #{$navbar-toggler-padding-y};
--#{$prefix}navbar-toggler-padding-x: #{$navbar-toggler-padding-x};
--#{$prefix}navbar-toggler-font-size: #{$navbar-toggler-font-size};
--#{$prefix}navbar-toggler-icon-bg: #{escape-svg($navbar-light-toggler-icon-bg)};
--#{$prefix}navbar-toggler-border-color: #{$navbar-light-toggler-border-color};
--#{$prefix}navbar-toggler-border-radius: #{$navbar-toggler-border-radius};
--#{$prefix}navbar-toggler-focus-width: #{$navbar-toggler-focus-width};
--#{$prefix}navbar-toggler-transition: #{$navbar-toggler-transition};
// scss-docs-end navbar-css-vars
position: relative;
display: flex;
flex-wrap: wrap; // allow us to do the line break for collapsing content
align-items: center;
justify-content: space-between; // space out brand from logo
padding: var(--#{$prefix}navbar-padding-y) var(--#{$prefix}navbar-padding-x);
@include gradient-bg();
// Because flex properties aren't inherited, we need to redeclare these first
// few properties so that content nested within behave properly.
// The `flex-wrap` property is inherited to simplify the expanded navbars
%container-flex-properties {
display: flex;
flex-wrap: inherit;
align-items: center;
justify-content: space-between;
}
> .container,
> .container-fluid {
@extend %container-flex-properties;
}
@each $breakpoint, $container-max-width in $container-max-widths {
> .container#{breakpoint-infix($breakpoint, $container-max-widths)} {
@extend %container-flex-properties;
}
}
}
// Navbar brand
//
// Used for brand, project, or site names.
.navbar-brand {
padding-top: var(--#{$prefix}navbar-brand-padding-y);
padding-bottom: var(--#{$prefix}navbar-brand-padding-y);
margin-right: var(--#{$prefix}navbar-brand-margin-end);
@include font-size(var(--#{$prefix}navbar-brand-font-size));
color: var(--#{$prefix}navbar-brand-color);
text-decoration: if($link-decoration == none, null, none);
white-space: nowrap;
&:hover,
&:focus {
color: var(--#{$prefix}navbar-brand-hover-color);
text-decoration: if($link-hover-decoration == underline, none, null);
}
}
// Navbar nav
//
// Custom navbar navigation (doesn't require `.nav`, but does make use of `.nav-link`).
.navbar-nav {
// scss-docs-start navbar-nav-css-vars
--#{$prefix}nav-link-padding-x: 0;
--#{$prefix}nav-link-padding-y: #{$nav-link-padding-y};
@include rfs($nav-link-font-size, --#{$prefix}nav-link-font-size);
--#{$prefix}nav-link-font-weight: #{$nav-link-font-weight};
--#{$prefix}nav-link-color: var(--#{$prefix}navbar-color);
--#{$prefix}nav-link-hover-color: var(--#{$prefix}navbar-hover-color);
--#{$prefix}nav-link-disabled-color: var(--#{$prefix}navbar-disabled-color);
// scss-docs-end navbar-nav-css-vars
display: flex;
flex-direction: column; // cannot use `inherit` to get the `.navbar`s value
padding-left: 0;
margin-bottom: 0;
list-style: none;
.show > .nav-link,
.nav-link.active {
color: var(--#{$prefix}navbar-active-color);
}
.dropdown-menu {
position: static;
}
}
// Navbar text
//
//
.navbar-text {
padding-top: $nav-link-padding-y;
padding-bottom: $nav-link-padding-y;
color: var(--#{$prefix}navbar-color);
a,
a:hover,
a:focus {
color: var(--#{$prefix}navbar-active-color);
}
}
// Responsive navbar
//
// Custom styles for responsive collapsing and toggling of navbar contents.
// Powered by the collapse Bootstrap JavaScript plugin.
// When collapsed, prevent the toggleable navbar contents from appearing in
// the default flexbox row orientation. Requires the use of `flex-wrap: wrap`
// on the `.navbar` parent.
.navbar-collapse {
flex-basis: 100%;
flex-grow: 1;
// For always expanded or extra full navbars, ensure content aligns itself
// properly vertically. Can be easily overridden with flex utilities.
align-items: center;
}
// Button for toggling the navbar when in its collapsed state
.navbar-toggler {
padding: var(--#{$prefix}navbar-toggler-padding-y) var(--#{$prefix}navbar-toggler-padding-x);
@include font-size(var(--#{$prefix}navbar-toggler-font-size));
line-height: 1;
color: var(--#{$prefix}navbar-color);
background-color: transparent; // remove default button style
border: var(--#{$prefix}border-width) solid var(--#{$prefix}navbar-toggler-border-color); // remove default button style
@include border-radius(var(--#{$prefix}navbar-toggler-border-radius));
@include transition(var(--#{$prefix}navbar-toggler-transition));
&:hover {
text-decoration: none;
}
&:focus {
text-decoration: none;
outline: 0;
box-shadow: 0 0 0 var(--#{$prefix}navbar-toggler-focus-width);
}
}
// Keep as a separate element so folks can easily override it with another icon
// or image file as needed.
.navbar-toggler-icon {
display: inline-block;
width: 1.5em;
height: 1.5em;
vertical-align: middle;
background-image: var(--#{$prefix}navbar-toggler-icon-bg);
background-repeat: no-repeat;
background-position: center;
background-size: 100%;
}
.navbar-nav-scroll {
max-height: var(--#{$prefix}scroll-height, 75vh);
overflow-y: auto;
}
// scss-docs-start navbar-expand-loop
// Generate series of `.navbar-expand-*` responsive classes for configuring
// where your navbar collapses.
.navbar-expand {
@each $breakpoint in map-keys($grid-breakpoints) {
$next: breakpoint-next($breakpoint, $grid-breakpoints);
$infix: breakpoint-infix($next, $grid-breakpoints);
// stylelint-disable-next-line scss/selector-no-union-class-name
&#{$infix} {
@include media-breakpoint-up($next) {
flex-wrap: nowrap;
justify-content: flex-start;
.navbar-nav {
flex-direction: row;
.dropdown-menu {
position: absolute;
}
.nav-link {
padding-right: var(--#{$prefix}navbar-nav-link-padding-x);
padding-left: var(--#{$prefix}navbar-nav-link-padding-x);
}
}
.navbar-nav-scroll {
overflow: visible;
}
.navbar-collapse {
display: flex !important; // stylelint-disable-line declaration-no-important
flex-basis: auto;
}
.navbar-toggler {
display: none;
}
.offcanvas {
// stylelint-disable declaration-no-important
position: static;
z-index: auto;
flex-grow: 1;
width: auto !important;
height: auto !important;
visibility: visible !important;
background-color: transparent !important;
border: 0 !important;
transform: none !important;
@include box-shadow(none);
@include transition(none);
// stylelint-enable declaration-no-important
.offcanvas-header {
display: none;
}
.offcanvas-body {
display: flex;
flex-grow: 0;
padding: 0;
overflow-y: visible;
}
}
}
}
}
}
// scss-docs-end navbar-expand-loop
// Navbar themes
//
// Styles for switching between navbars with light or dark background.
.navbar-light {
@include deprecate("`.navbar-light`", "v5.2.0", "v6.0.0", true);
}
.navbar-dark {
// scss-docs-start navbar-dark-css-vars
--#{$prefix}navbar-color: #{$navbar-dark-color};
--#{$prefix}navbar-hover-color: #{$navbar-dark-hover-color};
--#{$prefix}navbar-disabled-color: #{$navbar-dark-disabled-color};
--#{$prefix}navbar-active-color: #{$navbar-dark-active-color};
--#{$prefix}navbar-brand-color: #{$navbar-dark-brand-color};
--#{$prefix}navbar-brand-hover-color: #{$navbar-dark-brand-hover-color};
--#{$prefix}navbar-toggler-border-color: #{$navbar-dark-toggler-border-color};
--#{$prefix}navbar-toggler-icon-bg: #{escape-svg($navbar-dark-toggler-icon-bg)};
// scss-docs-end navbar-dark-css-vars
}

144
src/main/resources/static/assets/_scss/bootstrap/_offcanvas.scss

@ -0,0 +1,144 @@
// stylelint-disable function-disallowed-list
%offcanvas-css-vars {
// scss-docs-start offcanvas-css-vars
--#{$prefix}offcanvas-zindex: #{$zindex-offcanvas};
--#{$prefix}offcanvas-width: #{$offcanvas-horizontal-width};
--#{$prefix}offcanvas-height: #{$offcanvas-vertical-height};
--#{$prefix}offcanvas-padding-x: #{$offcanvas-padding-x};
--#{$prefix}offcanvas-padding-y: #{$offcanvas-padding-y};
--#{$prefix}offcanvas-color: #{$offcanvas-color};
--#{$prefix}offcanvas-bg: #{$offcanvas-bg-color};
--#{$prefix}offcanvas-border-width: #{$offcanvas-border-width};
--#{$prefix}offcanvas-border-color: #{$offcanvas-border-color};
--#{$prefix}offcanvas-box-shadow: #{$offcanvas-box-shadow};
// scss-docs-end offcanvas-css-vars
}
@each $breakpoint in map-keys($grid-breakpoints) {
$next: breakpoint-next($breakpoint, $grid-breakpoints);
$infix: breakpoint-infix($next, $grid-breakpoints);
.offcanvas#{$infix} {
@extend %offcanvas-css-vars;
}
}
@each $breakpoint in map-keys($grid-breakpoints) {
$next: breakpoint-next($breakpoint, $grid-breakpoints);
$infix: breakpoint-infix($next, $grid-breakpoints);
.offcanvas#{$infix} {
@include media-breakpoint-down($next) {
position: fixed;
bottom: 0;
z-index: var(--#{$prefix}offcanvas-zindex);
display: flex;
flex-direction: column;
max-width: 100%;
color: var(--#{$prefix}offcanvas-color);
visibility: hidden;
background-color: var(--#{$prefix}offcanvas-bg);
background-clip: padding-box;
outline: 0;
@include box-shadow(var(--#{$prefix}offcanvas-box-shadow));
@include transition(transform $offcanvas-transition-duration ease-in-out);
&.offcanvas-start {
top: 0;
left: 0;
width: var(--#{$prefix}offcanvas-width);
border-right: var(--#{$prefix}offcanvas-border-width) solid var(--#{$prefix}offcanvas-border-color);
transform: translateX(-100%);
}
&.offcanvas-end {
top: 0;
right: 0;
width: var(--#{$prefix}offcanvas-width);
border-left: var(--#{$prefix}offcanvas-border-width) solid var(--#{$prefix}offcanvas-border-color);
transform: translateX(100%);
}
&.offcanvas-top {
top: 0;
right: 0;
left: 0;
height: var(--#{$prefix}offcanvas-height);
max-height: 100%;
border-bottom: var(--#{$prefix}offcanvas-border-width) solid var(--#{$prefix}offcanvas-border-color);
transform: translateY(-100%);
}
&.offcanvas-bottom {
right: 0;
left: 0;
height: var(--#{$prefix}offcanvas-height);
max-height: 100%;
border-top: var(--#{$prefix}offcanvas-border-width) solid var(--#{$prefix}offcanvas-border-color);
transform: translateY(100%);
}
&.showing,
&.show:not(.hiding) {
transform: none;
}
&.showing,
&.hiding,
&.show {
visibility: visible;
}
}
@if not ($infix == "") {
@include media-breakpoint-up($next) {
--#{$prefix}offcanvas-height: auto;
--#{$prefix}offcanvas-border-width: 0;
background-color: transparent !important; // stylelint-disable-line declaration-no-important
.offcanvas-header {
display: none;
}
.offcanvas-body {
display: flex;
flex-grow: 0;
padding: 0;
overflow-y: visible;
// Reset `background-color` in case `.bg-*` classes are used in offcanvas
background-color: transparent !important; // stylelint-disable-line declaration-no-important
}
}
}
}
}
.offcanvas-backdrop {
@include overlay-backdrop($zindex-offcanvas-backdrop, $offcanvas-backdrop-bg, $offcanvas-backdrop-opacity);
}
.offcanvas-header {
display: flex;
align-items: center;
justify-content: space-between;
padding: var(--#{$prefix}offcanvas-padding-y) var(--#{$prefix}offcanvas-padding-x);
.btn-close {
padding: calc(var(--#{$prefix}offcanvas-padding-y) * .5) calc(var(--#{$prefix}offcanvas-padding-x) * .5);
margin-top: calc(-.5 * var(--#{$prefix}offcanvas-padding-y));
margin-right: calc(-.5 * var(--#{$prefix}offcanvas-padding-x));
margin-bottom: calc(-.5 * var(--#{$prefix}offcanvas-padding-y));
}
}
.offcanvas-title {
margin-bottom: 0;
line-height: $offcanvas-title-line-height;
}
.offcanvas-body {
flex-grow: 1;
padding: var(--#{$prefix}offcanvas-padding-y) var(--#{$prefix}offcanvas-padding-x);
overflow-y: auto;
}

109
src/main/resources/static/assets/_scss/bootstrap/_pagination.scss

@ -0,0 +1,109 @@
.pagination {
// scss-docs-start pagination-css-vars
--#{$prefix}pagination-padding-x: #{$pagination-padding-x};
--#{$prefix}pagination-padding-y: #{$pagination-padding-y};
@include rfs($pagination-font-size, --#{$prefix}pagination-font-size);
--#{$prefix}pagination-color: #{$pagination-color};
--#{$prefix}pagination-bg: #{$pagination-bg};
--#{$prefix}pagination-border-width: #{$pagination-border-width};
--#{$prefix}pagination-border-color: #{$pagination-border-color};
--#{$prefix}pagination-border-radius: #{$pagination-border-radius};
--#{$prefix}pagination-hover-color: #{$pagination-hover-color};
--#{$prefix}pagination-hover-bg: #{$pagination-hover-bg};
--#{$prefix}pagination-hover-border-color: #{$pagination-hover-border-color};
--#{$prefix}pagination-focus-color: #{$pagination-focus-color};
--#{$prefix}pagination-focus-bg: #{$pagination-focus-bg};
--#{$prefix}pagination-focus-box-shadow: #{$pagination-focus-box-shadow};
--#{$prefix}pagination-active-color: #{$pagination-active-color};
--#{$prefix}pagination-active-bg: #{$pagination-active-bg};
--#{$prefix}pagination-active-border-color: #{$pagination-active-border-color};
--#{$prefix}pagination-disabled-color: #{$pagination-disabled-color};
--#{$prefix}pagination-disabled-bg: #{$pagination-disabled-bg};
--#{$prefix}pagination-disabled-border-color: #{$pagination-disabled-border-color};
// scss-docs-end pagination-css-vars
display: flex;
@include list-unstyled();
}
.page-link {
position: relative;
display: block;
padding: var(--#{$prefix}pagination-padding-y) var(--#{$prefix}pagination-padding-x);
@include font-size(var(--#{$prefix}pagination-font-size));
color: var(--#{$prefix}pagination-color);
text-decoration: if($link-decoration == none, null, none);
background-color: var(--#{$prefix}pagination-bg);
border: var(--#{$prefix}pagination-border-width) solid var(--#{$prefix}pagination-border-color);
@include transition($pagination-transition);
&:hover {
z-index: 2;
color: var(--#{$prefix}pagination-hover-color);
text-decoration: if($link-hover-decoration == underline, none, null);
background-color: var(--#{$prefix}pagination-hover-bg);
border-color: var(--#{$prefix}pagination-hover-border-color);
}
&:focus {
z-index: 3;
color: var(--#{$prefix}pagination-focus-color);
background-color: var(--#{$prefix}pagination-focus-bg);
outline: $pagination-focus-outline;
box-shadow: var(--#{$prefix}pagination-focus-box-shadow);
}
&.active,
.active > & {
z-index: 3;
color: var(--#{$prefix}pagination-active-color);
@include gradient-bg(var(--#{$prefix}pagination-active-bg));
border-color: var(--#{$prefix}pagination-active-border-color);
}
&.disabled,
.disabled > & {
color: var(--#{$prefix}pagination-disabled-color);
pointer-events: none;
background-color: var(--#{$prefix}pagination-disabled-bg);
border-color: var(--#{$prefix}pagination-disabled-border-color);
}
}
.page-item {
&:not(:first-child) .page-link {
margin-left: $pagination-margin-start;
}
@if $pagination-margin-start == ($pagination-border-width * -1) {
&:first-child {
.page-link {
@include border-start-radius(var(--#{$prefix}pagination-border-radius));
}
}
&:last-child {
.page-link {
@include border-end-radius(var(--#{$prefix}pagination-border-radius));
}
}
} @else {
// Add border-radius to all pageLinks in case they have left margin
.page-link {
@include border-radius(var(--#{$prefix}pagination-border-radius));
}
}
}
//
// Sizing
//
.pagination-lg {
@include pagination-size($pagination-padding-y-lg, $pagination-padding-x-lg, $font-size-lg, $pagination-border-radius-lg);
}
.pagination-sm {
@include pagination-size($pagination-padding-y-sm, $pagination-padding-x-sm, $font-size-sm, $pagination-border-radius-sm);
}

51
src/main/resources/static/assets/_scss/bootstrap/_placeholders.scss

@ -0,0 +1,51 @@
.placeholder {
display: inline-block;
min-height: 1em;
vertical-align: middle;
cursor: wait;
background-color: currentcolor;
opacity: $placeholder-opacity-max;
&.btn::before {
display: inline-block;
content: "";
}
}
// Sizing
.placeholder-xs {
min-height: .6em;
}
.placeholder-sm {
min-height: .8em;
}
.placeholder-lg {
min-height: 1.2em;
}
// Animation
.placeholder-glow {
.placeholder {
animation: placeholder-glow 2s ease-in-out infinite;
}
}
@keyframes placeholder-glow {
50% {
opacity: $placeholder-opacity-min;
}
}
.placeholder-wave {
mask-image: linear-gradient(130deg, $black 55%, rgba(0, 0, 0, (1 - $placeholder-opacity-min)) 75%, $black 95%);
mask-size: 200% 100%;
animation: placeholder-wave 2s linear infinite;
}
@keyframes placeholder-wave {
100% {
mask-position: -200% 0%;
}
}

196
src/main/resources/static/assets/_scss/bootstrap/_popover.scss

@ -0,0 +1,196 @@
.popover {
// scss-docs-start popover-css-vars
--#{$prefix}popover-zindex: #{$zindex-popover};
--#{$prefix}popover-max-width: #{$popover-max-width};
@include rfs($popover-font-size, --#{$prefix}popover-font-size);
--#{$prefix}popover-bg: #{$popover-bg};
--#{$prefix}popover-border-width: #{$popover-border-width};
--#{$prefix}popover-border-color: #{$popover-border-color};
--#{$prefix}popover-border-radius: #{$popover-border-radius};
--#{$prefix}popover-inner-border-radius: #{$popover-inner-border-radius};
--#{$prefix}popover-box-shadow: #{$popover-box-shadow};
--#{$prefix}popover-header-padding-x: #{$popover-header-padding-x};
--#{$prefix}popover-header-padding-y: #{$popover-header-padding-y};
@include rfs($popover-header-font-size, --#{$prefix}popover-header-font-size);
--#{$prefix}popover-header-color: #{$popover-header-color};
--#{$prefix}popover-header-bg: #{$popover-header-bg};
--#{$prefix}popover-body-padding-x: #{$popover-body-padding-x};
--#{$prefix}popover-body-padding-y: #{$popover-body-padding-y};
--#{$prefix}popover-body-color: #{$popover-body-color};
--#{$prefix}popover-arrow-width: #{$popover-arrow-width};
--#{$prefix}popover-arrow-height: #{$popover-arrow-height};
--#{$prefix}popover-arrow-border: var(--#{$prefix}popover-border-color);
// scss-docs-end popover-css-vars
z-index: var(--#{$prefix}popover-zindex);
display: block;
max-width: var(--#{$prefix}popover-max-width);
// Our parent element can be arbitrary since tooltips are by default inserted as a sibling of their target element.
// So reset our font and text properties to avoid inheriting weird values.
@include reset-text();
@include font-size(var(--#{$prefix}popover-font-size));
// Allow breaking very long words so they don't overflow the popover's bounds
word-wrap: break-word;
background-color: var(--#{$prefix}popover-bg);
background-clip: padding-box;
border: var(--#{$prefix}popover-border-width) solid var(--#{$prefix}popover-border-color);
@include border-radius(var(--#{$prefix}popover-border-radius));
@include box-shadow(var(--#{$prefix}popover-box-shadow));
.popover-arrow {
display: block;
width: var(--#{$prefix}popover-arrow-width);
height: var(--#{$prefix}popover-arrow-height);
&::before,
&::after {
position: absolute;
display: block;
content: "";
border-color: transparent;
border-style: solid;
border-width: 0;
}
}
}
.bs-popover-top {
> .popover-arrow {
bottom: calc(-1 * (var(--#{$prefix}popover-arrow-height)) - var(--#{$prefix}popover-border-width)); // stylelint-disable-line function-disallowed-list
&::before,
&::after {
border-width: var(--#{$prefix}popover-arrow-height) calc(var(--#{$prefix}popover-arrow-width) * .5) 0; // stylelint-disable-line function-disallowed-list
}
&::before {
bottom: 0;
border-top-color: var(--#{$prefix}popover-arrow-border);
}
&::after {
bottom: var(--#{$prefix}popover-border-width);
border-top-color: var(--#{$prefix}popover-bg);
}
}
}
/* rtl:begin:ignore */
.bs-popover-end {
> .popover-arrow {
left: calc(-1 * (var(--#{$prefix}popover-arrow-height)) - var(--#{$prefix}popover-border-width)); // stylelint-disable-line function-disallowed-list
width: var(--#{$prefix}popover-arrow-height);
height: var(--#{$prefix}popover-arrow-width);
&::before,
&::after {
border-width: calc(var(--#{$prefix}popover-arrow-width) * .5) var(--#{$prefix}popover-arrow-height) calc(var(--#{$prefix}popover-arrow-width) * .5) 0; // stylelint-disable-line function-disallowed-list
}
&::before {
left: 0;
border-right-color: var(--#{$prefix}popover-arrow-border);
}
&::after {
left: var(--#{$prefix}popover-border-width);
border-right-color: var(--#{$prefix}popover-bg);
}
}
}
/* rtl:end:ignore */
.bs-popover-bottom {
> .popover-arrow {
top: calc(-1 * (var(--#{$prefix}popover-arrow-height)) - var(--#{$prefix}popover-border-width)); // stylelint-disable-line function-disallowed-list
&::before,
&::after {
border-width: 0 calc(var(--#{$prefix}popover-arrow-width) * .5) var(--#{$prefix}popover-arrow-height); // stylelint-disable-line function-disallowed-list
}
&::before {
top: 0;
border-bottom-color: var(--#{$prefix}popover-arrow-border);
}
&::after {
top: var(--#{$prefix}popover-border-width);
border-bottom-color: var(--#{$prefix}popover-bg);
}
}
// This will remove the popover-header's border just below the arrow
.popover-header::before {
position: absolute;
top: 0;
left: 50%;
display: block;
width: var(--#{$prefix}popover-arrow-width);
margin-left: calc(-.5 * var(--#{$prefix}popover-arrow-width)); // stylelint-disable-line function-disallowed-list
content: "";
border-bottom: var(--#{$prefix}popover-border-width) solid var(--#{$prefix}popover-header-bg);
}
}
/* rtl:begin:ignore */
.bs-popover-start {
> .popover-arrow {
right: calc(-1 * (var(--#{$prefix}popover-arrow-height)) - var(--#{$prefix}popover-border-width)); // stylelint-disable-line function-disallowed-list
width: var(--#{$prefix}popover-arrow-height);
height: var(--#{$prefix}popover-arrow-width);
&::before,
&::after {
border-width: calc(var(--#{$prefix}popover-arrow-width) * .5) 0 calc(var(--#{$prefix}popover-arrow-width) * .5) var(--#{$prefix}popover-arrow-height); // stylelint-disable-line function-disallowed-list
}
&::before {
right: 0;
border-left-color: var(--#{$prefix}popover-arrow-border);
}
&::after {
right: var(--#{$prefix}popover-border-width);
border-left-color: var(--#{$prefix}popover-bg);
}
}
}
/* rtl:end:ignore */
.bs-popover-auto {
&[data-popper-placement^="top"] {
@extend .bs-popover-top;
}
&[data-popper-placement^="right"] {
@extend .bs-popover-end;
}
&[data-popper-placement^="bottom"] {
@extend .bs-popover-bottom;
}
&[data-popper-placement^="left"] {
@extend .bs-popover-start;
}
}
// Offset the popover to account for the popover arrow
.popover-header {
padding: var(--#{$prefix}popover-header-padding-y) var(--#{$prefix}popover-header-padding-x);
margin-bottom: 0; // Reset the default from Reboot
@include font-size(var(--#{$prefix}popover-header-font-size));
color: var(--#{$prefix}popover-header-color);
background-color: var(--#{$prefix}popover-header-bg);
border-bottom: var(--#{$prefix}popover-border-width) solid var(--#{$prefix}popover-border-color);
@include border-top-radius(var(--#{$prefix}popover-inner-border-radius));
&:empty {
display: none;
}
}
.popover-body {
padding: var(--#{$prefix}popover-body-padding-y) var(--#{$prefix}popover-body-padding-x);
color: var(--#{$prefix}popover-body-color);
}

59
src/main/resources/static/assets/_scss/bootstrap/_progress.scss

@ -0,0 +1,59 @@
// Disable animation if transitions are disabled
// scss-docs-start progress-keyframes
@if $enable-transitions {
@keyframes progress-bar-stripes {
0% { background-position-x: $progress-height; }
}
}
// scss-docs-end progress-keyframes
.progress {
// scss-docs-start progress-css-vars
--#{$prefix}progress-height: #{$progress-height};
@include rfs($progress-font-size, --#{$prefix}progress-font-size);
--#{$prefix}progress-bg: #{$progress-bg};
--#{$prefix}progress-border-radius: #{$progress-border-radius};
--#{$prefix}progress-box-shadow: #{$progress-box-shadow};
--#{$prefix}progress-bar-color: #{$progress-bar-color};
--#{$prefix}progress-bar-bg: #{$progress-bar-bg};
--#{$prefix}progress-bar-transition: #{$progress-bar-transition};
// scss-docs-end progress-css-vars
display: flex;
height: var(--#{$prefix}progress-height);
overflow: hidden; // force rounded corners by cropping it
@include font-size(var(--#{$prefix}progress-font-size));
background-color: var(--#{$prefix}progress-bg);
@include border-radius(var(--#{$prefix}progress-border-radius));
@include box-shadow(var(--#{$prefix}progress-box-shadow));
}
.progress-bar {
display: flex;
flex-direction: column;
justify-content: center;
overflow: hidden;
color: var(--#{$prefix}progress-bar-color);
text-align: center;
white-space: nowrap;
background-color: var(--#{$prefix}progress-bar-bg);
@include transition(var(--#{$prefix}progress-bar-transition));
}
.progress-bar-striped {
@include gradient-striped();
background-size: var(--#{$prefix}progress-height) var(--#{$prefix}progress-height);
}
@if $enable-transitions {
.progress-bar-animated {
animation: $progress-bar-animation-timing progress-bar-stripes;
@if $enable-reduced-motion {
@media (prefers-reduced-motion: reduce) {
animation: none;
}
}
}
}

610
src/main/resources/static/assets/_scss/bootstrap/_reboot.scss

@ -0,0 +1,610 @@
// stylelint-disable declaration-no-important, selector-no-qualifying-type, property-no-vendor-prefix
// Reboot
//
// Normalization of HTML elements, manually forked from Normalize.css to remove
// styles targeting irrelevant browsers while applying new styles.
//
// Normalize is licensed MIT. https://github.com/necolas/normalize.css
// Document
//
// Change from `box-sizing: content-box` so that `width` is not affected by `padding` or `border`.
*,
*::before,
*::after {
box-sizing: border-box;
}
// Root
//
// Ability to the value of the root font sizes, affecting the value of `rem`.
// null by default, thus nothing is generated.
:root {
@if $font-size-root != null {
@include font-size(var(--#{$prefix}root-font-size));
}
@if $enable-smooth-scroll {
@media (prefers-reduced-motion: no-preference) {
scroll-behavior: smooth;
}
}
}
// Body
//
// 1. Remove the margin in all browsers.
// 2. As a best practice, apply a default `background-color`.
// 3. Prevent adjustments of font size after orientation changes in iOS.
// 4. Change the default tap highlight to be completely transparent in iOS.
// scss-docs-start reboot-body-rules
body {
margin: 0; // 1
font-family: var(--#{$prefix}body-font-family);
@include font-size(var(--#{$prefix}body-font-size));
font-weight: var(--#{$prefix}body-font-weight);
line-height: var(--#{$prefix}body-line-height);
color: var(--#{$prefix}body-color);
text-align: var(--#{$prefix}body-text-align);
background-color: var(--#{$prefix}body-bg); // 2
-webkit-text-size-adjust: 100%; // 3
-webkit-tap-highlight-color: rgba($black, 0); // 4
}
// scss-docs-end reboot-body-rules
// Content grouping
//
// 1. Reset Firefox's gray color
hr {
margin: $hr-margin-y 0;
color: $hr-color; // 1
border: 0;
border-top: $hr-border-width solid $hr-border-color;
opacity: $hr-opacity;
}
// Typography
//
// 1. Remove top margins from headings
// By default, `<h1>`-`<h6>` all receive top and bottom margins. We nuke the top
// margin for easier control within type scales as it avoids margin collapsing.
%heading {
margin-top: 0; // 1
margin-bottom: $headings-margin-bottom;
font-family: $headings-font-family;
font-style: $headings-font-style;
font-weight: $headings-font-weight;
line-height: $headings-line-height;
color: $headings-color;
}
h1 {
@extend %heading;
@include font-size($h1-font-size);
}
h2 {
@extend %heading;
@include font-size($h2-font-size);
}
h3 {
@extend %heading;
@include font-size($h3-font-size);
}
h4 {
@extend %heading;
@include font-size($h4-font-size);
}
h5 {
@extend %heading;
@include font-size($h5-font-size);
}
h6 {
@extend %heading;
@include font-size($h6-font-size);
}
// Reset margins on paragraphs
//
// Similarly, the top margin on `<p>`s get reset. However, we also reset the
// bottom margin to use `rem` units instead of `em`.
p {
margin-top: 0;
margin-bottom: $paragraph-margin-bottom;
}
// Abbreviations
//
// 1. Add the correct text decoration in Chrome, Edge, Opera, and Safari.
// 2. Add explicit cursor to indicate changed behavior.
// 3. Prevent the text-decoration to be skipped.
abbr[title] {
text-decoration: underline dotted; // 1
cursor: help; // 2
text-decoration-skip-ink: none; // 3
}
// Address
address {
margin-bottom: 1rem;
font-style: normal;
line-height: inherit;
}
// Lists
ol,
ul {
padding-left: 2rem;
}
ol,
ul,
dl {
margin-top: 0;
margin-bottom: 1rem;
}
ol ol,
ul ul,
ol ul,
ul ol {
margin-bottom: 0;
}
dt {
font-weight: $dt-font-weight;
}
// 1. Undo browser default
dd {
margin-bottom: .5rem;
margin-left: 0; // 1
}
// Blockquote
blockquote {
margin: 0 0 1rem;
}
// Strong
//
// Add the correct font weight in Chrome, Edge, and Safari
b,
strong {
font-weight: $font-weight-bolder;
}
// Small
//
// Add the correct font size in all browsers
small {
@include font-size($small-font-size);
}
// Mark
mark {
padding: $mark-padding;
background-color: var(--#{$prefix}highlight-bg);
}
// Sub and Sup
//
// Prevent `sub` and `sup` elements from affecting the line height in
// all browsers.
sub,
sup {
position: relative;
@include font-size($sub-sup-font-size);
line-height: 0;
vertical-align: baseline;
}
sub { bottom: -.25em; }
sup { top: -.5em; }
// Links
a {
color: var(--#{$prefix}link-color);
text-decoration: $link-decoration;
&:hover {
color: var(--#{$prefix}link-hover-color);
text-decoration: $link-hover-decoration;
}
}
// And undo these styles for placeholder links/named anchors (without href).
// It would be more straightforward to just use a[href] in previous block, but that
// causes specificity issues in many other styles that are too complex to fix.
// See https://github.com/twbs/bootstrap/issues/19402
a:not([href]):not([class]) {
&,
&:hover {
color: inherit;
text-decoration: none;
}
}
// Code
pre,
code,
kbd,
samp {
font-family: $font-family-code;
@include font-size(1em); // Correct the odd `em` font sizing in all browsers.
}
// 1. Remove browser default top margin
// 2. Reset browser default of `1em` to use `rem`s
// 3. Don't allow content to break outside
pre {
display: block;
margin-top: 0; // 1
margin-bottom: 1rem; // 2
overflow: auto; // 3
@include font-size($code-font-size);
color: $pre-color;
// Account for some code outputs that place code tags in pre tags
code {
@include font-size(inherit);
color: inherit;
word-break: normal;
}
}
code {
@include font-size($code-font-size);
color: var(--#{$prefix}code-color);
word-wrap: break-word;
// Streamline the style when inside anchors to avoid broken underline and more
a > & {
color: inherit;
}
}
kbd {
padding: $kbd-padding-y $kbd-padding-x;
@include font-size($kbd-font-size);
color: $kbd-color;
background-color: $kbd-bg;
@include border-radius($border-radius-sm);
kbd {
padding: 0;
@include font-size(1em);
font-weight: $nested-kbd-font-weight;
}
}
// Figures
//
// Apply a consistent margin strategy (matches our type styles).
figure {
margin: 0 0 1rem;
}
// Images and content
img,
svg {
vertical-align: middle;
}
// Tables
//
// Prevent double borders
table {
caption-side: bottom;
border-collapse: collapse;
}
caption {
padding-top: $table-cell-padding-y;
padding-bottom: $table-cell-padding-y;
color: $table-caption-color;
text-align: left;
}
// 1. Removes font-weight bold by inheriting
// 2. Matches default `<td>` alignment by inheriting `text-align`.
// 3. Fix alignment for Safari
th {
font-weight: $table-th-font-weight; // 1
text-align: inherit; // 2
text-align: -webkit-match-parent; // 3
}
thead,
tbody,
tfoot,
tr,
td,
th {
border-color: inherit;
border-style: solid;
border-width: 0;
}
// Forms
//
// 1. Allow labels to use `margin` for spacing.
label {
display: inline-block; // 1
}
// Remove the default `border-radius` that macOS Chrome adds.
// See https://github.com/twbs/bootstrap/issues/24093
button {
// stylelint-disable-next-line property-disallowed-list
border-radius: 0;
}
// Explicitly remove focus outline in Chromium when it shouldn't be
// visible (e.g. as result of mouse click or touch tap). It already
// should be doing this automatically, but seems to currently be
// confused and applies its very visible two-tone outline anyway.
button:focus:not(:focus-visible) {
outline: 0;
}
// 1. Remove the margin in Firefox and Safari
input,
button,
select,
optgroup,
textarea {
margin: 0; // 1
font-family: inherit;
@include font-size(inherit);
line-height: inherit;
}
// Remove the inheritance of text transform in Firefox
button,
select {
text-transform: none;
}
// Set the cursor for non-`<button>` buttons
//
// Details at https://github.com/twbs/bootstrap/pull/30562
[role="button"] {
cursor: pointer;
}
select {
// Remove the inheritance of word-wrap in Safari.
// See https://github.com/twbs/bootstrap/issues/24990
word-wrap: normal;
// Undo the opacity change from Chrome
&:disabled {
opacity: 1;
}
}
// Remove the dropdown arrow only from text type inputs built with datalists in Chrome.
// See https://stackoverflow.com/a/54997118
[list]:not([type="date"]):not([type="datetime-local"]):not([type="month"]):not([type="week"]):not([type="time"])::-webkit-calendar-picker-indicator {
display: none !important;
}
// 1. Prevent a WebKit bug where (2) destroys native `audio` and `video`
// controls in Android 4.
// 2. Correct the inability to style clickable types in iOS and Safari.
// 3. Opinionated: add "hand" cursor to non-disabled button elements.
button,
[type="button"], // 1
[type="reset"],
[type="submit"] {
-webkit-appearance: button; // 2
@if $enable-button-pointers {
&:not(:disabled) {
cursor: pointer; // 3
}
}
}
// Remove inner border and padding from Firefox, but don't restore the outline like Normalize.
::-moz-focus-inner {
padding: 0;
border-style: none;
}
// 1. Textareas should really only resize vertically so they don't break their (horizontal) containers.
textarea {
resize: vertical; // 1
}
// 1. Browsers set a default `min-width: min-content;` on fieldsets,
// unlike e.g. `<div>`s, which have `min-width: 0;` by default.
// So we reset that to ensure fieldsets behave more like a standard block element.
// See https://github.com/twbs/bootstrap/issues/12359
// and https://html.spec.whatwg.org/multipage/#the-fieldset-and-legend-elements
// 2. Reset the default outline behavior of fieldsets so they don't affect page layout.
fieldset {
min-width: 0; // 1
padding: 0; // 2
margin: 0; // 2
border: 0; // 2
}
// 1. By using `float: left`, the legend will behave like a block element.
// This way the border of a fieldset wraps around the legend if present.
// 2. Fix wrapping bug.
// See https://github.com/twbs/bootstrap/issues/29712
legend {
float: left; // 1
width: 100%;
padding: 0;
margin-bottom: $legend-margin-bottom;
@include font-size($legend-font-size);
font-weight: $legend-font-weight;
line-height: inherit;
+ * {
clear: left; // 2
}
}
// Fix height of inputs with a type of datetime-local, date, month, week, or time
// See https://github.com/twbs/bootstrap/issues/18842
::-webkit-datetime-edit-fields-wrapper,
::-webkit-datetime-edit-text,
::-webkit-datetime-edit-minute,
::-webkit-datetime-edit-hour-field,
::-webkit-datetime-edit-day-field,
::-webkit-datetime-edit-month-field,
::-webkit-datetime-edit-year-field {
padding: 0;
}
::-webkit-inner-spin-button {
height: auto;
}
// 1. Correct the outline style in Safari.
// 2. This overrides the extra rounded corners on search inputs in iOS so that our
// `.form-control` class can properly style them. Note that this cannot simply
// be added to `.form-control` as it's not specific enough. For details, see
// https://github.com/twbs/bootstrap/issues/11586.
[type="search"] {
outline-offset: -2px; // 1
-webkit-appearance: textfield; // 2
}
// 1. A few input types should stay LTR
// See https://rtlstyling.com/posts/rtl-styling#form-inputs
// 2. RTL only output
// See https://rtlcss.com/learn/usage-guide/control-directives/#raw
/* rtl:raw:
[type="tel"],
[type="url"],
[type="email"],
[type="number"] {
direction: ltr;
}
*/
// Remove the inner padding in Chrome and Safari on macOS.
::-webkit-search-decoration {
-webkit-appearance: none;
}
// Remove padding around color pickers in webkit browsers
::-webkit-color-swatch-wrapper {
padding: 0;
}
// 1. Inherit font family and line height for file input buttons
// 2. Correct the inability to style clickable types in iOS and Safari.
::file-selector-button {
font: inherit; // 1
-webkit-appearance: button; // 2
}
// Correct element displays
output {
display: inline-block;
}
// Remove border from iframe
iframe {
border: 0;
}
// Summary
//
// 1. Add the correct display in all browsers
summary {
display: list-item; // 1
cursor: pointer;
}
// Progress
//
// Add the correct vertical alignment in Chrome, Firefox, and Opera.
progress {
vertical-align: baseline;
}
// Hidden attribute
//
// Always hide an element with the `hidden` HTML attribute.
[hidden] {
display: none !important;
}

73
src/main/resources/static/assets/_scss/bootstrap/_root.scss

@ -0,0 +1,73 @@
:root {
// Note: Custom variable values only support SassScript inside `#{}`.
// Colors
//
// Generate palettes for full colors, grays, and theme colors.
@each $color, $value in $colors {
--#{$prefix}#{$color}: #{$value};
}
@each $color, $value in $grays {
--#{$prefix}gray-#{$color}: #{$value};
}
@each $color, $value in $theme-colors {
--#{$prefix}#{$color}: #{$value};
}
@each $color, $value in $theme-colors-rgb {
--#{$prefix}#{$color}-rgb: #{$value};
}
--#{$prefix}white-rgb: #{to-rgb($white)};
--#{$prefix}black-rgb: #{to-rgb($black)};
--#{$prefix}body-color-rgb: #{to-rgb($body-color)};
--#{$prefix}body-bg-rgb: #{to-rgb($body-bg)};
// Fonts
// Note: Use `inspect` for lists so that quoted items keep the quotes.
// See https://github.com/sass/sass/issues/2383#issuecomment-336349172
--#{$prefix}font-sans-serif: #{inspect($font-family-sans-serif)};
--#{$prefix}font-monospace: #{inspect($font-family-monospace)};
--#{$prefix}gradient: #{$gradient};
// Root and body
// scss-docs-start root-body-variables
@if $font-size-root != null {
--#{$prefix}root-font-size: #{$font-size-root};
}
--#{$prefix}body-font-family: #{$font-family-base};
@include rfs($font-size-base, --#{$prefix}body-font-size);
--#{$prefix}body-font-weight: #{$font-weight-base};
--#{$prefix}body-line-height: #{$line-height-base};
--#{$prefix}body-color: #{$body-color};
@if $body-text-align != null {
--#{$prefix}body-text-align: #{$body-text-align};
}
--#{$prefix}body-bg: #{$body-bg};
// scss-docs-end root-body-variables
// scss-docs-start root-border-var
--#{$prefix}border-width: #{$border-width};
--#{$prefix}border-style: #{$border-style};
--#{$prefix}border-color: #{$border-color};
--#{$prefix}border-color-translucent: #{$border-color-translucent};
--#{$prefix}border-radius: #{$border-radius};
--#{$prefix}border-radius-sm: #{$border-radius-sm};
--#{$prefix}border-radius-lg: #{$border-radius-lg};
--#{$prefix}border-radius-xl: #{$border-radius-xl};
--#{$prefix}border-radius-2xl: #{$border-radius-2xl};
--#{$prefix}border-radius-pill: #{$border-radius-pill};
// scss-docs-end root-border-var
--#{$prefix}link-color: #{$link-color};
--#{$prefix}link-hover-color: #{$link-hover-color};
--#{$prefix}code-color: #{$code-color};
--#{$prefix}highlight-bg: #{$mark-bg};
}

85
src/main/resources/static/assets/_scss/bootstrap/_spinners.scss

@ -0,0 +1,85 @@
//
// Rotating border
//
.spinner-grow,
.spinner-border {
display: inline-block;
width: var(--#{$prefix}spinner-width);
height: var(--#{$prefix}spinner-height);
vertical-align: var(--#{$prefix}spinner-vertical-align);
// stylelint-disable-next-line property-disallowed-list
border-radius: 50%;
animation: var(--#{$prefix}spinner-animation-speed) linear infinite var(--#{$prefix}spinner-animation-name);
}
// scss-docs-start spinner-border-keyframes
@keyframes spinner-border {
to { transform: rotate(360deg) #{"/* rtl:ignore */"}; }
}
// scss-docs-end spinner-border-keyframes
.spinner-border {
// scss-docs-start spinner-border-css-vars
--#{$prefix}spinner-width: #{$spinner-width};
--#{$prefix}spinner-height: #{$spinner-height};
--#{$prefix}spinner-vertical-align: #{$spinner-vertical-align};
--#{$prefix}spinner-border-width: #{$spinner-border-width};
--#{$prefix}spinner-animation-speed: #{$spinner-animation-speed};
--#{$prefix}spinner-animation-name: spinner-border;
// scss-docs-end spinner-border-css-vars
border: var(--#{$prefix}spinner-border-width) solid currentcolor;
border-right-color: transparent;
}
.spinner-border-sm {
// scss-docs-start spinner-border-sm-css-vars
--#{$prefix}spinner-width: #{$spinner-width-sm};
--#{$prefix}spinner-height: #{$spinner-height-sm};
--#{$prefix}spinner-border-width: #{$spinner-border-width-sm};
// scss-docs-end spinner-border-sm-css-vars
}
//
// Growing circle
//
// scss-docs-start spinner-grow-keyframes
@keyframes spinner-grow {
0% {
transform: scale(0);
}
50% {
opacity: 1;
transform: none;
}
}
// scss-docs-end spinner-grow-keyframes
.spinner-grow {
// scss-docs-start spinner-grow-css-vars
--#{$prefix}spinner-width: #{$spinner-width};
--#{$prefix}spinner-height: #{$spinner-height};
--#{$prefix}spinner-vertical-align: #{$spinner-vertical-align};
--#{$prefix}spinner-animation-speed: #{$spinner-animation-speed};
--#{$prefix}spinner-animation-name: spinner-grow;
// scss-docs-end spinner-grow-css-vars
background-color: currentcolor;
opacity: 0;
}
.spinner-grow-sm {
--#{$prefix}spinner-width: #{$spinner-width-sm};
--#{$prefix}spinner-height: #{$spinner-height-sm};
}
@if $enable-reduced-motion {
@media (prefers-reduced-motion: reduce) {
.spinner-border,
.spinner-grow {
--#{$prefix}spinner-animation-speed: #{$spinner-animation-speed * 2};
}
}
}

164
src/main/resources/static/assets/_scss/bootstrap/_tables.scss

@ -0,0 +1,164 @@
//
// Basic Bootstrap table
//
.table {
--#{$prefix}table-color: #{$table-color};
--#{$prefix}table-bg: #{$table-bg};
--#{$prefix}table-border-color: #{$table-border-color};
--#{$prefix}table-accent-bg: #{$table-accent-bg};
--#{$prefix}table-striped-color: #{$table-striped-color};
--#{$prefix}table-striped-bg: #{$table-striped-bg};
--#{$prefix}table-active-color: #{$table-active-color};
--#{$prefix}table-active-bg: #{$table-active-bg};
--#{$prefix}table-hover-color: #{$table-hover-color};
--#{$prefix}table-hover-bg: #{$table-hover-bg};
width: 100%;
margin-bottom: $spacer;
color: var(--#{$prefix}table-color);
vertical-align: $table-cell-vertical-align;
border-color: var(--#{$prefix}table-border-color);
// Target th & td
// We need the child combinator to prevent styles leaking to nested tables which doesn't have a `.table` class.
// We use the universal selectors here to simplify the selector (else we would need 6 different selectors).
// Another advantage is that this generates less code and makes the selector less specific making it easier to override.
// stylelint-disable-next-line selector-max-universal
> :not(caption) > * > * {
padding: $table-cell-padding-y $table-cell-padding-x;
background-color: var(--#{$prefix}table-bg);
border-bottom-width: $table-border-width;
box-shadow: inset 0 0 0 9999px var(--#{$prefix}table-accent-bg);
}
> tbody {
vertical-align: inherit;
}
> thead {
vertical-align: bottom;
}
}
.table-group-divider {
border-top: ($table-border-width * 2) solid $table-group-separator-color;
}
//
// Change placement of captions with a class
//
.caption-top {
caption-side: top;
}
//
// Condensed table w/ half padding
//
.table-sm {
// stylelint-disable-next-line selector-max-universal
> :not(caption) > * > * {
padding: $table-cell-padding-y-sm $table-cell-padding-x-sm;
}
}
// Border versions
//
// Add or remove borders all around the table and between all the columns.
//
// When borders are added on all sides of the cells, the corners can render odd when
// these borders do not have the same color or if they are semi-transparent.
// Therefor we add top and border bottoms to the `tr`s and left and right borders
// to the `td`s or `th`s
.table-bordered {
> :not(caption) > * {
border-width: $table-border-width 0;
// stylelint-disable-next-line selector-max-universal
> * {
border-width: 0 $table-border-width;
}
}
}
.table-borderless {
// stylelint-disable-next-line selector-max-universal
> :not(caption) > * > * {
border-bottom-width: 0;
}
> :not(:first-child) {
border-top-width: 0;
}
}
// Zebra-striping
//
// Default zebra-stripe styles (alternating gray and transparent backgrounds)
// For rows
.table-striped {
> tbody > tr:nth-of-type(#{$table-striped-order}) > * {
--#{$prefix}table-accent-bg: var(--#{$prefix}table-striped-bg);
color: var(--#{$prefix}table-striped-color);
}
}
// For columns
.table-striped-columns {
> :not(caption) > tr > :nth-child(#{$table-striped-columns-order}) {
--#{$prefix}table-accent-bg: var(--#{$prefix}table-striped-bg);
color: var(--#{$prefix}table-striped-color);
}
}
// Active table
//
// The `.table-active` class can be added to highlight rows or cells
.table-active {
--#{$prefix}table-accent-bg: var(--#{$prefix}table-active-bg);
color: var(--#{$prefix}table-active-color);
}
// Hover effect
//
// Placed here since it has to come after the potential zebra striping
.table-hover {
> tbody > tr:hover > * {
--#{$prefix}table-accent-bg: var(--#{$prefix}table-hover-bg);
color: var(--#{$prefix}table-hover-color);
}
}
// Table variants
//
// Table variants set the table cell backgrounds, border colors
// and the colors of the striped, hovered & active tables
@each $color, $value in $table-variants {
@include table-variant($color, $value);
}
// Responsive tables
//
// Generate series of `.table-responsive-*` classes for configuring the screen
// size of where your table will overflow.
@each $breakpoint in map-keys($grid-breakpoints) {
$infix: breakpoint-infix($breakpoint, $grid-breakpoints);
@include media-breakpoint-down($breakpoint) {
.table-responsive#{$infix} {
overflow-x: auto;
-webkit-overflow-scrolling: touch;
}
}
}

73
src/main/resources/static/assets/_scss/bootstrap/_toasts.scss

@ -0,0 +1,73 @@
.toast {
// scss-docs-start toast-css-vars
--#{$prefix}toast-zindex: #{$zindex-toast};
--#{$prefix}toast-padding-x: #{$toast-padding-x};
--#{$prefix}toast-padding-y: #{$toast-padding-y};
--#{$prefix}toast-spacing: #{$toast-spacing};
--#{$prefix}toast-max-width: #{$toast-max-width};
@include rfs($toast-font-size, --#{$prefix}toast-font-size);
--#{$prefix}toast-color: #{$toast-color};
--#{$prefix}toast-bg: #{$toast-background-color};
--#{$prefix}toast-border-width: #{$toast-border-width};
--#{$prefix}toast-border-color: #{$toast-border-color};
--#{$prefix}toast-border-radius: #{$toast-border-radius};
--#{$prefix}toast-box-shadow: #{$toast-box-shadow};
--#{$prefix}toast-header-color: #{$toast-header-color};
--#{$prefix}toast-header-bg: #{$toast-header-background-color};
--#{$prefix}toast-header-border-color: #{$toast-header-border-color};
// scss-docs-end toast-css-vars
width: var(--#{$prefix}toast-max-width);
max-width: 100%;
@include font-size(var(--#{$prefix}toast-font-size));
color: var(--#{$prefix}toast-color);
pointer-events: auto;
background-color: var(--#{$prefix}toast-bg);
background-clip: padding-box;
border: var(--#{$prefix}toast-border-width) solid var(--#{$prefix}toast-border-color);
box-shadow: var(--#{$prefix}toast-box-shadow);
@include border-radius(var(--#{$prefix}toast-border-radius));
&.showing {
opacity: 0;
}
&:not(.show) {
display: none;
}
}
.toast-container {
--#{$prefix}toast-zindex: #{$zindex-toast};
position: absolute;
z-index: var(--#{$prefix}toast-zindex);
width: max-content;
max-width: 100%;
pointer-events: none;
> :not(:last-child) {
margin-bottom: var(--#{$prefix}toast-spacing);
}
}
.toast-header {
display: flex;
align-items: center;
padding: var(--#{$prefix}toast-padding-y) var(--#{$prefix}toast-padding-x);
color: var(--#{$prefix}toast-header-color);
background-color: var(--#{$prefix}toast-header-bg);
background-clip: padding-box;
border-bottom: var(--#{$prefix}toast-border-width) solid var(--#{$prefix}toast-header-border-color);
@include border-top-radius(calc(var(--#{$prefix}toast-border-radius) - var(--#{$prefix}toast-border-width)));
.btn-close {
margin-right: calc(-.5 * var(--#{$prefix}toast-padding-x)); // stylelint-disable-line function-disallowed-list
margin-left: var(--#{$prefix}toast-padding-x);
}
}
.toast-body {
padding: var(--#{$prefix}toast-padding-x);
word-wrap: break-word;
}

120
src/main/resources/static/assets/_scss/bootstrap/_tooltip.scss

@ -0,0 +1,120 @@
// Base class
.tooltip {
// scss-docs-start tooltip-css-vars
--#{$prefix}tooltip-zindex: #{$zindex-tooltip};
--#{$prefix}tooltip-max-width: #{$tooltip-max-width};
--#{$prefix}tooltip-padding-x: #{$tooltip-padding-x};
--#{$prefix}tooltip-padding-y: #{$tooltip-padding-y};
--#{$prefix}tooltip-margin: #{$tooltip-margin};
@include rfs($tooltip-font-size, --#{$prefix}tooltip-font-size);
--#{$prefix}tooltip-color: #{$tooltip-color};
--#{$prefix}tooltip-bg: #{$tooltip-bg};
--#{$prefix}tooltip-border-radius: #{$tooltip-border-radius};
--#{$prefix}tooltip-opacity: #{$tooltip-opacity};
--#{$prefix}tooltip-arrow-width: #{$tooltip-arrow-width};
--#{$prefix}tooltip-arrow-height: #{$tooltip-arrow-height};
// scss-docs-end tooltip-css-vars
z-index: var(--#{$prefix}tooltip-zindex);
display: block;
padding: var(--#{$prefix}tooltip-arrow-height);
margin: var(--#{$prefix}tooltip-margin);
@include deprecate("`$tooltip-margin`", "v5", "v5.x", true);
// Our parent element can be arbitrary since tooltips are by default inserted as a sibling of their target element.
// So reset our font and text properties to avoid inheriting weird values.
@include reset-text();
@include font-size(var(--#{$prefix}tooltip-font-size));
// Allow breaking very long words so they don't overflow the tooltip's bounds
word-wrap: break-word;
opacity: 0;
&.show { opacity: var(--#{$prefix}tooltip-opacity); }
.tooltip-arrow {
display: block;
width: var(--#{$prefix}tooltip-arrow-width);
height: var(--#{$prefix}tooltip-arrow-height);
&::before {
position: absolute;
content: "";
border-color: transparent;
border-style: solid;
}
}
}
.bs-tooltip-top .tooltip-arrow {
bottom: 0;
&::before {
top: -1px;
border-width: var(--#{$prefix}tooltip-arrow-height) calc(var(--#{$prefix}tooltip-arrow-width) * .5) 0; // stylelint-disable-line function-disallowed-list
border-top-color: var(--#{$prefix}tooltip-bg);
}
}
/* rtl:begin:ignore */
.bs-tooltip-end .tooltip-arrow {
left: 0;
width: var(--#{$prefix}tooltip-arrow-height);
height: var(--#{$prefix}tooltip-arrow-width);
&::before {
right: -1px;
border-width: calc(var(--#{$prefix}tooltip-arrow-width) * .5) var(--#{$prefix}tooltip-arrow-height) calc(var(--#{$prefix}tooltip-arrow-width) * .5) 0; // stylelint-disable-line function-disallowed-list
border-right-color: var(--#{$prefix}tooltip-bg);
}
}
/* rtl:end:ignore */
.bs-tooltip-bottom .tooltip-arrow {
top: 0;
&::before {
bottom: -1px;
border-width: 0 calc(var(--#{$prefix}tooltip-arrow-width) * .5) var(--#{$prefix}tooltip-arrow-height); // stylelint-disable-line function-disallowed-list
border-bottom-color: var(--#{$prefix}tooltip-bg);
}
}
/* rtl:begin:ignore */
.bs-tooltip-start .tooltip-arrow {
right: 0;
width: var(--#{$prefix}tooltip-arrow-height);
height: var(--#{$prefix}tooltip-arrow-width);
&::before {
left: -1px;
border-width: calc(var(--#{$prefix}tooltip-arrow-width) * .5) 0 calc(var(--#{$prefix}tooltip-arrow-width) * .5) var(--#{$prefix}tooltip-arrow-height); // stylelint-disable-line function-disallowed-list
border-left-color: var(--#{$prefix}tooltip-bg);
}
}
/* rtl:end:ignore */
.bs-tooltip-auto {
&[data-popper-placement^="top"] {
@extend .bs-tooltip-top;
}
&[data-popper-placement^="right"] {
@extend .bs-tooltip-end;
}
&[data-popper-placement^="bottom"] {
@extend .bs-tooltip-bottom;
}
&[data-popper-placement^="left"] {
@extend .bs-tooltip-start;
}
}
// Wrapper for the tooltip content
.tooltip-inner {
max-width: var(--#{$prefix}tooltip-max-width);
padding: var(--#{$prefix}tooltip-padding-y) var(--#{$prefix}tooltip-padding-x);
color: var(--#{$prefix}tooltip-color);
text-align: center;
background-color: var(--#{$prefix}tooltip-bg);
@include border-radius(var(--#{$prefix}tooltip-border-radius));
}

27
src/main/resources/static/assets/_scss/bootstrap/_transitions.scss

@ -0,0 +1,27 @@
.fade {
@include transition($transition-fade);
&:not(.show) {
opacity: 0;
}
}
// scss-docs-start collapse-classes
.collapse {
&:not(.show) {
display: none;
}
}
.collapsing {
height: 0;
overflow: hidden;
@include transition($transition-collapse);
&.collapse-horizontal {
width: 0;
height: auto;
@include transition($transition-collapse-width);
}
}
// scss-docs-end collapse-classes

106
src/main/resources/static/assets/_scss/bootstrap/_type.scss

@ -0,0 +1,106 @@
//
// Headings
//
.h1 {
@extend h1;
}
.h2 {
@extend h2;
}
.h3 {
@extend h3;
}
.h4 {
@extend h4;
}
.h5 {
@extend h5;
}
.h6 {
@extend h6;
}
.lead {
@include font-size($lead-font-size);
font-weight: $lead-font-weight;
}
// Type display classes
@each $display, $font-size in $display-font-sizes {
.display-#{$display} {
@include font-size($font-size);
font-family: $display-font-family;
font-style: $display-font-style;
font-weight: $display-font-weight;
line-height: $display-line-height;
}
}
//
// Emphasis
//
.small {
@extend small;
}
.mark {
@extend mark;
}
//
// Lists
//
.list-unstyled {
@include list-unstyled();
}
// Inline turns list items into inline-block
.list-inline {
@include list-unstyled();
}
.list-inline-item {
display: inline-block;
&:not(:last-child) {
margin-right: $list-inline-padding;
}
}
//
// Misc
//
// Builds on `abbr`
.initialism {
@include font-size($initialism-font-size);
text-transform: uppercase;
}
// Blockquotes
.blockquote {
margin-bottom: $blockquote-margin-y;
@include font-size($blockquote-font-size);
> :last-child {
margin-bottom: 0;
}
}
.blockquote-footer {
margin-top: -$blockquote-margin-y;
margin-bottom: $blockquote-margin-y;
@include font-size($blockquote-footer-font-size);
color: $blockquote-footer-color;
&::before {
content: "\2014\00A0"; // em dash, nbsp
}
}

647
src/main/resources/static/assets/_scss/bootstrap/_utilities.scss

@ -0,0 +1,647 @@
// Utilities
$utilities: () !default;
// stylelint-disable-next-line scss/dollar-variable-default
$utilities: map-merge(
(
// scss-docs-start utils-vertical-align
"align": (
property: vertical-align,
class: align,
values: baseline top middle bottom text-bottom text-top
),
// scss-docs-end utils-vertical-align
// scss-docs-start utils-float
"float": (
responsive: true,
property: float,
values: (
start: left,
end: right,
none: none,
)
),
// scss-docs-end utils-float
// Opacity utilities
// scss-docs-start utils-opacity
"opacity": (
property: opacity,
values: (
0: 0,
25: .25,
50: .5,
75: .75,
100: 1,
)
),
// scss-docs-end utils-opacity
// scss-docs-start utils-overflow
"overflow": (
property: overflow,
values: auto hidden visible scroll,
),
// scss-docs-end utils-overflow
// scss-docs-start utils-display
"display": (
responsive: true,
print: true,
property: display,
class: d,
values: inline inline-block block grid table table-row table-cell flex inline-flex none
),
// scss-docs-end utils-display
// scss-docs-start utils-shadow
"shadow": (
property: box-shadow,
class: shadow,
values: (
null: $box-shadow,
sm: $box-shadow-sm,
lg: $box-shadow-lg,
none: none,
)
),
// scss-docs-end utils-shadow
// scss-docs-start utils-position
"position": (
property: position,
values: static relative absolute fixed sticky
),
"top": (
property: top,
values: $position-values
),
"bottom": (
property: bottom,
values: $position-values
),
"start": (
property: left,
class: start,
values: $position-values
),
"end": (
property: right,
class: end,
values: $position-values
),
"translate-middle": (
property: transform,
class: translate-middle,
values: (
null: translate(-50%, -50%),
x: translateX(-50%),
y: translateY(-50%),
)
),
// scss-docs-end utils-position
// scss-docs-start utils-borders
"border": (
property: border,
values: (
null: var(--#{$prefix}border-width) var(--#{$prefix}border-style) var(--#{$prefix}border-color),
0: 0,
)
),
"border-top": (
property: border-top,
values: (
null: var(--#{$prefix}border-width) var(--#{$prefix}border-style) var(--#{$prefix}border-color),
0: 0,
)
),
"border-end": (
property: border-right,
class: border-end,
values: (
null: var(--#{$prefix}border-width) var(--#{$prefix}border-style) var(--#{$prefix}border-color),
0: 0,
)
),
"border-bottom": (
property: border-bottom,
values: (
null: var(--#{$prefix}border-width) var(--#{$prefix}border-style) var(--#{$prefix}border-color),
0: 0,
)
),
"border-start": (
property: border-left,
class: border-start,
values: (
null: var(--#{$prefix}border-width) var(--#{$prefix}border-style) var(--#{$prefix}border-color),
0: 0,
)
),
"border-color": (
property: border-color,
class: border,
local-vars: (
"border-opacity": 1
),
values: $utilities-border-colors
),
"border-width": (
css-var: true,
css-variable-name: border-width,
class: border,
values: $border-widths
),
"border-opacity": (
css-var: true,
class: border-opacity,
values: (
10: .1,
25: .25,
50: .5,
75: .75,
100: 1
)
),
// scss-docs-end utils-borders
// Sizing utilities
// scss-docs-start utils-sizing
"width": (
property: width,
class: w,
values: (
25: 25%,
50: 50%,
75: 75%,
100: 100%,
auto: auto
)
),
"max-width": (
property: max-width,
class: mw,
values: (100: 100%)
),
"viewport-width": (
property: width,
class: vw,
values: (100: 100vw)
),
"min-viewport-width": (
property: min-width,
class: min-vw,
values: (100: 100vw)
),
"height": (
property: height,
class: h,
values: (
25: 25%,
50: 50%,
75: 75%,
100: 100%,
auto: auto
)
),
"max-height": (
property: max-height,
class: mh,
values: (100: 100%)
),
"viewport-height": (
property: height,
class: vh,
values: (100: 100vh)
),
"min-viewport-height": (
property: min-height,
class: min-vh,
values: (100: 100vh)
),
// scss-docs-end utils-sizing
// Flex utilities
// scss-docs-start utils-flex
"flex": (
responsive: true,
property: flex,
values: (fill: 1 1 auto)
),
"flex-direction": (
responsive: true,
property: flex-direction,
class: flex,
values: row column row-reverse column-reverse
),
"flex-grow": (
responsive: true,
property: flex-grow,
class: flex,
values: (
grow-0: 0,
grow-1: 1,
)
),
"flex-shrink": (
responsive: true,
property: flex-shrink,
class: flex,
values: (
shrink-0: 0,
shrink-1: 1,
)
),
"flex-wrap": (
responsive: true,
property: flex-wrap,
class: flex,
values: wrap nowrap wrap-reverse
),
"justify-content": (
responsive: true,
property: justify-content,
values: (
start: flex-start,
end: flex-end,
center: center,
between: space-between,
around: space-around,
evenly: space-evenly,
)
),
"align-items": (
responsive: true,
property: align-items,
values: (
start: flex-start,
end: flex-end,
center: center,
baseline: baseline,
stretch: stretch,
)
),
"align-content": (
responsive: true,
property: align-content,
values: (
start: flex-start,
end: flex-end,
center: center,
between: space-between,
around: space-around,
stretch: stretch,
)
),
"align-self": (
responsive: true,
property: align-self,
values: (
auto: auto,
start: flex-start,
end: flex-end,
center: center,
baseline: baseline,
stretch: stretch,
)
),
"order": (
responsive: true,
property: order,
values: (
first: -1,
0: 0,
1: 1,
2: 2,
3: 3,
4: 4,
5: 5,
last: 6,
),
),
// scss-docs-end utils-flex
// Margin utilities
// scss-docs-start utils-spacing
"margin": (
responsive: true,
property: margin,
class: m,
values: map-merge($spacers, (auto: auto))
),
"margin-x": (
responsive: true,
property: margin-right margin-left,
class: mx,
values: map-merge($spacers, (auto: auto))
),
"margin-y": (
responsive: true,
property: margin-top margin-bottom,
class: my,
values: map-merge($spacers, (auto: auto))
),
"margin-top": (
responsive: true,
property: margin-top,
class: mt,
values: map-merge($spacers, (auto: auto))
),
"margin-end": (
responsive: true,
property: margin-right,
class: me,
values: map-merge($spacers, (auto: auto))
),
"margin-bottom": (
responsive: true,
property: margin-bottom,
class: mb,
values: map-merge($spacers, (auto: auto))
),
"margin-start": (
responsive: true,
property: margin-left,
class: ms,
values: map-merge($spacers, (auto: auto))
),
// Negative margin utilities
"negative-margin": (
responsive: true,
property: margin,
class: m,
values: $negative-spacers
),
"negative-margin-x": (
responsive: true,
property: margin-right margin-left,
class: mx,
values: $negative-spacers
),
"negative-margin-y": (
responsive: true,
property: margin-top margin-bottom,
class: my,
values: $negative-spacers
),
"negative-margin-top": (
responsive: true,
property: margin-top,
class: mt,
values: $negative-spacers
),
"negative-margin-end": (
responsive: true,
property: margin-right,
class: me,
values: $negative-spacers
),
"negative-margin-bottom": (
responsive: true,
property: margin-bottom,
class: mb,
values: $negative-spacers
),
"negative-margin-start": (
responsive: true,
property: margin-left,
class: ms,
values: $negative-spacers
),
// Padding utilities
"padding": (
responsive: true,
property: padding,
class: p,
values: $spacers
),
"padding-x": (
responsive: true,
property: padding-right padding-left,
class: px,
values: $spacers
),
"padding-y": (
responsive: true,
property: padding-top padding-bottom,
class: py,
values: $spacers
),
"padding-top": (
responsive: true,
property: padding-top,
class: pt,
values: $spacers
),
"padding-end": (
responsive: true,
property: padding-right,
class: pe,
values: $spacers
),
"padding-bottom": (
responsive: true,
property: padding-bottom,
class: pb,
values: $spacers
),
"padding-start": (
responsive: true,
property: padding-left,
class: ps,
values: $spacers
),
// Gap utility
"gap": (
responsive: true,
property: gap,
class: gap,
values: $spacers
),
// scss-docs-end utils-spacing
// Text
// scss-docs-start utils-text
"font-family": (
property: font-family,
class: font,
values: (monospace: var(--#{$prefix}font-monospace))
),
"font-size": (
rfs: true,
property: font-size,
class: fs,
values: $font-sizes
),
"font-style": (
property: font-style,
class: fst,
values: italic normal
),
"font-weight": (
property: font-weight,
class: fw,
values: (
light: $font-weight-light,
lighter: $font-weight-lighter,
normal: $font-weight-normal,
bold: $font-weight-bold,
semibold: $font-weight-semibold,
bolder: $font-weight-bolder
)
),
"line-height": (
property: line-height,
class: lh,
values: (
1: 1,
sm: $line-height-sm,
base: $line-height-base,
lg: $line-height-lg,
)
),
"text-align": (
responsive: true,
property: text-align,
class: text,
values: (
start: left,
end: right,
center: center,
)
),
"text-decoration": (
property: text-decoration,
values: none underline line-through
),
"text-transform": (
property: text-transform,
class: text,
values: lowercase uppercase capitalize
),
"white-space": (
property: white-space,
class: text,
values: (
wrap: normal,
nowrap: nowrap,
)
),
"word-wrap": (
property: word-wrap word-break,
class: text,
values: (break: break-word),
rtl: false
),
// scss-docs-end utils-text
// scss-docs-start utils-color
"color": (
property: color,
class: text,
local-vars: (
"text-opacity": 1
),
values: map-merge(
$utilities-text-colors,
(
"muted": $text-muted,
"black-50": rgba($black, .5), // deprecated
"white-50": rgba($white, .5), // deprecated
"reset": inherit,
)
)
),
"text-opacity": (
css-var: true,
class: text-opacity,
values: (
25: .25,
50: .5,
75: .75,
100: 1
)
),
// scss-docs-end utils-color
// scss-docs-start utils-bg-color
"background-color": (
property: background-color,
class: bg,
local-vars: (
"bg-opacity": 1
),
values: map-merge(
$utilities-bg-colors,
(
"transparent": transparent
)
)
),
"bg-opacity": (
css-var: true,
class: bg-opacity,
values: (
10: .1,
25: .25,
50: .5,
75: .75,
100: 1
)
),
// scss-docs-end utils-bg-color
"gradient": (
property: background-image,
class: bg,
values: (gradient: var(--#{$prefix}gradient))
),
// scss-docs-start utils-interaction
"user-select": (
property: user-select,
values: all auto none
),
"pointer-events": (
property: pointer-events,
class: pe,
values: none auto,
),
// scss-docs-end utils-interaction
// scss-docs-start utils-border-radius
"rounded": (
property: border-radius,
class: rounded,
values: (
null: var(--#{$prefix}border-radius),
0: 0,
1: var(--#{$prefix}border-radius-sm),
2: var(--#{$prefix}border-radius),
3: var(--#{$prefix}border-radius-lg),
4: var(--#{$prefix}border-radius-xl),
5: var(--#{$prefix}border-radius-2xl),
circle: 50%,
pill: var(--#{$prefix}border-radius-pill)
)
),
"rounded-top": (
property: border-top-left-radius border-top-right-radius,
class: rounded-top,
values: (null: var(--#{$prefix}border-radius))
),
"rounded-end": (
property: border-top-right-radius border-bottom-right-radius,
class: rounded-end,
values: (null: var(--#{$prefix}border-radius))
),
"rounded-bottom": (
property: border-bottom-right-radius border-bottom-left-radius,
class: rounded-bottom,
values: (null: var(--#{$prefix}border-radius))
),
"rounded-start": (
property: border-bottom-left-radius border-top-left-radius,
class: rounded-start,
values: (null: var(--#{$prefix}border-radius))
),
// scss-docs-end utils-border-radius
// scss-docs-start utils-visibility
"visibility": (
property: visibility,
class: null,
values: (
visible: visible,
invisible: hidden,
)
)
// scss-docs-end utils-visibility
),
$utilities
);

1634
src/main/resources/static/assets/_scss/bootstrap/_variables.scss
File diff suppressed because it is too large
View File

64
src/main/resources/static/assets/_scss/bootstrap/bootstrap-grid.scss

@ -0,0 +1,64 @@
@import "mixins/banner";
@include bsBanner(Grid);
$include-column-box-sizing: true !default;
@import "functions";
@import "variables";
@import "maps";
@import "mixins/lists";
@import "mixins/breakpoints";
@import "mixins/container";
@import "mixins/grid";
@import "mixins/utilities";
@import "vendor/rfs";
@import "root";
@import "containers";
@import "grid";
@import "utilities";
// Only use the utilities we need
// stylelint-disable-next-line scss/dollar-variable-default
$utilities: map-get-multiple(
$utilities,
(
"display",
"order",
"flex",
"flex-direction",
"flex-grow",
"flex-shrink",
"flex-wrap",
"justify-content",
"align-items",
"align-content",
"align-self",
"margin",
"margin-x",
"margin-y",
"margin-top",
"margin-end",
"margin-bottom",
"margin-start",
"negative-margin",
"negative-margin-x",
"negative-margin-y",
"negative-margin-top",
"negative-margin-end",
"negative-margin-bottom",
"negative-margin-start",
"padding",
"padding-x",
"padding-y",
"padding-top",
"padding-end",
"padding-bottom",
"padding-start",
)
);
@import "utilities/api";

9
src/main/resources/static/assets/_scss/bootstrap/bootstrap-reboot.scss

@ -0,0 +1,9 @@
@import "mixins/banner";
@include bsBanner(Reboot);
@import "functions";
@import "variables";
@import "maps";
@import "mixins";
@import "root";
@import "reboot";

18
src/main/resources/static/assets/_scss/bootstrap/bootstrap-utilities.scss

@ -0,0 +1,18 @@
@import "mixins/banner";
@include bsBanner(Utilities);
// Configuration
@import "functions";
@import "variables";
@import "maps";
@import "mixins";
@import "utilities";
// Layout & components
@import "root";
// Helpers
@import "helpers";
// Utilities
@import "utilities/api";

51
src/main/resources/static/assets/_scss/bootstrap/bootstrap.scss

@ -0,0 +1,51 @@
@import "mixins/banner";
@include bsBanner("");
// scss-docs-start import-stack
// Configuration
@import "functions";
@import "variables";
@import "maps";
@import "mixins";
@import "utilities";
// Layout & components
@import "root";
@import "reboot";
@import "type";
@import "images";
@import "containers";
@import "grid";
@import "tables";
@import "forms";
@import "buttons";
@import "transitions";
@import "dropdown";
@import "button-group";
@import "nav";
@import "navbar";
@import "card";
@import "accordion";
@import "breadcrumb";
@import "pagination";
@import "badge";
@import "alert";
@import "progress";
@import "list-group";
@import "close";
@import "toasts";
@import "modal";
@import "tooltip";
@import "popover";
@import "carousel";
@import "spinners";
@import "offcanvas";
@import "placeholders";
// Helpers
@import "helpers";
// Utilities
@import "utilities/api";
// scss-docs-end import-stack

75
src/main/resources/static/assets/_scss/bootstrap/forms/_floating-labels.scss

@ -0,0 +1,75 @@
.form-floating {
position: relative;
> .form-control,
> .form-control-plaintext,
> .form-select {
height: $form-floating-height;
line-height: $form-floating-line-height;
}
> label {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%; // allow textareas
padding: $form-floating-padding-y $form-floating-padding-x;
overflow: hidden;
text-align: start;
text-overflow: ellipsis;
white-space: nowrap;
pointer-events: none;
border: $input-border-width solid transparent; // Required for aligning label's text with the input as it affects inner box model
transform-origin: 0 0;
@include transition($form-floating-transition);
}
> .form-control,
> .form-control-plaintext {
padding: $form-floating-padding-y $form-floating-padding-x;
&::placeholder {
color: transparent;
}
&:focus,
&:not(:placeholder-shown) {
padding-top: $form-floating-input-padding-t;
padding-bottom: $form-floating-input-padding-b;
}
// Duplicated because `:-webkit-autofill` invalidates other selectors when grouped
&:-webkit-autofill {
padding-top: $form-floating-input-padding-t;
padding-bottom: $form-floating-input-padding-b;
}
}
> .form-select {
padding-top: $form-floating-input-padding-t;
padding-bottom: $form-floating-input-padding-b;
}
> .form-control:focus,
> .form-control:not(:placeholder-shown),
> .form-control-plaintext,
> .form-select {
~ label {
opacity: $form-floating-label-opacity;
transform: $form-floating-label-transform;
}
}
// Duplicated because `:-webkit-autofill` invalidates other selectors when grouped
> .form-control:-webkit-autofill {
~ label {
opacity: $form-floating-label-opacity;
transform: $form-floating-label-transform;
}
}
> .form-control-plaintext {
~ label {
border-width: $input-border-width 0; // Required to properly position label text - as explained above
}
}
}

175
src/main/resources/static/assets/_scss/bootstrap/forms/_form-check.scss

@ -0,0 +1,175 @@
//
// Check/radio
//
.form-check {
display: block;
min-height: $form-check-min-height;
padding-left: $form-check-padding-start;
margin-bottom: $form-check-margin-bottom;
.form-check-input {
float: left;
margin-left: $form-check-padding-start * -1;
}
}
.form-check-reverse {
padding-right: $form-check-padding-start;
padding-left: 0;
text-align: right;
.form-check-input {
float: right;
margin-right: $form-check-padding-start * -1;
margin-left: 0;
}
}
.form-check-input {
width: $form-check-input-width;
height: $form-check-input-width;
margin-top: ($line-height-base - $form-check-input-width) * .5; // line-height minus check height
vertical-align: top;
background-color: $form-check-input-bg;
background-repeat: no-repeat;
background-position: center;
background-size: contain;
border: $form-check-input-border;
appearance: none;
print-color-adjust: exact; // Keep themed appearance for print
@include transition($form-check-transition);
&[type="checkbox"] {
@include border-radius($form-check-input-border-radius);
}
&[type="radio"] {
// stylelint-disable-next-line property-disallowed-list
border-radius: $form-check-radio-border-radius;
}
&:active {
filter: $form-check-input-active-filter;
}
&:focus {
border-color: $form-check-input-focus-border;
outline: 0;
box-shadow: $form-check-input-focus-box-shadow;
}
&:checked {
background-color: $form-check-input-checked-bg-color;
border-color: $form-check-input-checked-border-color;
&[type="checkbox"] {
@if $enable-gradients {
background-image: escape-svg($form-check-input-checked-bg-image), var(--#{$prefix}gradient);
} @else {
background-image: escape-svg($form-check-input-checked-bg-image);
}
}
&[type="radio"] {
@if $enable-gradients {
background-image: escape-svg($form-check-radio-checked-bg-image), var(--#{$prefix}gradient);
} @else {
background-image: escape-svg($form-check-radio-checked-bg-image);
}
}
}
&[type="checkbox"]:indeterminate {
background-color: $form-check-input-indeterminate-bg-color;
border-color: $form-check-input-indeterminate-border-color;
@if $enable-gradients {
background-image: escape-svg($form-check-input-indeterminate-bg-image), var(--#{$prefix}gradient);
} @else {
background-image: escape-svg($form-check-input-indeterminate-bg-image);
}
}
&:disabled {
pointer-events: none;
filter: none;
opacity: $form-check-input-disabled-opacity;
}
// Use disabled attribute in addition of :disabled pseudo-class
// See: https://github.com/twbs/bootstrap/issues/28247
&[disabled],
&:disabled {
~ .form-check-label {
cursor: default;
opacity: $form-check-label-disabled-opacity;
}
}
}
.form-check-label {
color: $form-check-label-color;
cursor: $form-check-label-cursor;
}
//
// Switch
//
.form-switch {
padding-left: $form-switch-padding-start;
.form-check-input {
width: $form-switch-width;
margin-left: $form-switch-padding-start * -1;
background-image: escape-svg($form-switch-bg-image);
background-position: left center;
@include border-radius($form-switch-border-radius);
@include transition($form-switch-transition);
&:focus {
background-image: escape-svg($form-switch-focus-bg-image);
}
&:checked {
background-position: $form-switch-checked-bg-position;
@if $enable-gradients {
background-image: escape-svg($form-switch-checked-bg-image), var(--#{$prefix}gradient);
} @else {
background-image: escape-svg($form-switch-checked-bg-image);
}
}
}
&.form-check-reverse {
padding-right: $form-switch-padding-start;
padding-left: 0;
.form-check-input {
margin-right: $form-switch-padding-start * -1;
margin-left: 0;
}
}
}
.form-check-inline {
display: inline-block;
margin-right: $form-check-inline-margin-end;
}
.btn-check {
position: absolute;
clip: rect(0, 0, 0, 0);
pointer-events: none;
&[disabled],
&:disabled {
+ .btn {
pointer-events: none;
filter: none;
opacity: $form-check-btn-check-disabled-opacity;
}
}
}

194
src/main/resources/static/assets/_scss/bootstrap/forms/_form-control.scss

@ -0,0 +1,194 @@
//
// General form controls (plus a few specific high-level interventions)
//
.form-control {
display: block;
width: 100%;
padding: $input-padding-y $input-padding-x;
font-family: $input-font-family;
@include font-size($input-font-size);
font-weight: $input-font-weight;
line-height: $input-line-height;
color: $input-color;
background-color: $input-bg;
background-clip: padding-box;
border: $input-border-width solid $input-border-color;
appearance: none; // Fix appearance for date inputs in Safari
// Note: This has no effect on <select>s in some browsers, due to the limited stylability of `<select>`s in CSS.
@include border-radius($input-border-radius, 0);
@include box-shadow($input-box-shadow);
@include transition($input-transition);
&[type="file"] {
overflow: hidden; // prevent pseudo element button overlap
&:not(:disabled):not([readonly]) {
cursor: pointer;
}
}
// Customize the `:focus` state to imitate native WebKit styles.
&:focus {
color: $input-focus-color;
background-color: $input-focus-bg;
border-color: $input-focus-border-color;
outline: 0;
@if $enable-shadows {
@include box-shadow($input-box-shadow, $input-focus-box-shadow);
} @else {
// Avoid using mixin so we can pass custom focus shadow properly
box-shadow: $input-focus-box-shadow;
}
}
// Add some height to date inputs on iOS
// https://github.com/twbs/bootstrap/issues/23307
// TODO: we can remove this workaround once https://bugs.webkit.org/show_bug.cgi?id=198959 is resolved
&::-webkit-date-and-time-value {
// Multiply line-height by 1em if it has no unit
height: if(unit($input-line-height) == "", $input-line-height * 1em, $input-line-height);
}
// Placeholder
&::placeholder {
color: $input-placeholder-color;
// Override Firefox's unusual default opacity; see https://github.com/twbs/bootstrap/pull/11526.
opacity: 1;
}
// Disabled inputs
//
// HTML5 says that controls under a fieldset > legend:first-child won't be
// disabled if the fieldset is disabled. Due to implementation difficulty, we
// don't honor that edge case; we style them as disabled anyway.
&:disabled {
color: $input-disabled-color;
background-color: $input-disabled-bg;
border-color: $input-disabled-border-color;
// iOS fix for unreadable disabled content; see https://github.com/twbs/bootstrap/issues/11655.
opacity: 1;
}
// File input buttons theming
&::file-selector-button {
padding: $input-padding-y $input-padding-x;
margin: (-$input-padding-y) (-$input-padding-x);
margin-inline-end: $input-padding-x;
color: $form-file-button-color;
@include gradient-bg($form-file-button-bg);
pointer-events: none;
border-color: inherit;
border-style: solid;
border-width: 0;
border-inline-end-width: $input-border-width;
border-radius: 0; // stylelint-disable-line property-disallowed-list
@include transition($btn-transition);
}
&:hover:not(:disabled):not([readonly])::file-selector-button {
background-color: $form-file-button-hover-bg;
}
}
// Readonly controls as plain text
//
// Apply class to a readonly input to make it appear like regular plain
// text (without any border, background color, focus indicator)
.form-control-plaintext {
display: block;
width: 100%;
padding: $input-padding-y 0;
margin-bottom: 0; // match inputs if this class comes on inputs with default margins
line-height: $input-line-height;
color: $input-plaintext-color;
background-color: transparent;
border: solid transparent;
border-width: $input-border-width 0;
&:focus {
outline: 0;
}
&.form-control-sm,
&.form-control-lg {
padding-right: 0;
padding-left: 0;
}
}
// Form control sizing
//
// Build on `.form-control` with modifier classes to decrease or increase the
// height and font-size of form controls.
//
// Repeated in `_input_group.scss` to avoid Sass extend issues.
.form-control-sm {
min-height: $input-height-sm;
padding: $input-padding-y-sm $input-padding-x-sm;
@include font-size($input-font-size-sm);
@include border-radius($input-border-radius-sm);
&::file-selector-button {
padding: $input-padding-y-sm $input-padding-x-sm;
margin: (-$input-padding-y-sm) (-$input-padding-x-sm);
margin-inline-end: $input-padding-x-sm;
}
}
.form-control-lg {
min-height: $input-height-lg;
padding: $input-padding-y-lg $input-padding-x-lg;
@include font-size($input-font-size-lg);
@include border-radius($input-border-radius-lg);
&::file-selector-button {
padding: $input-padding-y-lg $input-padding-x-lg;
margin: (-$input-padding-y-lg) (-$input-padding-x-lg);
margin-inline-end: $input-padding-x-lg;
}
}
// Make sure textareas don't shrink too much when resized
// https://github.com/twbs/bootstrap/pull/29124
// stylelint-disable selector-no-qualifying-type
textarea {
&.form-control {
min-height: $input-height;
}
&.form-control-sm {
min-height: $input-height-sm;
}
&.form-control-lg {
min-height: $input-height-lg;
}
}
// stylelint-enable selector-no-qualifying-type
.form-control-color {
width: $form-color-width;
height: $input-height;
padding: $input-padding-y;
&:not(:disabled):not([readonly]) {
cursor: pointer;
}
&::-moz-color-swatch {
border: 0 !important; // stylelint-disable-line declaration-no-important
@include border-radius($input-border-radius);
}
&::-webkit-color-swatch {
@include border-radius($input-border-radius);
}
&.form-control-sm { height: $input-height-sm; }
&.form-control-lg { height: $input-height-lg; }
}

91
src/main/resources/static/assets/_scss/bootstrap/forms/_form-range.scss

@ -0,0 +1,91 @@
// Range
//
// Style range inputs the same across browsers. Vendor-specific rules for pseudo
// elements cannot be mixed. As such, there are no shared styles for focus or
// active states on prefixed selectors.
.form-range {
width: 100%;
height: add($form-range-thumb-height, $form-range-thumb-focus-box-shadow-width * 2);
padding: 0; // Need to reset padding
background-color: transparent;
appearance: none;
&:focus {
outline: 0;
// Pseudo-elements must be split across multiple rulesets to have an effect.
// No box-shadow() mixin for focus accessibility.
&::-webkit-slider-thumb { box-shadow: $form-range-thumb-focus-box-shadow; }
&::-moz-range-thumb { box-shadow: $form-range-thumb-focus-box-shadow; }
}
&::-moz-focus-outer {
border: 0;
}
&::-webkit-slider-thumb {
width: $form-range-thumb-width;
height: $form-range-thumb-height;
margin-top: ($form-range-track-height - $form-range-thumb-height) * .5; // Webkit specific
@include gradient-bg($form-range-thumb-bg);
border: $form-range-thumb-border;
@include border-radius($form-range-thumb-border-radius);
@include box-shadow($form-range-thumb-box-shadow);
@include transition($form-range-thumb-transition);
appearance: none;
&:active {
@include gradient-bg($form-range-thumb-active-bg);
}
}
&::-webkit-slider-runnable-track {
width: $form-range-track-width;
height: $form-range-track-height;
color: transparent; // Why?
cursor: $form-range-track-cursor;
background-color: $form-range-track-bg;
border-color: transparent;
@include border-radius($form-range-track-border-radius);
@include box-shadow($form-range-track-box-shadow);
}
&::-moz-range-thumb {
width: $form-range-thumb-width;
height: $form-range-thumb-height;
@include gradient-bg($form-range-thumb-bg);
border: $form-range-thumb-border;
@include border-radius($form-range-thumb-border-radius);
@include box-shadow($form-range-thumb-box-shadow);
@include transition($form-range-thumb-transition);
appearance: none;
&:active {
@include gradient-bg($form-range-thumb-active-bg);
}
}
&::-moz-range-track {
width: $form-range-track-width;
height: $form-range-track-height;
color: transparent;
cursor: $form-range-track-cursor;
background-color: $form-range-track-bg;
border-color: transparent; // Firefox specific?
@include border-radius($form-range-track-border-radius);
@include box-shadow($form-range-track-box-shadow);
}
&:disabled {
pointer-events: none;
&::-webkit-slider-thumb {
background-color: $form-range-thumb-disabled-bg;
}
&::-moz-range-thumb {
background-color: $form-range-thumb-disabled-bg;
}
}
}

71
src/main/resources/static/assets/_scss/bootstrap/forms/_form-select.scss

@ -0,0 +1,71 @@
// Select
//
// Replaces the browser default select with a custom one, mostly pulled from
// https://primer.github.io/.
.form-select {
display: block;
width: 100%;
padding: $form-select-padding-y $form-select-indicator-padding $form-select-padding-y $form-select-padding-x;
-moz-padding-start: subtract($form-select-padding-x, 3px); // See https://github.com/twbs/bootstrap/issues/32636
font-family: $form-select-font-family;
@include font-size($form-select-font-size);
font-weight: $form-select-font-weight;
line-height: $form-select-line-height;
color: $form-select-color;
background-color: $form-select-bg;
background-image: escape-svg($form-select-indicator);
background-repeat: no-repeat;
background-position: $form-select-bg-position;
background-size: $form-select-bg-size;
border: $form-select-border-width solid $form-select-border-color;
@include border-radius($form-select-border-radius, 0);
@include box-shadow($form-select-box-shadow);
@include transition($form-select-transition);
appearance: none;
&:focus {
border-color: $form-select-focus-border-color;
outline: 0;
@if $enable-shadows {
@include box-shadow($form-select-box-shadow, $form-select-focus-box-shadow);
} @else {
// Avoid using mixin so we can pass custom focus shadow properly
box-shadow: $form-select-focus-box-shadow;
}
}
&[multiple],
&[size]:not([size="1"]) {
padding-right: $form-select-padding-x;
background-image: none;
}
&:disabled {
color: $form-select-disabled-color;
background-color: $form-select-disabled-bg;
border-color: $form-select-disabled-border-color;
}
// Remove outline from select box in FF
&:-moz-focusring {
color: transparent;
text-shadow: 0 0 0 $form-select-color;
}
}
.form-select-sm {
padding-top: $form-select-padding-y-sm;
padding-bottom: $form-select-padding-y-sm;
padding-left: $form-select-padding-x-sm;
@include font-size($form-select-font-size-sm);
@include border-radius($form-select-border-radius-sm);
}
.form-select-lg {
padding-top: $form-select-padding-y-lg;
padding-bottom: $form-select-padding-y-lg;
padding-left: $form-select-padding-x-lg;
@include font-size($form-select-font-size-lg);
@include border-radius($form-select-border-radius-lg);
}

11
src/main/resources/static/assets/_scss/bootstrap/forms/_form-text.scss

@ -0,0 +1,11 @@
//
// Form text
//
.form-text {
margin-top: $form-text-margin-top;
@include font-size($form-text-font-size);
font-style: $form-text-font-style;
font-weight: $form-text-font-weight;
color: $form-text-color;
}

132
src/main/resources/static/assets/_scss/bootstrap/forms/_input-group.scss

@ -0,0 +1,132 @@
//
// Base styles
//
.input-group {
position: relative;
display: flex;
flex-wrap: wrap; // For form validation feedback
align-items: stretch;
width: 100%;
> .form-control,
> .form-select,
> .form-floating {
position: relative; // For focus state's z-index
flex: 1 1 auto;
width: 1%;
min-width: 0; // https://stackoverflow.com/questions/36247140/why-dont-flex-items-shrink-past-content-size
}
// Bring the "active" form control to the top of surrounding elements
> .form-control:focus,
> .form-select:focus,
> .form-floating:focus-within {
z-index: 5;
}
// Ensure buttons are always above inputs for more visually pleasing borders.
// This isn't needed for `.input-group-text` since it shares the same border-color
// as our inputs.
.btn {
position: relative;
z-index: 2;
&:focus {
z-index: 5;
}
}
}
// Textual addons
//
// Serves as a catch-all element for any text or radio/checkbox input you wish
// to prepend or append to an input.
.input-group-text {
display: flex;
align-items: center;
padding: $input-group-addon-padding-y $input-group-addon-padding-x;
@include font-size($input-font-size); // Match inputs
font-weight: $input-group-addon-font-weight;
line-height: $input-line-height;
color: $input-group-addon-color;
text-align: center;
white-space: nowrap;
background-color: $input-group-addon-bg;
border: $input-border-width solid $input-group-addon-border-color;
@include border-radius($input-border-radius);
}
// Sizing
//
// Remix the default form control sizing classes into new ones for easier
// manipulation.
.input-group-lg > .form-control,
.input-group-lg > .form-select,
.input-group-lg > .input-group-text,
.input-group-lg > .btn {
padding: $input-padding-y-lg $input-padding-x-lg;
@include font-size($input-font-size-lg);
@include border-radius($input-border-radius-lg);
}
.input-group-sm > .form-control,
.input-group-sm > .form-select,
.input-group-sm > .input-group-text,
.input-group-sm > .btn {
padding: $input-padding-y-sm $input-padding-x-sm;
@include font-size($input-font-size-sm);
@include border-radius($input-border-radius-sm);
}
.input-group-lg > .form-select,
.input-group-sm > .form-select {
padding-right: $form-select-padding-x + $form-select-indicator-padding;
}
// Rounded corners
//
// These rulesets must come after the sizing ones to properly override sm and lg
// border-radius values when extending. They're more specific than we'd like
// with the `.input-group >` part, but without it, we cannot override the sizing.
// stylelint-disable-next-line no-duplicate-selectors
.input-group {
&:not(.has-validation) {
> :not(:last-child):not(.dropdown-toggle):not(.dropdown-menu):not(.form-floating),
> .dropdown-toggle:nth-last-child(n + 3),
> .form-floating:not(:last-child) > .form-control,
> .form-floating:not(:last-child) > .form-select {
@include border-end-radius(0);
}
}
&.has-validation {
> :nth-last-child(n + 3):not(.dropdown-toggle):not(.dropdown-menu):not(.form-floating),
> .dropdown-toggle:nth-last-child(n + 4),
> .form-floating:nth-last-child(n + 3) > .form-control,
> .form-floating:nth-last-child(n + 3) > .form-select {
@include border-end-radius(0);
}
}
$validation-messages: "";
@each $state in map-keys($form-validation-states) {
$validation-messages: $validation-messages + ":not(." + unquote($state) + "-tooltip)" + ":not(." + unquote($state) + "-feedback)";
}
> :not(:first-child):not(.dropdown-menu)#{$validation-messages} {
margin-left: -$input-border-width;
@include border-start-radius(0);
}
> .form-floating:not(:first-child) > .form-control,
> .form-floating:not(:first-child) > .form-select {
@include border-start-radius(0);
}
}

36
src/main/resources/static/assets/_scss/bootstrap/forms/_labels.scss

@ -0,0 +1,36 @@
//
// Labels
//
.form-label {
margin-bottom: $form-label-margin-bottom;
@include font-size($form-label-font-size);
font-style: $form-label-font-style;
font-weight: $form-label-font-weight;
color: $form-label-color;
}
// For use with horizontal and inline forms, when you need the label (or legend)
// text to align with the form controls.
.col-form-label {
padding-top: add($input-padding-y, $input-border-width);
padding-bottom: add($input-padding-y, $input-border-width);
margin-bottom: 0; // Override the `<legend>` default
@include font-size(inherit); // Override the `<legend>` default
font-style: $form-label-font-style;
font-weight: $form-label-font-weight;
line-height: $input-line-height;
color: $form-label-color;
}
.col-form-label-lg {
padding-top: add($input-padding-y-lg, $input-border-width);
padding-bottom: add($input-padding-y-lg, $input-border-width);
@include font-size($input-font-size-lg);
}
.col-form-label-sm {
padding-top: add($input-padding-y-sm, $input-border-width);
padding-bottom: add($input-padding-y-sm, $input-border-width);
@include font-size($input-font-size-sm);
}

12
src/main/resources/static/assets/_scss/bootstrap/forms/_validation.scss

@ -0,0 +1,12 @@
// Form validation
//
// Provide feedback to users when form field values are valid or invalid. Works
// primarily for client-side validation via scoped `:invalid` and `:valid`
// pseudo-classes but also includes `.is-invalid` and `.is-valid` classes for
// server-side validation.
// scss-docs-start form-validation-states-loop
@each $state, $data in $form-validation-states {
@include form-validation-state($state, $data...);
}
// scss-docs-end form-validation-states-loop

3
src/main/resources/static/assets/_scss/bootstrap/helpers/_clearfix.scss

@ -0,0 +1,3 @@
.clearfix {
@include clearfix();
}

10
src/main/resources/static/assets/_scss/bootstrap/helpers/_color-bg.scss

@ -0,0 +1,10 @@
// stylelint-disable function-name-case
// All-caps `RGBA()` function used because of this Sass bug: https://github.com/sass/node-sass/issues/2251
@each $color, $value in $theme-colors {
$color-rgb: to-rgb($value);
.text-bg-#{$color} {
color: color-contrast($value) if($enable-important-utilities, !important, null);
background-color: RGBA($color-rgb, var(--#{$prefix}bg-opacity, 1)) if($enable-important-utilities, !important, null);
}
}

12
src/main/resources/static/assets/_scss/bootstrap/helpers/_colored-links.scss

@ -0,0 +1,12 @@
@each $color, $value in $theme-colors {
.link-#{$color} {
color: $value !important; // stylelint-disable-line declaration-no-important
@if $link-shade-percentage != 0 {
&:hover,
&:focus {
color: if(color-contrast($value) == $color-contrast-light, shade-color($value, $link-shade-percentage), tint-color($value, $link-shade-percentage)) !important; // stylelint-disable-line declaration-no-important
}
}
}
}

Some files were not shown because too many files changed in this diff

Loading…
Cancel
Save