Browse Source

first commit

master
Hariprasath S 4 months ago
commit
023a7f57aa
  1. 2
      .gitattributes
  2. 33
      .gitignore
  3. 3
      .mvn/wrapper/maven-wrapper.properties
  4. BIN
      gcc_mobile_service_uploads/green_committee_files/2025/12/comp_image1_27122025124945_bird.jpg
  5. BIN
      gcc_mobile_service_uploads/green_committee_files/2025/12/comp_image1_27122025124945_duck-7406987.jpg
  6. BIN
      gcc_mobile_service_uploads/green_committee_files/2025/12/comp_image1_27122025130138_bird.jpg
  7. BIN
      gcc_mobile_service_uploads/green_committee_files/2025/12/comp_image1_27122025130138_joban-khangura-hG8B9pKiilw-unsplash.jpg
  8. BIN
      gcc_mobile_service_uploads/green_committee_files/2025/12/comp_image1_27122025130247_bird.jpg
  9. BIN
      gcc_mobile_service_uploads/green_committee_files/2025/12/comp_image1_27122025130247_duck-7406987.jpg
  10. BIN
      gcc_mobile_service_uploads/green_committee_files/2025/12/comp_image1_27122025160944_sc1.jpeg
  11. BIN
      gcc_mobile_service_uploads/green_committee_files/2025/12/comp_image1_27122025161152_sc1.jpeg
  12. BIN
      gcc_mobile_service_uploads/green_committee_files/2025/12/comp_image1_27122025161603_sc1.jpeg
  13. BIN
      gcc_mobile_service_uploads/green_committee_files/2025/12/comp_image1_27122025161755_sc1.jpeg
  14. BIN
      gcc_mobile_service_uploads/green_committee_files/2025/12/comp_image1_27122025162323_sc1.jpeg
  15. BIN
      gcc_mobile_service_uploads/green_committee_files/2025/12/comp_image1_27122025162414_sc1.jpeg
  16. BIN
      gcc_mobile_service_uploads/green_committee_files/2025/12/comp_image1_29122025110136_sc1.jpeg
  17. BIN
      gcc_mobile_service_uploads/green_committee_files/2025/12/comp_image1_29122025112848_sc1.jpeg
  18. BIN
      gcc_mobile_service_uploads/green_committee_files/2025/12/comp_image1_29122025113046_sc1.jpeg
  19. BIN
      gcc_mobile_service_uploads/green_committee_files/2026/01/comp_image1_02012026134533_sample1.jpg
  20. BIN
      gcc_mobile_service_uploads/green_committee_files/2026/01/comp_image1_02012026134650_sample1.jpg
  21. BIN
      gcc_mobile_service_uploads/green_committee_files/2026/01/comp_image1_02012026165041_newuser.jpg
  22. BIN
      gcc_mobile_service_uploads/green_committee_files/2026/01/comp_image1_02012026165137_newuser.jpg
  23. BIN
      gcc_mobile_service_uploads/green_committee_files/2026/01/comp_image1_02012026165232_newuser.jpg
  24. BIN
      gcc_mobile_service_uploads/green_committee_files/2026/01/comp_image1_12012026113726_MacBookPro14_-1.jpg
  25. BIN
      gcc_mobile_service_uploads/green_committee_files/2026/01/comp_image1_12012026113726_sample1.jpg
  26. BIN
      gcc_mobile_service_uploads/green_committee_files/2026/01/comp_image1_12012026115813_MacBookPro14_-1.jpg
  27. BIN
      gcc_mobile_service_uploads/green_committee_files/2026/01/comp_image1_12012026115813_sample1.jpg
  28. BIN
      gcc_mobile_service_uploads/green_committee_files/2026/01/comp_image1_12012026132432_MacBookPro14_-1.jpg
  29. BIN
      gcc_mobile_service_uploads/green_committee_files/2026/01/comp_image1_12012026132432_sample1.jpg
  30. BIN
      gcc_mobile_service_uploads/green_committee_files/2026/01/comp_image1_22012026125708_newuser.jpg
  31. BIN
      gcc_mobile_service_uploads/green_committee_files/2026/01/comp_image1_22012026125832_newuser.jpg
  32. 295
      mvnw
  33. 189
      mvnw.cmd
  34. BIN
      nullnull/2025/12/comp_image1_27122025123322_bird.jpg
  35. BIN
      nullnull/2025/12/comp_image1_27122025123322_joban-khangura-hG8B9pKiilw-unsplash.jpg
  36. 81
      pom.xml
  37. 13
      src/main/java/com/gcc/greencommitte/GreencommitteApplication.java
  38. 47
      src/main/java/com/gcc/greencommitte/config/AppConfig.java
  39. 16
      src/main/java/com/gcc/greencommitte/config/GlobalAttributes.java
  40. 9
      src/main/java/com/gcc/greencommitte/config/TomcatConfig.java
  41. 10
      src/main/java/com/gcc/greencommitte/config/TomcatCustomizer.java
  42. 389
      src/main/java/com/gcc/greencommitte/controller/Apicontroller.java
  43. 32
      src/main/java/com/gcc/greencommitte/controller/Maincontroller.java
  44. 36
      src/main/java/com/gcc/greencommitte/service/DateTimeUtil.java
  45. 612
      src/main/java/com/gcc/greencommitte/service/Greencommitteeservice.java
  46. 32
      src/main/resources/application-dev.properties
  47. 31
      src/main/resources/application-prod.properties
  48. 3
      src/main/resources/application.properties
  49. BIN
      src/main/resources/favicon.ico
  50. 65
      src/main/resources/static/assets/_js/main/app.js
  51. 1110
      src/main/resources/static/assets/_js/main/modules/helpers.js
  52. 802
      src/main/resources/static/assets/_js/main/modules/template.js
  53. 179
      src/main/resources/static/assets/_js/pages/be_comp_calendar.js
  54. 143
      src/main/resources/static/assets/_js/pages/be_comp_charts.js
  55. 156
      src/main/resources/static/assets/_js/pages/be_comp_chat.js
  56. 106
      src/main/resources/static/assets/_js/pages/be_comp_dialogs.js
  57. 88
      src/main/resources/static/assets/_js/pages/be_comp_image_cropper.js
  58. 154
      src/main/resources/static/assets/_js/pages/be_comp_maps_vector.js
  59. 47
      src/main/resources/static/assets/_js/pages/be_comp_nestable.js
  60. 41
      src/main/resources/static/assets/_js/pages/be_comp_onboarding.js
  61. 50
      src/main/resources/static/assets/_js/pages/be_comp_rating.js
  62. 124
      src/main/resources/static/assets/_js/pages/be_forms_validation.js
  63. 89
      src/main/resources/static/assets/_js/pages/be_pages_dashboard.js
  64. 225
      src/main/resources/static/assets/_js/pages/be_pages_dashboard_v1.js
  65. 104
      src/main/resources/static/assets/_js/pages/be_pages_ecom_dashboard.js
  66. 271
      src/main/resources/static/assets/_js/pages/be_pages_projects_tasks.js
  67. 101
      src/main/resources/static/assets/_js/pages/be_tables_datatables.js
  68. 45
      src/main/resources/static/assets/_js/pages/be_ui_animations.js
  69. 2184
      src/main/resources/static/assets/_js/pages/be_ui_icons.js
  70. 41
      src/main/resources/static/assets/_js/pages/be_ui_progress.js
  71. 73
      src/main/resources/static/assets/_js/pages/db_analytics.js
  72. 144
      src/main/resources/static/assets/_js/pages/db_corporate_slim.js
  73. 93
      src/main/resources/static/assets/_js/pages/db_crypto.js
  74. 42
      src/main/resources/static/assets/_js/pages/op_auth_lock.js
  75. 42
      src/main/resources/static/assets/_js/pages/op_auth_reminder.js
  76. 51
      src/main/resources/static/assets/_js/pages/op_auth_signin.js
  77. 69
      src/main/resources/static/assets/_js/pages/op_auth_signup.js
  78. 34
      src/main/resources/static/assets/_js/pages/op_coming_soon.js
  79. 78
      src/main/resources/static/assets/_js/pages/op_installation.js
  80. 149
      src/main/resources/static/assets/_scss/bootstrap/_accordion.scss
  81. 71
      src/main/resources/static/assets/_scss/bootstrap/_alert.scss
  82. 38
      src/main/resources/static/assets/_scss/bootstrap/_badge.scss
  83. 40
      src/main/resources/static/assets/_scss/bootstrap/_breadcrumb.scss
  84. 142
      src/main/resources/static/assets/_scss/bootstrap/_button-group.scss
  85. 207
      src/main/resources/static/assets/_scss/bootstrap/_buttons.scss
  86. 234
      src/main/resources/static/assets/_scss/bootstrap/_card.scss
  87. 226
      src/main/resources/static/assets/_scss/bootstrap/_carousel.scss
  88. 40
      src/main/resources/static/assets/_scss/bootstrap/_close.scss
  89. 41
      src/main/resources/static/assets/_scss/bootstrap/_containers.scss
  90. 249
      src/main/resources/static/assets/_scss/bootstrap/_dropdown.scss
  91. 9
      src/main/resources/static/assets/_scss/bootstrap/_forms.scss
  92. 302
      src/main/resources/static/assets/_scss/bootstrap/_functions.scss
  93. 33
      src/main/resources/static/assets/_scss/bootstrap/_grid.scss
  94. 10
      src/main/resources/static/assets/_scss/bootstrap/_helpers.scss
  95. 42
      src/main/resources/static/assets/_scss/bootstrap/_images.scss
  96. 192
      src/main/resources/static/assets/_scss/bootstrap/_list-group.scss
  97. 54
      src/main/resources/static/assets/_scss/bootstrap/_maps.scss
  98. 43
      src/main/resources/static/assets/_scss/bootstrap/_mixins.scss
  99. 237
      src/main/resources/static/assets/_scss/bootstrap/_modal.scss
  100. 172
      src/main/resources/static/assets/_scss/bootstrap/_nav.scss

2
.gitattributes

@ -0,0 +1,2 @@
/mvnw text eol=lf
*.cmd text eol=crlf

33
.gitignore

@ -0,0 +1,33 @@
HELP.md
target/
.mvn/wrapper/maven-wrapper.jar
!**/src/main/**/target/
!**/src/test/**/target/
### STS ###
.apt_generated
.classpath
.factorypath
.project
.settings
.springBeans
.sts4-cache
### IntelliJ IDEA ###
.idea
*.iws
*.iml
*.ipr
### NetBeans ###
/nbproject/private/
/nbbuild/
/dist/
/nbdist/
/.nb-gradle/
build/
!**/src/main/**/build/
!**/src/test/**/build/
### VS Code ###
.vscode/

3
.mvn/wrapper/maven-wrapper.properties

@ -0,0 +1,3 @@
wrapperVersion=3.3.4
distributionType=only-script
distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.12/apache-maven-3.9.12-bin.zip

BIN
gcc_mobile_service_uploads/green_committee_files/2025/12/comp_image1_27122025124945_bird.jpg

After

Width: 1280  |  Height: 897  |  Size: 191 KiB

BIN
gcc_mobile_service_uploads/green_committee_files/2025/12/comp_image1_27122025124945_duck-7406987.jpg

After

Width: 5401  |  Height: 3601  |  Size: 3.2 MiB

BIN
gcc_mobile_service_uploads/green_committee_files/2025/12/comp_image1_27122025130138_bird.jpg

After

Width: 1280  |  Height: 897  |  Size: 191 KiB

BIN
gcc_mobile_service_uploads/green_committee_files/2025/12/comp_image1_27122025130138_joban-khangura-hG8B9pKiilw-unsplash.jpg

After

Width: 2400  |  Height: 3001  |  Size: 2.5 MiB

BIN
gcc_mobile_service_uploads/green_committee_files/2025/12/comp_image1_27122025130247_bird.jpg

After

Width: 1280  |  Height: 897  |  Size: 191 KiB

BIN
gcc_mobile_service_uploads/green_committee_files/2025/12/comp_image1_27122025130247_duck-7406987.jpg

After

Width: 5401  |  Height: 3601  |  Size: 3.2 MiB

BIN
gcc_mobile_service_uploads/green_committee_files/2025/12/comp_image1_27122025160944_sc1.jpeg

After

Width: 781  |  Height: 218  |  Size: 32 KiB

BIN
gcc_mobile_service_uploads/green_committee_files/2025/12/comp_image1_27122025161152_sc1.jpeg

After

Width: 781  |  Height: 218  |  Size: 32 KiB

BIN
gcc_mobile_service_uploads/green_committee_files/2025/12/comp_image1_27122025161603_sc1.jpeg

After

Width: 781  |  Height: 218  |  Size: 32 KiB

BIN
gcc_mobile_service_uploads/green_committee_files/2025/12/comp_image1_27122025161755_sc1.jpeg

After

Width: 781  |  Height: 218  |  Size: 32 KiB

BIN
gcc_mobile_service_uploads/green_committee_files/2025/12/comp_image1_27122025162323_sc1.jpeg

After

Width: 781  |  Height: 218  |  Size: 32 KiB

BIN
gcc_mobile_service_uploads/green_committee_files/2025/12/comp_image1_27122025162414_sc1.jpeg

After

Width: 781  |  Height: 218  |  Size: 32 KiB

BIN
gcc_mobile_service_uploads/green_committee_files/2025/12/comp_image1_29122025110136_sc1.jpeg

After

Width: 781  |  Height: 218  |  Size: 32 KiB

BIN
gcc_mobile_service_uploads/green_committee_files/2025/12/comp_image1_29122025112848_sc1.jpeg

After

Width: 781  |  Height: 218  |  Size: 32 KiB

BIN
gcc_mobile_service_uploads/green_committee_files/2025/12/comp_image1_29122025113046_sc1.jpeg

After

Width: 781  |  Height: 218  |  Size: 32 KiB

BIN
gcc_mobile_service_uploads/green_committee_files/2026/01/comp_image1_02012026134533_sample1.jpg

After

Width: 1181  |  Height: 781  |  Size: 278 KiB

BIN
gcc_mobile_service_uploads/green_committee_files/2026/01/comp_image1_02012026134650_sample1.jpg

After

Width: 1181  |  Height: 781  |  Size: 278 KiB

BIN
gcc_mobile_service_uploads/green_committee_files/2026/01/comp_image1_02012026165041_newuser.jpg

After

Width: 1440  |  Height: 1482  |  Size: 102 KiB

BIN
gcc_mobile_service_uploads/green_committee_files/2026/01/comp_image1_02012026165137_newuser.jpg

After

Width: 1440  |  Height: 1482  |  Size: 102 KiB

BIN
gcc_mobile_service_uploads/green_committee_files/2026/01/comp_image1_02012026165232_newuser.jpg

After

Width: 1440  |  Height: 1482  |  Size: 102 KiB

BIN
gcc_mobile_service_uploads/green_committee_files/2026/01/comp_image1_12012026113726_MacBookPro14_-1.jpg

After

Width: 1512  |  Height: 982  |  Size: 515 KiB

BIN
gcc_mobile_service_uploads/green_committee_files/2026/01/comp_image1_12012026113726_sample1.jpg

After

Width: 1181  |  Height: 781  |  Size: 278 KiB

BIN
gcc_mobile_service_uploads/green_committee_files/2026/01/comp_image1_12012026115813_MacBookPro14_-1.jpg

After

Width: 1512  |  Height: 982  |  Size: 515 KiB

BIN
gcc_mobile_service_uploads/green_committee_files/2026/01/comp_image1_12012026115813_sample1.jpg

After

Width: 1181  |  Height: 781  |  Size: 278 KiB

BIN
gcc_mobile_service_uploads/green_committee_files/2026/01/comp_image1_12012026132432_MacBookPro14_-1.jpg

After

Width: 1512  |  Height: 982  |  Size: 515 KiB

BIN
gcc_mobile_service_uploads/green_committee_files/2026/01/comp_image1_12012026132432_sample1.jpg

After

Width: 1181  |  Height: 781  |  Size: 278 KiB

BIN
gcc_mobile_service_uploads/green_committee_files/2026/01/comp_image1_22012026125708_newuser.jpg

After

Width: 1440  |  Height: 1482  |  Size: 102 KiB

BIN
gcc_mobile_service_uploads/green_committee_files/2026/01/comp_image1_22012026125832_newuser.jpg

After

Width: 1440  |  Height: 1482  |  Size: 102 KiB

295
mvnw

@ -0,0 +1,295 @@
#!/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
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
# ----------------------------------------------------------------------------
# ----------------------------------------------------------------------------
# Apache Maven Wrapper startup batch script, version 3.3.4
#
# Optional ENV vars
# -----------------
# JAVA_HOME - location of a JDK home dir, required when download maven via java source
# MVNW_REPOURL - repo url base for downloading maven distribution
# MVNW_USERNAME/MVNW_PASSWORD - user and password for downloading maven
# MVNW_VERBOSE - true: enable verbose log; debug: trace the mvnw script; others: silence the output
# ----------------------------------------------------------------------------
set -euf
[ "${MVNW_VERBOSE-}" != debug ] || set -x
# OS specific support.
native_path() { printf %s\\n "$1"; }
case "$(uname)" in
CYGWIN* | MINGW*)
[ -z "${JAVA_HOME-}" ] || JAVA_HOME="$(cygpath --unix "$JAVA_HOME")"
native_path() { cygpath --path --windows "$1"; }
;;
esac
# set JAVACMD and JAVACCMD
set_java_home() {
# For Cygwin and MinGW, ensure paths are in Unix format before anything is touched
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"
JAVACCMD="$JAVA_HOME/jre/sh/javac"
else
JAVACMD="$JAVA_HOME/bin/java"
JAVACCMD="$JAVA_HOME/bin/javac"
if [ ! -x "$JAVACMD" ] || [ ! -x "$JAVACCMD" ]; then
echo "The JAVA_HOME environment variable is not defined correctly, so mvnw cannot run." >&2
echo "JAVA_HOME is set to \"$JAVA_HOME\", but \"\$JAVA_HOME/bin/java\" or \"\$JAVA_HOME/bin/javac\" does not exist." >&2
return 1
fi
fi
else
JAVACMD="$(
'set' +e
'unset' -f command 2>/dev/null
'command' -v java
)" || :
JAVACCMD="$(
'set' +e
'unset' -f command 2>/dev/null
'command' -v javac
)" || :
if [ ! -x "${JAVACMD-}" ] || [ ! -x "${JAVACCMD-}" ]; then
echo "The java/javac command does not exist in PATH nor is JAVA_HOME set, so mvnw cannot run." >&2
return 1
fi
fi
}
# hash string like Java String::hashCode
hash_string() {
str="${1:-}" h=0
while [ -n "$str" ]; do
char="${str%"${str#?}"}"
h=$(((h * 31 + $(LC_CTYPE=C printf %d "'$char")) % 4294967296))
str="${str#?}"
done
printf %x\\n $h
}
verbose() { :; }
[ "${MVNW_VERBOSE-}" != true ] || verbose() { printf %s\\n "${1-}"; }
die() {
printf %s\\n "$1" >&2
exit 1
}
trim() {
# MWRAPPER-139:
# Trims trailing and leading whitespace, carriage returns, tabs, and linefeeds.
# Needed for removing poorly interpreted newline sequences when running in more
# exotic environments such as mingw bash on Windows.
printf "%s" "${1}" | tr -d '[:space:]'
}
scriptDir="$(dirname "$0")"
scriptName="$(basename "$0")"
# parse distributionUrl and optional distributionSha256Sum, requires .mvn/wrapper/maven-wrapper.properties
while IFS="=" read -r key value; do
case "${key-}" in
distributionUrl) distributionUrl=$(trim "${value-}") ;;
distributionSha256Sum) distributionSha256Sum=$(trim "${value-}") ;;
esac
done <"$scriptDir/.mvn/wrapper/maven-wrapper.properties"
[ -n "${distributionUrl-}" ] || die "cannot read distributionUrl property in $scriptDir/.mvn/wrapper/maven-wrapper.properties"
case "${distributionUrl##*/}" in
maven-mvnd-*bin.*)
MVN_CMD=mvnd.sh _MVNW_REPO_PATTERN=/maven/mvnd/
case "${PROCESSOR_ARCHITECTURE-}${PROCESSOR_ARCHITEW6432-}:$(uname -a)" in
*AMD64:CYGWIN* | *AMD64:MINGW*) distributionPlatform=windows-amd64 ;;
:Darwin*x86_64) distributionPlatform=darwin-amd64 ;;
:Darwin*arm64) distributionPlatform=darwin-aarch64 ;;
:Linux*x86_64*) distributionPlatform=linux-amd64 ;;
*)
echo "Cannot detect native platform for mvnd on $(uname)-$(uname -m), use pure java version" >&2
distributionPlatform=linux-amd64
;;
esac
distributionUrl="${distributionUrl%-bin.*}-$distributionPlatform.zip"
;;
maven-mvnd-*) MVN_CMD=mvnd.sh _MVNW_REPO_PATTERN=/maven/mvnd/ ;;
*) MVN_CMD="mvn${scriptName#mvnw}" _MVNW_REPO_PATTERN=/org/apache/maven/ ;;
esac
# apply MVNW_REPOURL and calculate MAVEN_HOME
# maven home pattern: ~/.m2/wrapper/dists/{apache-maven-<version>,maven-mvnd-<version>-<platform>}/<hash>
[ -z "${MVNW_REPOURL-}" ] || distributionUrl="$MVNW_REPOURL$_MVNW_REPO_PATTERN${distributionUrl#*"$_MVNW_REPO_PATTERN"}"
distributionUrlName="${distributionUrl##*/}"
distributionUrlNameMain="${distributionUrlName%.*}"
distributionUrlNameMain="${distributionUrlNameMain%-bin}"
MAVEN_USER_HOME="${MAVEN_USER_HOME:-${HOME}/.m2}"
MAVEN_HOME="${MAVEN_USER_HOME}/wrapper/dists/${distributionUrlNameMain-}/$(hash_string "$distributionUrl")"
exec_maven() {
unset MVNW_VERBOSE MVNW_USERNAME MVNW_PASSWORD MVNW_REPOURL || :
exec "$MAVEN_HOME/bin/$MVN_CMD" "$@" || die "cannot exec $MAVEN_HOME/bin/$MVN_CMD"
}
if [ -d "$MAVEN_HOME" ]; then
verbose "found existing MAVEN_HOME at $MAVEN_HOME"
exec_maven "$@"
fi
case "${distributionUrl-}" in
*?-bin.zip | *?maven-mvnd-?*-?*.zip) ;;
*) die "distributionUrl is not valid, must match *-bin.zip or maven-mvnd-*.zip, but found '${distributionUrl-}'" ;;
esac
# prepare tmp dir
if TMP_DOWNLOAD_DIR="$(mktemp -d)" && [ -d "$TMP_DOWNLOAD_DIR" ]; then
clean() { rm -rf -- "$TMP_DOWNLOAD_DIR"; }
trap clean HUP INT TERM EXIT
else
die "cannot create temp dir"
fi
mkdir -p -- "${MAVEN_HOME%/*}"
# Download and Install Apache Maven
verbose "Couldn't find MAVEN_HOME, downloading and installing it ..."
verbose "Downloading from: $distributionUrl"
verbose "Downloading to: $TMP_DOWNLOAD_DIR/$distributionUrlName"
# select .zip or .tar.gz
if ! command -v unzip >/dev/null; then
distributionUrl="${distributionUrl%.zip}.tar.gz"
distributionUrlName="${distributionUrl##*/}"
fi
# verbose opt
__MVNW_QUIET_WGET=--quiet __MVNW_QUIET_CURL=--silent __MVNW_QUIET_UNZIP=-q __MVNW_QUIET_TAR=''
[ "${MVNW_VERBOSE-}" != true ] || __MVNW_QUIET_WGET='' __MVNW_QUIET_CURL='' __MVNW_QUIET_UNZIP='' __MVNW_QUIET_TAR=v
# normalize http auth
case "${MVNW_PASSWORD:+has-password}" in
'') MVNW_USERNAME='' MVNW_PASSWORD='' ;;
has-password) [ -n "${MVNW_USERNAME-}" ] || MVNW_USERNAME='' MVNW_PASSWORD='' ;;
esac
if [ -z "${MVNW_USERNAME-}" ] && command -v wget >/dev/null; then
verbose "Found wget ... using wget"
wget ${__MVNW_QUIET_WGET:+"$__MVNW_QUIET_WGET"} "$distributionUrl" -O "$TMP_DOWNLOAD_DIR/$distributionUrlName" || die "wget: Failed to fetch $distributionUrl"
elif [ -z "${MVNW_USERNAME-}" ] && command -v curl >/dev/null; then
verbose "Found curl ... using curl"
curl ${__MVNW_QUIET_CURL:+"$__MVNW_QUIET_CURL"} -f -L -o "$TMP_DOWNLOAD_DIR/$distributionUrlName" "$distributionUrl" || die "curl: Failed to fetch $distributionUrl"
elif set_java_home; then
verbose "Falling back to use Java to download"
javaSource="$TMP_DOWNLOAD_DIR/Downloader.java"
targetZip="$TMP_DOWNLOAD_DIR/$distributionUrlName"
cat >"$javaSource" <<-END
public class Downloader extends java.net.Authenticator
{
protected java.net.PasswordAuthentication getPasswordAuthentication()
{
return new java.net.PasswordAuthentication( System.getenv( "MVNW_USERNAME" ), System.getenv( "MVNW_PASSWORD" ).toCharArray() );
}
public static void main( String[] args ) throws Exception
{
setDefault( new Downloader() );
java.nio.file.Files.copy( java.net.URI.create( args[0] ).toURL().openStream(), java.nio.file.Paths.get( args[1] ).toAbsolutePath().normalize() );
}
}
END
# For Cygwin/MinGW, switch paths to Windows format before running javac and java
verbose " - Compiling Downloader.java ..."
"$(native_path "$JAVACCMD")" "$(native_path "$javaSource")" || die "Failed to compile Downloader.java"
verbose " - Running Downloader.java ..."
"$(native_path "$JAVACMD")" -cp "$(native_path "$TMP_DOWNLOAD_DIR")" Downloader "$distributionUrl" "$(native_path "$targetZip")"
fi
# If specified, validate the SHA-256 sum of the Maven distribution zip file
if [ -n "${distributionSha256Sum-}" ]; then
distributionSha256Result=false
if [ "$MVN_CMD" = mvnd.sh ]; then
echo "Checksum validation is not supported for maven-mvnd." >&2
echo "Please disable validation by removing 'distributionSha256Sum' from your maven-wrapper.properties." >&2
exit 1
elif command -v sha256sum >/dev/null; then
if echo "$distributionSha256Sum $TMP_DOWNLOAD_DIR/$distributionUrlName" | sha256sum -c - >/dev/null 2>&1; then
distributionSha256Result=true
fi
elif command -v shasum >/dev/null; then
if echo "$distributionSha256Sum $TMP_DOWNLOAD_DIR/$distributionUrlName" | shasum -a 256 -c >/dev/null 2>&1; then
distributionSha256Result=true
fi
else
echo "Checksum validation was requested but neither 'sha256sum' or 'shasum' are available." >&2
echo "Please install either command, or disable validation by removing 'distributionSha256Sum' from your maven-wrapper.properties." >&2
exit 1
fi
if [ $distributionSha256Result = false ]; then
echo "Error: Failed to validate Maven distribution SHA-256, your Maven distribution might be compromised." >&2
echo "If you updated your Maven version, you need to update the specified distributionSha256Sum property." >&2
exit 1
fi
fi
# unzip and move
if command -v unzip >/dev/null; then
unzip ${__MVNW_QUIET_UNZIP:+"$__MVNW_QUIET_UNZIP"} "$TMP_DOWNLOAD_DIR/$distributionUrlName" -d "$TMP_DOWNLOAD_DIR" || die "failed to unzip"
else
tar xzf${__MVNW_QUIET_TAR:+"$__MVNW_QUIET_TAR"} "$TMP_DOWNLOAD_DIR/$distributionUrlName" -C "$TMP_DOWNLOAD_DIR" || die "failed to untar"
fi
# Find the actual extracted directory name (handles snapshots where filename != directory name)
actualDistributionDir=""
# First try the expected directory name (for regular distributions)
if [ -d "$TMP_DOWNLOAD_DIR/$distributionUrlNameMain" ]; then
if [ -f "$TMP_DOWNLOAD_DIR/$distributionUrlNameMain/bin/$MVN_CMD" ]; then
actualDistributionDir="$distributionUrlNameMain"
fi
fi
# If not found, search for any directory with the Maven executable (for snapshots)
if [ -z "$actualDistributionDir" ]; then
# enable globbing to iterate over items
set +f
for dir in "$TMP_DOWNLOAD_DIR"/*; do
if [ -d "$dir" ]; then
if [ -f "$dir/bin/$MVN_CMD" ]; then
actualDistributionDir="$(basename "$dir")"
break
fi
fi
done
set -f
fi
if [ -z "$actualDistributionDir" ]; then
verbose "Contents of $TMP_DOWNLOAD_DIR:"
verbose "$(ls -la "$TMP_DOWNLOAD_DIR")"
die "Could not find Maven distribution directory in extracted archive"
fi
verbose "Found extracted Maven distribution directory: $actualDistributionDir"
printf %s\\n "$distributionUrl" >"$TMP_DOWNLOAD_DIR/$actualDistributionDir/mvnw.url"
mv -- "$TMP_DOWNLOAD_DIR/$actualDistributionDir" "$MAVEN_HOME" || [ -d "$MAVEN_HOME" ] || die "fail to move MAVEN_HOME"
clean || :
exec_maven "$@"

189
mvnw.cmd

@ -0,0 +1,189 @@
<# : batch portion
@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 http://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.3.4
@REM
@REM Optional ENV vars
@REM MVNW_REPOURL - repo url base for downloading maven distribution
@REM MVNW_USERNAME/MVNW_PASSWORD - user and password for downloading maven
@REM MVNW_VERBOSE - true: enable verbose log; others: silence the output
@REM ----------------------------------------------------------------------------
@IF "%__MVNW_ARG0_NAME__%"=="" (SET __MVNW_ARG0_NAME__=%~nx0)
@SET __MVNW_CMD__=
@SET __MVNW_ERROR__=
@SET __MVNW_PSMODULEP_SAVE=%PSModulePath%
@SET PSModulePath=
@FOR /F "usebackq tokens=1* delims==" %%A IN (`powershell -noprofile "& {$scriptDir='%~dp0'; $script='%__MVNW_ARG0_NAME__%'; icm -ScriptBlock ([Scriptblock]::Create((Get-Content -Raw '%~f0'))) -NoNewScope}"`) DO @(
IF "%%A"=="MVN_CMD" (set __MVNW_CMD__=%%B) ELSE IF "%%B"=="" (echo %%A) ELSE (echo %%A=%%B)
)
@SET PSModulePath=%__MVNW_PSMODULEP_SAVE%
@SET __MVNW_PSMODULEP_SAVE=
@SET __MVNW_ARG0_NAME__=
@SET MVNW_USERNAME=
@SET MVNW_PASSWORD=
@IF NOT "%__MVNW_CMD__%"=="" ("%__MVNW_CMD__%" %*)
@echo Cannot start maven from wrapper >&2 && exit /b 1
@GOTO :EOF
: end batch / begin powershell #>
$ErrorActionPreference = "Stop"
if ($env:MVNW_VERBOSE -eq "true") {
$VerbosePreference = "Continue"
}
# calculate distributionUrl, requires .mvn/wrapper/maven-wrapper.properties
$distributionUrl = (Get-Content -Raw "$scriptDir/.mvn/wrapper/maven-wrapper.properties" | ConvertFrom-StringData).distributionUrl
if (!$distributionUrl) {
Write-Error "cannot read distributionUrl property in $scriptDir/.mvn/wrapper/maven-wrapper.properties"
}
switch -wildcard -casesensitive ( $($distributionUrl -replace '^.*/','') ) {
"maven-mvnd-*" {
$USE_MVND = $true
$distributionUrl = $distributionUrl -replace '-bin\.[^.]*$',"-windows-amd64.zip"
$MVN_CMD = "mvnd.cmd"
break
}
default {
$USE_MVND = $false
$MVN_CMD = $script -replace '^mvnw','mvn'
break
}
}
# apply MVNW_REPOURL and calculate MAVEN_HOME
# maven home pattern: ~/.m2/wrapper/dists/{apache-maven-<version>,maven-mvnd-<version>-<platform>}/<hash>
if ($env:MVNW_REPOURL) {
$MVNW_REPO_PATTERN = if ($USE_MVND -eq $False) { "/org/apache/maven/" } else { "/maven/mvnd/" }
$distributionUrl = "$env:MVNW_REPOURL$MVNW_REPO_PATTERN$($distributionUrl -replace "^.*$MVNW_REPO_PATTERN",'')"
}
$distributionUrlName = $distributionUrl -replace '^.*/',''
$distributionUrlNameMain = $distributionUrlName -replace '\.[^.]*$','' -replace '-bin$',''
$MAVEN_M2_PATH = "$HOME/.m2"
if ($env:MAVEN_USER_HOME) {
$MAVEN_M2_PATH = "$env:MAVEN_USER_HOME"
}
if (-not (Test-Path -Path $MAVEN_M2_PATH)) {
New-Item -Path $MAVEN_M2_PATH -ItemType Directory | Out-Null
}
$MAVEN_WRAPPER_DISTS = $null
if ((Get-Item $MAVEN_M2_PATH).Target[0] -eq $null) {
$MAVEN_WRAPPER_DISTS = "$MAVEN_M2_PATH/wrapper/dists"
} else {
$MAVEN_WRAPPER_DISTS = (Get-Item $MAVEN_M2_PATH).Target[0] + "/wrapper/dists"
}
$MAVEN_HOME_PARENT = "$MAVEN_WRAPPER_DISTS/$distributionUrlNameMain"
$MAVEN_HOME_NAME = ([System.Security.Cryptography.SHA256]::Create().ComputeHash([byte[]][char[]]$distributionUrl) | ForEach-Object {$_.ToString("x2")}) -join ''
$MAVEN_HOME = "$MAVEN_HOME_PARENT/$MAVEN_HOME_NAME"
if (Test-Path -Path "$MAVEN_HOME" -PathType Container) {
Write-Verbose "found existing MAVEN_HOME at $MAVEN_HOME"
Write-Output "MVN_CMD=$MAVEN_HOME/bin/$MVN_CMD"
exit $?
}
if (! $distributionUrlNameMain -or ($distributionUrlName -eq $distributionUrlNameMain)) {
Write-Error "distributionUrl is not valid, must end with *-bin.zip, but found $distributionUrl"
}
# prepare tmp dir
$TMP_DOWNLOAD_DIR_HOLDER = New-TemporaryFile
$TMP_DOWNLOAD_DIR = New-Item -Itemtype Directory -Path "$TMP_DOWNLOAD_DIR_HOLDER.dir"
$TMP_DOWNLOAD_DIR_HOLDER.Delete() | Out-Null
trap {
if ($TMP_DOWNLOAD_DIR.Exists) {
try { Remove-Item $TMP_DOWNLOAD_DIR -Recurse -Force | Out-Null }
catch { Write-Warning "Cannot remove $TMP_DOWNLOAD_DIR" }
}
}
New-Item -Itemtype Directory -Path "$MAVEN_HOME_PARENT" -Force | Out-Null
# Download and Install Apache Maven
Write-Verbose "Couldn't find MAVEN_HOME, downloading and installing it ..."
Write-Verbose "Downloading from: $distributionUrl"
Write-Verbose "Downloading to: $TMP_DOWNLOAD_DIR/$distributionUrlName"
$webclient = New-Object System.Net.WebClient
if ($env:MVNW_USERNAME -and $env:MVNW_PASSWORD) {
$webclient.Credentials = New-Object System.Net.NetworkCredential($env:MVNW_USERNAME, $env:MVNW_PASSWORD)
}
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
$webclient.DownloadFile($distributionUrl, "$TMP_DOWNLOAD_DIR/$distributionUrlName") | Out-Null
# If specified, validate the SHA-256 sum of the Maven distribution zip file
$distributionSha256Sum = (Get-Content -Raw "$scriptDir/.mvn/wrapper/maven-wrapper.properties" | ConvertFrom-StringData).distributionSha256Sum
if ($distributionSha256Sum) {
if ($USE_MVND) {
Write-Error "Checksum validation is not supported for maven-mvnd. `nPlease disable validation by removing 'distributionSha256Sum' from your maven-wrapper.properties."
}
Import-Module $PSHOME\Modules\Microsoft.PowerShell.Utility -Function Get-FileHash
if ((Get-FileHash "$TMP_DOWNLOAD_DIR/$distributionUrlName" -Algorithm SHA256).Hash.ToLower() -ne $distributionSha256Sum) {
Write-Error "Error: Failed to validate Maven distribution SHA-256, your Maven distribution might be compromised. If you updated your Maven version, you need to update the specified distributionSha256Sum property."
}
}
# unzip and move
Expand-Archive "$TMP_DOWNLOAD_DIR/$distributionUrlName" -DestinationPath "$TMP_DOWNLOAD_DIR" | Out-Null
# Find the actual extracted directory name (handles snapshots where filename != directory name)
$actualDistributionDir = ""
# First try the expected directory name (for regular distributions)
$expectedPath = Join-Path "$TMP_DOWNLOAD_DIR" "$distributionUrlNameMain"
$expectedMvnPath = Join-Path "$expectedPath" "bin/$MVN_CMD"
if ((Test-Path -Path $expectedPath -PathType Container) -and (Test-Path -Path $expectedMvnPath -PathType Leaf)) {
$actualDistributionDir = $distributionUrlNameMain
}
# If not found, search for any directory with the Maven executable (for snapshots)
if (!$actualDistributionDir) {
Get-ChildItem -Path "$TMP_DOWNLOAD_DIR" -Directory | ForEach-Object {
$testPath = Join-Path $_.FullName "bin/$MVN_CMD"
if (Test-Path -Path $testPath -PathType Leaf) {
$actualDistributionDir = $_.Name
}
}
}
if (!$actualDistributionDir) {
Write-Error "Could not find Maven distribution directory in extracted archive"
}
Write-Verbose "Found extracted Maven distribution directory: $actualDistributionDir"
Rename-Item -Path "$TMP_DOWNLOAD_DIR/$actualDistributionDir" -NewName $MAVEN_HOME_NAME | Out-Null
try {
Move-Item -Path "$TMP_DOWNLOAD_DIR/$MAVEN_HOME_NAME" -Destination $MAVEN_HOME_PARENT | Out-Null
} catch {
if (! (Test-Path -Path "$MAVEN_HOME" -PathType Container)) {
Write-Error "fail to move MAVEN_HOME"
}
} finally {
try { Remove-Item $TMP_DOWNLOAD_DIR -Recurse -Force | Out-Null }
catch { Write-Warning "Cannot remove $TMP_DOWNLOAD_DIR" }
}
Write-Output "MVN_CMD=$MAVEN_HOME/bin/$MVN_CMD"

BIN
nullnull/2025/12/comp_image1_27122025123322_bird.jpg

After

Width: 1280  |  Height: 897  |  Size: 191 KiB

BIN
nullnull/2025/12/comp_image1_27122025123322_joban-khangura-hG8B9pKiilw-unsplash.jpg

After

Width: 2400  |  Height: 3001  |  Size: 2.5 MiB

81
pom.xml

@ -0,0 +1,81 @@
<?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.5.7</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.gcc</groupId>
<artifactId>greencommitte</artifactId>
<version>0.0.1</version>
<name>greencommitte</name>
<description>Green Committee Form Submission On Web </description>
<url/>
<licenses>
<license/>
</licenses>
<developers>
<developer/>
</developers>
<scm>
<connection/>
<developerConnection/>
<tag/>
<url/>
</scm>
<properties>
<java.version>17</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</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>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</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/gcc/greencommitte/GreencommitteApplication.java

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

47
src/main/java/com/gcc/greencommitte/config/AppConfig.java

@ -0,0 +1,47 @@
package com.gcc.greencommitte.config;
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 filebaseurl;
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 getFilebaseurl() {
return filebaseurl;
}
public void setFilebaseurl(String filebaseurl) {
this.filebaseurl = filebaseurl;
}
}

16
src/main/java/com/gcc/greencommitte/config/GlobalAttributes.java

@ -0,0 +1,16 @@
package com.gcc.greencommitte.config;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ModelAttribute;
@ControllerAdvice
public class GlobalAttributes {
@Autowired
private AppConfig appConfig;
@ModelAttribute("baseURL")
public String baseURL() {
return appConfig.getBaseUrl();
}
}

9
src/main/java/com/gcc/greencommitte/config/TomcatConfig.java

@ -0,0 +1,9 @@
package com.gcc.greencommitte.config;
public class TomcatConfig {
}

10
src/main/java/com/gcc/greencommitte/config/TomcatCustomizer.java

@ -0,0 +1,10 @@
package com.gcc.greencommitte.config;
import org.springframework.context.annotation.Configuration;
@Configuration
public class TomcatCustomizer {
}

389
src/main/java/com/gcc/greencommitte/controller/Apicontroller.java

@ -0,0 +1,389 @@
package com.gcc.greencommitte.controller;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Random;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.multipart.MultipartFile;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.gcc.greencommitte.config.AppConfig;
import com.gcc.greencommitte.service.Greencommitteeservice;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpSession;
@RestController
@RequestMapping("/greencommittee/api")
public class Apicontroller {
@Autowired
private AppConfig appConfig;
@Autowired
private Greencommitteeservice gcservice;
@GetMapping(value = "/sendOTP")
public String sendOtp(HttpServletRequest request, @RequestParam String mobileNo) {
// Generate OTP logic as before
String MobileNo = mobileNo;
Random rand = new Random();
int otp = rand.nextInt(90000) + 10000;
String key = "pfTEYN6H";
String entityId = "1401572690000011081";
String templateId = "1407175765770900925";
String appName="Green Committe";
String generatedMessage = "Welcome to GCC! Your OTP for " + appName + " is " + otp + ".";
String urlString = appConfig.getGetOtpUrl() + "from=GCCCRP" + "&key=" + key + "&sender=GCCCRP" + "&to=" + MobileNo + "&body="
+ generatedMessage + "&entityid=" + entityId + "&templateid=" + templateId;
System.out.println("\n urlString---: " + urlString);
String bodyMessage = "";
try {
RestTemplate restTemplate = new RestTemplate();
String Response = restTemplate.getForObject(urlString, String.class);
bodyMessage = Response;
System.out.println("\n bodyMessage" + bodyMessage);
System.out.println("OTP sent successfully!");
} catch (Exception e) {
System.out.print("ERROR---: " + e);
bodyMessage = "Error";
}
HttpSession session = request.getSession();
session.setAttribute("otp", otp);
session.setAttribute("mobileNo", mobileNo);
return bodyMessage;
}
@GetMapping(value = "/verifyOTP")
public String verifyOtp(HttpServletRequest request, @RequestParam String otp) {
HttpSession session = request.getSession();
try {
Integer session_otp = (Integer) session.getAttribute("otp");
//System.out.println("session_otp---:" + session_otp);
Integer entered_otp = Integer.parseInt(otp);
if (session_otp != null && session_otp.equals(entered_otp)) {
System.out.println("Entered OTP Correct");
session.setAttribute("verifiedotp", "success");
return "Success";
} else {
System.out.println("Incorrect OTP. Please enter correct OTPs.");
session.setAttribute("verifiedotp", "error");
return "Error";
}
} catch (NumberFormatException e) {
System.out.println("Invalid OTP format: " + otp);
return "Error";
} catch (Exception e) {
System.out.println("Error verifying OTP: " + e.getMessage());
return "Error";
}
}
@GetMapping("/getcompnatureforpublic")
public ResponseEntity<?> getCompNatureForPublic(){
try {
List<Map<String, Object>> list = gcservice.getCompNatureForPublic();
Map<String, Object> response = new HashMap<>();
response.put("status", "success");
response.put("data", list);
return ResponseEntity.ok(response);
} catch (Exception ex) {
ex.printStackTrace();
Map<String, Object> error = new HashMap<>();
error.put("status", "error");
error.put("message", ex.getMessage());
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(error);
}
}
@GetMapping("/getcompnaturefordept")
public ResponseEntity<?> getCompNatureForDept(){
try {
List<Map<String, Object>> list = gcservice.getCompNatureForDept();
Map<String, Object> response = new HashMap<>();
response.put("status", "success");
response.put("data", list);
return ResponseEntity.ok(response);
} catch (Exception ex) {
ex.printStackTrace();
Map<String, Object> error = new HashMap<>();
error.put("status", "error");
error.put("message", ex.getMessage());
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(error);
}
}
@GetMapping("/getAllDepts")
public ResponseEntity<?> getAllDepts(){
try {
List<Map<String, Object>> list = gcservice.getAllDepts();
Map<String, Object> response = new HashMap<>();
response.put("status", "success");
response.put("data", list);
return ResponseEntity.ok(response);
} catch (Exception ex) {
ex.printStackTrace();
Map<String, Object> error = new HashMap<>();
error.put("status", "error");
error.put("message", ex.getMessage());
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(error);
}
}
@PostMapping("/savepublicform")
public ResponseEntity<?> savepublicform(
@RequestParam String p_name,
@RequestParam String ph_no,
@RequestParam String gender,
@RequestParam String address,
@RequestParam String latitude,
@RequestParam String longitude,
@RequestParam String zone,
@RequestParam String ward,
@RequestParam String remarks,
@RequestParam MultipartFile c1image,
@RequestParam MultipartFile c2image,
@RequestParam String comp_details,
@RequestParam String source) throws JsonMappingException, JsonProcessingException{
ObjectMapper mapper = new ObjectMapper();
List<Map<String, Object>> compList = mapper.readValue(comp_details,
new TypeReference<List<Map<String, Object>>>() {
});
int totalTreeCount = compList.stream()
.mapToInt(item -> Integer.parseInt(item.get("count").toString()))
.sum();
String c1imagePath=null;
String c2imagePath=null;
c1imagePath=gcservice.fileUpload(c1image, "comp_image1");
c2imagePath=gcservice.fileUpload(c2image, "comp_image1");
//System.out.println("======="+latitude+","+longitude);
String saveStatus = gcservice.savepublicform(p_name,ph_no,gender,address,latitude,longitude,zone,ward,remarks,c1imagePath,c2imagePath,compList,totalTreeCount,source);
if (saveStatus == null || saveStatus.equals("error")) {
return ResponseEntity.ok(Map.of(
"status", false,
"message", "failed",
"description", "Failed to save the details"
));
}
return ResponseEntity.ok(Map.of(
"status", true,
"message", "success",
"description", "Details saved successfully",
"ref_id", saveStatus
));
}
@PostMapping("/savedeptform")
public ResponseEntity<?> savedeptform(
@RequestParam String dept_id,
@RequestParam (required = false) String dept_name,
@RequestParam String ph_no,
@RequestParam String designation,
@RequestParam String govt_type,
@RequestParam String address,
@RequestParam String latitude,
@RequestParam String longitude,
@RequestParam String zone,
@RequestParam String ward,
@RequestParam String remarks,
@RequestParam MultipartFile c1image,
@RequestParam MultipartFile c2image,
@RequestParam String comp_details,
@RequestParam String source) throws JsonMappingException, JsonProcessingException{
ObjectMapper mapper = new ObjectMapper();
List<Map<String, Object>> compList = mapper.readValue(comp_details,
new TypeReference<List<Map<String, Object>>>() {
});
int totalTreeCount = compList.stream()
.mapToInt(item -> Integer.parseInt(item.get("count").toString()))
.sum();
String c1imagePath=null;
String c2imagePath=null;
c1imagePath=gcservice.fileUpload(c1image, "comp_image1");
c2imagePath=gcservice.fileUpload(c2image, "comp_image1");
// System.out.println("======="+latitude+","+longitude);
String saveStatus = gcservice.savedeptform(dept_id,dept_name,ph_no,designation,govt_type,address,latitude,longitude,zone,ward,remarks,c1imagePath,c2imagePath,compList,totalTreeCount,source);
if (saveStatus == null || saveStatus.equals("error")) {
return ResponseEntity.ok(Map.of(
"status", false,
"message", "failed",
"description", "Failed to save the details"
));
}
return ResponseEntity.ok(Map.of(
"status", true,
"message", "success",
"description", "Details saved successfully",
"ref_id", saveStatus
));
}
@GetMapping(value = "/sendOTPforwithdraw")
public String sendOtpforwithdraw(HttpServletRequest request, @RequestParam String mobileNo) {
List<?> CompDetailsList = gcservice.findByMobileNo(mobileNo);
System.out.println("CompDetailsList="+CompDetailsList);
if (CompDetailsList == null || CompDetailsList.isEmpty()) {
// If the mobile number is not registered, return an error message
return "Error: This number is not registered.";
}
// Generate OTP logic as before
String MobileNo = mobileNo;
Random rand = new Random();
int otp = rand.nextInt(90000) + 10000;
String key = "pfTEYN6H";
String entityId = "1401572690000011081";
String templateId = "1407175765770900925";
String appName="Green Committe";
String generatedMessage = "Welcome to GCC! Your OTP for " + appName + " is " + otp + ".";
String urlString = appConfig.getGetOtpUrl() + "from=GCCCRP" + "&key=" + key + "&sender=GCCCRP" + "&to=" + MobileNo + "&body="
+ generatedMessage + "&entityid=" + entityId + "&templateid=" + templateId;
System.out.println("\n urlString---: " + urlString);
String bodyMessage = "";
try {
RestTemplate restTemplate = new RestTemplate();
String Response = restTemplate.getForObject(urlString, String.class);
bodyMessage = Response;
System.out.println("\n bodyMessage" + bodyMessage);
System.out.println("OTP sent successfully!");
} catch (Exception e) {
System.out.print("ERROR---: " + e);
bodyMessage = "Error";
}
HttpSession session = request.getSession();
session.setAttribute("otp", otp);
session.setAttribute("mobileNo", mobileNo);
return bodyMessage;
}
// @GetMapping("/checkwithdraw")
// public List<Map<String, Object>> checkWithdrawByMobileNumber(@RequestParam String mobile_num){
//
// return gcservice.checkwithdraw(mobile_num);
// }
@GetMapping("/checkwithdraw")
public List<Map<String, Object>> checkWithdrawByMobileNumber(@RequestParam String mobile_num) {
List<String> refnums = gcservice.getrefnums(mobile_num);
System.out.println("refnums="+refnums);
Map<String, Object> wrapper = new HashMap<>();
List<Map<String, Object>> finalList = new ArrayList<>();
if (refnums.isEmpty()) {
wrapper.put("message", "Empty List");
wrapper.put("status", "Success");
return Collections.singletonList(wrapper);
}
for (String ref : refnums) {
System.out.println("ref="+ref);
Map<String, Object> data = gcservice.getfulldetailsdata(ref);
if (data != null && !data.isEmpty()) {
finalList.add(data);
}
}
wrapper.put("data", finalList);
wrapper.put("message", "Complaint List");
wrapper.put("status", "Success");
return Collections.singletonList(wrapper);
}
@PostMapping("/withdraw")
public ResponseEntity<?> withdraw(@RequestParam String id,@RequestParam String remarks)
{
String saveStatus=gcservice.withdraw(id,remarks);
if (saveStatus == null || saveStatus.equals("error")) {
return ResponseEntity.ok(Map.of(
"status", false,
"message", "failed",
"description", "Failed to withdraw the Complaint"
));
}
return ResponseEntity.ok(Map.of(
"status", true,
"message", "success",
"description", "Application withdrawn successfully",
"ref_id", saveStatus
));
}
}

32
src/main/java/com/gcc/greencommitte/controller/Maincontroller.java

@ -0,0 +1,32 @@
package com.gcc.greencommitte.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
@RequestMapping(value={"/greencommittee"})
public class Maincontroller {
@GetMapping(value = {"", "/","/home"})
public String homepage() {
return "modules/home";
}
@GetMapping("/publicform")
public String publicformpage(){
return "modules/public/form";
}
@GetMapping("/deptform")
public String deptformpage(){
return "modules/department/form";
}
@GetMapping("/withdrawpage")
public String withdrawpage(){
return "modules/withdrawpage";
}
}

36
src/main/java/com/gcc/greencommitte/service/DateTimeUtil.java

@ -0,0 +1,36 @@
package com.gcc.greencommitte.service;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import org.springframework.stereotype.Component;
@Component("greencommitteeDateTimeUtil")
public class DateTimeUtil {
public static String getCurrentDateTime() {
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("ddMMyyyyHHmmss");
LocalDateTime now = LocalDateTime.now();
return now.format(formatter);
}
public static String getCurrentYear() {
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy");
LocalDateTime now = LocalDateTime.now();
return now.format(formatter);
}
public static String getCurrentMonth() {
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("MM");
LocalDateTime now = LocalDateTime.now();
return now.format(formatter);
}
public static String getCurrentDay() {
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd");
LocalDateTime now = LocalDateTime.now();
return now.format(formatter);
}
public static String getCurrentDateTimeMysql() {
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
LocalDateTime now = LocalDateTime.now();
return now.format(formatter);
}
}

612
src/main/java/com/gcc/greencommitte/service/Greencommitteeservice.java

@ -0,0 +1,612 @@
package com.gcc.greencommitte.service;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.sql.PreparedStatement;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.env.Environment;
import org.springframework.http.ResponseEntity;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.support.GeneratedKeyHolder;
import org.springframework.jdbc.support.KeyHolder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;
import com.gcc.greencommitte.config.AppConfig;
@Service
public class Greencommitteeservice {
@Autowired
private AppConfig appconfig;
@Autowired
private JdbcTemplate jdbcTemplate;
private final Environment environment;
public Greencommitteeservice(Environment environment) {
this.environment = environment;
}
public List<Map<String, Object>> getCompNatureForPublic() {
String sql="SELECT * FROM comp_nature WHERE category='public' AND is_active=1 AND is_delete=0";
try {
return jdbcTemplate.queryForList(sql);
} catch (Exception ex) {
ex.printStackTrace();
return new ArrayList<>(); // return empty list on error
}
}
public List<Map<String, Object>> getCompNatureForDept() {
String sql="SELECT * FROM comp_nature WHERE category='dept' AND is_active=1 AND is_delete=0";
try {
return jdbcTemplate.queryForList(sql);
} catch (Exception ex) {
ex.printStackTrace();
return new ArrayList<>(); // return empty list on error
}
}
public List<Map<String, Object>> getAllDepts() {
String sql="SELECT * FROM dept_master WHERE is_active=1 AND is_delete=0";
try {
return jdbcTemplate.queryForList(sql);
} catch (Exception ex) {
ex.printStackTrace();
return new ArrayList<>(); // return empty list on error
}
}
public String fileUpload(MultipartFile file, String name) {
// Set the file path where you want to save it
String uploadDirectory = environment.getProperty("file.upload.directory.mobile");
String serviceFolderName = environment.getProperty("green_committee_foldername");
var year = DateTimeUtil.getCurrentYear();
var month = DateTimeUtil.getCurrentMonth();
uploadDirectory = uploadDirectory + serviceFolderName + "/" + year + "/" + month;
try {
// Create directory if it doesn't exist
Path directoryPath = Paths.get(uploadDirectory);
if (!Files.exists(directoryPath)) {
Files.createDirectories(directoryPath);
}
// Datetime string
String datetimetxt = DateTimeUtil.getCurrentDateTime();
// File name
String fileName = name + "_" + datetimetxt + "_" + file.getOriginalFilename();
fileName = fileName.replaceAll("\\s+", ""); // Remove space on filename
String filePath = uploadDirectory + "/" + fileName;
String filepath_txt = "/" + serviceFolderName + "/" + year + "/" + month + "/" + fileName;
// Create a new Path object
Path path = Paths.get(filePath);
// Get the bytes of the file
byte[] bytes = file.getBytes();
Files.write(path, bytes);
//System.out.println(filePath);
return filepath_txt;
} catch (IOException e) {
e.printStackTrace();
return "Failed to save file " + file.getOriginalFilename();
}
}
@Transactional
public String savepublicform(String p_name, String ph_no, String gender, String address,String latitude,String longitude, String zone, String ward,String remarks,
String c1imagePath, String c2imagePath, List<Map<String, Object>> compList,int totalTreeCount ,String source) {
String cby="public";
String remarksVal = (remarks != null && !remarks.isEmpty()) ? remarks : null;
String sql = "INSERT INTO reg_details ("
+ "cby,p_name,ph_no,gender,address,zone,ward,total_trees,remarks,latitude,longitude,source "
+ ") VALUES (?,?, ?, ?, ?, ?, ?, ?,?,?,?,?)";
KeyHolder keyHolder = new GeneratedKeyHolder();
try {
int result = jdbcTemplate.update(connection -> {
PreparedStatement ps = connection.prepareStatement(sql, new String[] { "id" });
ps.setString(1, cby);
ps.setString(2, p_name);
ps.setString(3, ph_no);
ps.setString(4, gender);
ps.setString(5, address);
ps.setString(6, zone);
ps.setString(7, ward);
ps.setInt(8, totalTreeCount);
ps.setString(9, remarksVal);
ps.setString(10,latitude );
ps.setString(11,longitude);
ps.setString(12,source);
return ps;
}, keyHolder);
//return keyHolder.getKey().intValue();
if (result > 0) {
int generatedId = keyHolder.getKey().intValue();
String prefix = "GC"+LocalDate.now().format(DateTimeFormatter.ofPattern("yyyyMMdd"));
String refId = prefix + generatedId;
String updateSql = "UPDATE reg_details SET ref_id = ? WHERE id = ? ";
jdbcTemplate.update(updateSql,refId, generatedId);
String img1sql="INSERT INTO img_uploads (ref_id,img_path) VALUES (?,?)";
jdbcTemplate.update(img1sql,refId, c1imagePath);
String img2sql="INSERT INTO img_uploads (ref_id,img_path) VALUES (?,?)";
jdbcTemplate.update(img2sql,refId, c2imagePath);
String compSql = "INSERT INTO complaint_details (ref_id, comp_nature_id, no_of_trees) "
+ "VALUES (?, ?, ?)";
for (Map<String, Object> item : compList) {
int compNatureId = Integer.parseInt(item.get("id").toString());
int noOfTrees = Integer.parseInt(item.get("count").toString());
jdbcTemplate.update(compSql, refId, compNatureId, noOfTrees);
}
return refId;
}
//return "error";
} catch (Exception e) {
e.printStackTrace();
}
return "error";
}
@Transactional
public String savedeptform(String dept_id, String dept_name, String ph_no, String designation, String govt_type,
String address,String latitude,String longitude, String zone, String ward, String remarks, String c1imagePath, String c2imagePath,
List<Map<String, Object>> compList, int totalTreeCount,String source) {
String cby="department";
int deptIdInt = Integer.parseInt(dept_id);
String remarksVal = (remarks != null && !remarks.isEmpty()) ? remarks : null;
String sql = "INSERT INTO reg_details ("
+ "cby,dept_id,dept_name,govt_type,designation,ph_no,address,zone,ward,total_trees,remarks,latitude,longitude,source "
+ ") VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?)";
KeyHolder keyHolder = new GeneratedKeyHolder();
try {
int result = jdbcTemplate.update(connection -> {
PreparedStatement ps = connection.prepareStatement(sql, new String[] { "id" });
ps.setString(1, cby);
ps.setInt(2, deptIdInt);
ps.setString(3, dept_name);
ps.setString(4, govt_type);
ps.setString(5, designation);
ps.setString(6, ph_no);
ps.setString(7, address);
ps.setString(8, zone);
ps.setString(9, ward);
ps.setInt(10, totalTreeCount);
ps.setString(11, remarksVal);
ps.setString(12,latitude );
ps.setString(13,longitude);
ps.setString(14,source);
return ps;
}, keyHolder);
//return keyHolder.getKey().intValue();
if (result > 0) {
int generatedId = keyHolder.getKey().intValue();
String prefix = "GC"+LocalDate.now().format(DateTimeFormatter.ofPattern("yyyyMMdd"));
String refId = prefix + generatedId;
String updateSql = "UPDATE reg_details SET ref_id = ? WHERE id = ? ";
jdbcTemplate.update(updateSql,refId, generatedId);
String img1sql="INSERT INTO img_uploads (ref_id,img_path) VALUES (?,?)";
jdbcTemplate.update(img1sql,refId, c1imagePath);
String img2sql="INSERT INTO img_uploads (ref_id,img_path) VALUES (?,?)";
jdbcTemplate.update(img2sql,refId, c2imagePath);
String compSql = "INSERT INTO complaint_details (ref_id, comp_nature_id, no_of_trees) "
+ "VALUES (?, ?, ?)";
for (Map<String, Object> item : compList) {
int compNatureId = Integer.parseInt(item.get("id").toString());
int noOfTrees = Integer.parseInt(item.get("count").toString());
jdbcTemplate.update(compSql, refId, compNatureId, noOfTrees);
}
return refId;
}
//return "error";
} catch (Exception e) {
e.printStackTrace();
}
return "error";
}
@Transactional
public List<Map<String, Object>> findByMobileNo(String mobileNo){
String sqlQuery = "select id from reg_details where ph_no =?";
System.out.println(sqlQuery);
return jdbcTemplate.queryForList(sqlQuery,mobileNo);
}
// public List<Map<String, Object>> checkwithdraw(String mobile_num) {
//
// String sql="SELECT rd.ref_id "
// + " FROM reg_details rd "
// + " WHERE rd.ph_no = ? AND is_active=1 "
// + " AND NOT EXISTS ( "
// + " SELECT 1 "
// + " FROM inspection_data id "
// + " WHERE id.ref_id = rd.ref_id AND id.isactive=1 "
// + " )";
//
// List<String> refIds=jdbcTemplate.query(sql,new Object[]{mobile_num},(rs, rowNum) -> rs.getString("ref_id"));
// Map<String, Object> wrapper = new HashMap<>();
// List<Map<String, Object>> dataList = new ArrayList<>();
//
// if(!refIds.isEmpty()) {
//
// for (String refId : refIds) {
//
// Map<String, Object> fullData = getfulldetailsdata(refId);
//
// if (fullData != null && !fullData.isEmpty()) {
// dataList.add((Map<String, Object>) fullData.get("data"));
// }
// }
//
// wrapper.put("data", dataList);
// wrapper.put("message", "Complaint List");
// wrapper.put("status", "Success");
//
// return Collections.singletonList(wrapper);
//
// }
// else {
//
//
// wrapper.put("message", "Empty List");
// wrapper.put("status", "Success");
//
// return Collections.singletonList(wrapper);
//
// }
//
// }
public Map<String, Object> getfulldetailsdata(String refId) {
Map<String, Object> response = new HashMap<>();
// 1 — Application details
Map<String, Object> app = jdbcTemplate.queryForMap(
"SELECT *,DATE_FORMAT(cdate, '%d-%m-%Y %l:%i %p') as r_Cdate,IFNULL(reinspection_id, '') AS com_reinspection_id FROM reg_details WHERE ref_id=?",
refId
);
// 2 — Complaint details (grouped)
List<Map<String, Object>> complaints = jdbcTemplate.queryForList(
"SELECT cn.name AS nature, SUM(cd.no_of_trees) AS count " +
"FROM complaint_details cd JOIN comp_nature cn ON cn.id=cd.comp_nature_id " +
"WHERE cd.ref_id=? GROUP BY cn.name", refId
);
String compDetails = complaints.stream()
.map(c -> c.get("nature") + "-" + c.get("count"))
.collect(Collectors.joining(","));
// 3 — Complaint images
List<Map<String, Object>> imagePaths =
jdbcTemplate.queryForList(
"SELECT img_path FROM img_uploads WHERE ref_id=? AND is_active=1",
new Object[]{refId}
).stream()
.map(row -> {
Map<String, Object> img = new HashMap<>();
img.put(
"img_path",
appconfig.getFilebaseurl() + "/gccofficialapp/files" + row.get("img_path").toString()
);
return img;
})
.collect(Collectors.toList());
app.put("complaints", complaints);
app.put("comp_details", compDetails);
app.put("image_paths", imagePaths);
List<Map<String, Object>> inspectionList = new ArrayList<>();
String sql =
"SELECT id.*, um.name AS inspector_name, " +
" DATE_FORMAT(id.cdate, '%d-%m-%Y %l:%i %p') AS f_Cdate " +
"FROM inspection_data id " +
"LEFT JOIN user_maping um ON um.userid = id.cby " +
"INNER JOIN ( " +
" SELECT inspection_by, MAX(cdate) AS latest_date " +
" FROM inspection_data " +
" WHERE ref_id = ? AND isactive = 1 " +
" GROUP BY inspection_by " +
") latest ON id.inspection_by = latest.inspection_by " +
" AND id.cdate = latest.latest_date " +
"WHERE id.ref_id = ? AND id.isactive = 1 " +
"ORDER BY FIELD(id.inspection_by, 'GCC', 'NGO', 'TNFD')";
List<Map<String, Object>> rows = jdbcTemplate.queryForList(
sql, refId, refId
);
for (Map<String, Object> row : rows) {
Integer inspId = (Integer) row.get("inspection_data_id");
// 4a — Recommendation details
List<Map<String, Object>> recommend = jdbcTemplate.queryForList(
"SELECT rm.name, itd.nooftrees AS count " +
"FROM inspection_tree_data itd " +
"JOIN inspection_recommend_master rm ON rm.rid = itd.action " +
"WHERE itd.inspection_data_id=? AND itd.isactive=1",
inspId
);
row.put("recommendations", recommend);
List<String> imgs = new ArrayList<>();
if (row.get("file_1") != null) {
imgs.add(appconfig.getFilebaseurl() + "/gccofficialapp/files" + row.get("file_1").toString());
}
if (row.get("file_2") != null) {
imgs.add(appconfig.getFilebaseurl() + "/gccofficialapp/files" + row.get("file_2").toString());
}
if (row.get("file_3") != null) {
imgs.add(appconfig.getFilebaseurl() + "/gccofficialapp/files" + row.get("file_3").toString());
}
row.put("images", imgs);
inspectionList.add(row);
}
app.put("inspections", inspectionList);
String reSql =
"SELECT r.id AS reins_id, r.committee_action, r.remarks AS reins_remarks, " +
" DATE_FORMAT(r.cdate, '%d-%m-%Y %l:%i %p') AS reins_date, " +
" cm.event_name, DATE_FORMAT(cm.event_date, '%d-%m-%Y') AS event_date, crm.name as ins_name " +
"FROM reinspection r " +
"LEFT JOIN create_meeting cm ON cm.id = r.meeting_id " +
" LEFT JOIN committee_recommend_master crm ON crm.id=r.committee_action " +
"WHERE r.ref_id = ? AND r.isactive = 1 " +
"ORDER BY r.id DESC";
List<Map<String, Object>> reinspectionList = jdbcTemplate.queryForList(reSql, refId);
app.put("reinspections", reinspectionList);
Map<String, Object> c1 = null;
List<Map<String, Object>> committeeList = jdbcTemplate.queryForList(
"SELECT cd.*, DATE_FORMAT(cd.cdate, '%d-%m-%Y %l:%i %p') AS c_Cdate, " +
"cm.event_name AS meeting_name, cm.event_date AS meeting_date " +
"FROM committee_data cd " +
"LEFT JOIN create_meeting cm ON cm.id = cd.meeting_id " +
"WHERE cd.ref_id = ? AND cd.isactive = 1",
refId
);
if (!committeeList.isEmpty()) {
c1 = committeeList.get(0);
List<Map<String, Object>> com_complaints = jdbcTemplate.queryForList(
"SELECT crm.name AS nature, SUM(ctd.nooftrees) AS count " +
"FROM committee_tree_data ctd " +
"JOIN committee_recommend_master crm ON crm.id = ctd.committee_action " +
"WHERE ctd.ref_id = ? " +
"GROUP BY crm.name",
refId
);
c1.put("com_complaints", com_complaints);
}
// IMPORTANT: always put committee key (even if null)
app.put("committee", c1);
//response.put("data", app);
return app;
}
public List<String> getrefnums(String mobile_num) {
try {
String sql="SELECT ref_id "
+ " FROM reg_details "
+ " WHERE ph_no = ?";
System.out.println(sql);
return jdbcTemplate.query(sql,new Object[]{mobile_num},(rs, rowNum) -> rs.getString("ref_id"));
} catch (Exception e) {
System.err.println("Error in getrefnums(): " + e.getMessage());
e.printStackTrace();
return Collections.emptyList();
}
}
// public Map<String, Object> getlistdata(String ref) {
//
// Map<String, Object> regDetails = getRegDetails(ref);
//
// List<Map<String, Object>> compDetails = getComplaintDetails(ref);
//
// regDetails.put("comp_details", compDetails);
//
//
//
// String linecompDetails = compDetails.stream()
// .map(c -> c.get("nature") + "-" + c.get("count"))
// .collect(Collectors.joining(","));
//
// List<Map<String, Object>> inspectionList = new ArrayList<>();
//
// String sql =
// "SELECT id.*, um.name AS inspector_name, " +
// " DATE_FORMAT(id.cdate, '%d-%m-%Y %l:%i %p') AS f_Cdate " +
// "FROM inspection_data id " +
// "LEFT JOIN user_maping um ON um.userid = id.cby " +
// "INNER JOIN ( " +
// " SELECT inspection_by, MAX(cdate) AS latest_date " +
// " FROM inspection_data " +
// " WHERE ref_id = ? AND isactive = 1 " +
// " GROUP BY inspection_by " +
// ") latest ON id.inspection_by = latest.inspection_by " +
// " AND id.cdate = latest.latest_date " +
// "WHERE id.ref_id = ? AND id.isactive = 1 " +
// "ORDER BY FIELD(id.inspection_by, 'GCC', 'NGO', 'TNFD')";
//
// List<Map<String, Object>> rows = jdbcTemplate.queryForList(
// sql, ref, ref
// );
//
//
// for (Map<String, Object> row : rows) {
//
// Integer inspId = (Integer) row.get("inspection_data_id");
//
// // 4a — Recommendation details
// List<Map<String, Object>> recommend = jdbcTemplate.queryForList(
// "SELECT rm.name, itd.nooftrees AS count " +
// "FROM inspection_tree_data itd " +
// "JOIN inspection_recommend_master rm ON rm.rid = itd.action " +
// "WHERE itd.inspection_data_id=? AND itd.isactive=1",
// inspId
// );
//
// row.put("recommendations", recommend);
//
// inspectionList.add(row);
// }
//
// regDetails.put("inspections", inspectionList);
//
//
// String reSql =
// "SELECT r.id AS reins_id, r.committee_action, r.remarks AS reins_remarks, " +
// " DATE_FORMAT(r.cdate, '%d-%m-%Y %l:%i %p') AS reins_date, " +
// " cm.event_name, DATE_FORMAT(cm.event_date, '%d-%m-%Y') AS event_date, crm.name as ins_name " +
// "FROM reinspection r " +
// "LEFT JOIN create_meeting cm ON cm.id = r.meeting_id " +
// " LEFT JOIN committee_recommend_master crm ON crm.id=r.committee_action " +
// "WHERE r.ref_id = ? AND r.isactive = 1 " +
// "ORDER BY r.id DESC";
//
// List<Map<String, Object>> reinspectionList = jdbcTemplate.queryForList(reSql, ref);
//
// regDetails.put("reinspections", reinspectionList);
//
// Map<String, Object> c1 = null;
//
// List<Map<String, Object>> committeeList = jdbcTemplate.queryForList(
// "SELECT cd.*, DATE_FORMAT(cd.cdate, '%d-%m-%Y %l:%i %p') AS c_Cdate, " +
// "cm.event_name AS meeting_name, cm.event_date AS meeting_date " +
// "FROM committee_data cd " +
// "LEFT JOIN create_meeting cm ON cm.id = cd.meeting_id " +
// "WHERE cd.ref_id = ? AND cd.isactive = 1",
// ref
// );
//
// if (!committeeList.isEmpty()) {
// c1 = committeeList.get(0);
//
// List<Map<String, Object>> com_complaints = jdbcTemplate.queryForList(
// "SELECT crm.name AS nature, SUM(ctd.nooftrees) AS count " +
// "FROM committee_tree_data ctd " +
// "JOIN committee_recommend_master crm ON crm.id = ctd.committee_action " +
// "WHERE ctd.ref_id = ? " +
// "GROUP BY crm.name",
// ref
// );
//
// c1.put("com_complaints", com_complaints);
// }
//
// // IMPORTANT: always put committee key (even if null)
// regDetails.put("committee", c1);
//
//
// return regDetails;
// }
//
// public Map<String, Object> getRegDetails(String ref) {
// String sql = "SELECT * FROM reg_details WHERE is_active = 1 AND ref_id = ?";
// return jdbcTemplate.queryForMap(sql, ref);
// }
//
// public List<Map<String, Object>> getComplaintDetails(String ref) {
//
// String sql = "SELECT cn.name AS nature, SUM(cd.no_of_trees) AS total_trees " +
// "FROM complaint_details cd " +
// "JOIN comp_nature cn ON cn.id = cd.comp_nature_id " +
// "WHERE cd.is_active = 1 AND cd.ref_id = ? " +
// "GROUP BY cn.name";
//
// return jdbcTemplate.queryForList(sql, ref);
// }
@Transactional
public String withdraw(String id, String remarks) {
String sql="UPDATE reg_details SET is_active=0,is_delete=1,is_withdraw=1,withdraw_remarks=?,withdraw_date=NOW() WHERE id=?";
try {
jdbcTemplate.update(sql, remarks, id);
return "success";
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
return "error";
}
}
}

32
src/main/resources/application-dev.properties

@ -0,0 +1,32 @@
spring.application.name=greencommitte
server.port=8082
app.baseUrl=http://localhost:8082/
app.title=GREEN COMMITTEE
app.filebaseurl=https://gccservices.in
spring.datasource.url=jdbc:mysql://localhost:3306/green_committee
spring.datasource.username=root
spring.datasource.password=root
spring.jpa.hibernate.ddl-auto=update
spring.jpa.show-sql=true
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
app.getOtpUrl=https://tmegov.onex-aura.com/api/sms?
#////////// For street vendor ////////////
green_committee_foldername=green_committee_files
file.upload.directory.mobile=${user.dir}/gcc_mobile_service_uploads/
spring.servlet.multipart.enabled=true
# FIX for FileCountLimitExceededException
spring.servlet.multipart.max-file-size=200MB
spring.servlet.multipart.max-request-size=200MB
server.max-http-post-size=200MB
server.max-http-header-size=20MB

31
src/main/resources/application-prod.properties

@ -0,0 +1,31 @@
spring.application.name=greencommitte
server.port=8082
app.baseUrl=https://gccservices.in/greencommittee/
app.title=GREEN COMMITTEE
app.filebaseurl=https://gccservices.in
spring.datasource.url=jdbc:mysql://gcc-facial-db-instance-1.cf48eqcciziq.ap-south-1.rds.amazonaws.com:3306/green_committee
spring.datasource.username=root
spring.datasource.password=gcc-facial-password
spring.jpa.hibernate.ddl-auto=update
spring.jpa.show-sql=true
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
app.getOtpUrl=https://tmegov.onex-aura.com/api/sms?
#////////// For street vendor ////////////
green_committee_foldername=green_committee_files
file.upload.directory.mobile=${user.dir}/gcc_mobile_service_uploads/
spring.servlet.multipart.enabled=true
# FIX for FileCountLimitExceededException
spring.servlet.multipart.max-file-size=200MB
spring.servlet.multipart.max-request-size=200MB
server.max-http-post-size=200MB
server.max-http-header-size=20MB

3
src/main/resources/application.properties

@ -0,0 +1,3 @@
spring.application.name=greencommitte
spring.profiles.active=dev

BIN
src/main/resources/favicon.ico

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());

101
src/main/resources/static/assets/_js/pages/be_tables_datatables.js

@ -0,0 +1,101 @@
/*
* Document : be_tables_datatables.js
* Author : pixelcave
* Description: Custom JS code used in DataTables Page
*/
// DataTables, for more examples you can check out https://www.datatables.net/
class pageTablesDatatables {
/*
* Init DataTables functionality
*
*/
static initDataTables() {
// Override a few default classes
jQuery.extend(jQuery.fn.dataTable.ext.classes, {
sWrapper: "dataTables_wrapper dt-bootstrap5",
sFilterInput: "form-control",
sLengthSelect: "form-select"
});
// Override a few defaults
jQuery.extend(true, jQuery.fn.dataTable.defaults, {
language: {
lengthMenu: "_MENU_",
search: "_INPUT_",
searchPlaceholder: "Search..",
info: "Page <strong>_PAGE_</strong> of <strong>_PAGES_</strong>",
paginate: {
first: '<i class="fa fa-angle-double-left"></i>',
previous: '<i class="fa fa-angle-left"></i>',
next: '<i class="fa fa-angle-right"></i>',
last: '<i class="fa fa-angle-double-right"></i>'
}
}
});
// Override buttons default classes
jQuery.extend(true, jQuery.fn.DataTable.Buttons.defaults, {
dom: {
button: {
className: 'btn btn-sm btn-primary'
},
}
});
// Init full DataTable
jQuery('.js-dataTable-full').DataTable({
pageLength: 5,
lengthMenu: [[5, 10, 20], [5, 10, 20]],
autoWidth: false
});
// Init DataTable with Buttons
jQuery('.js-dataTable-buttons').DataTable({
pageLength: 5,
lengthMenu: [[5, 10, 20], [5, 10, 20]],
autoWidth: false,
buttons: ['copy', 'csv', 'excel', 'pdf', 'print'],
dom: "<'row'<'col-sm-12'<'text-center bg-body-light py-2 mb-2'B>>>" +
"<'row'<'col-sm-12 col-md-6'l><'col-sm-12 col-md-6'f>><'row'<'col-sm-12'tr>><'row'<'col-sm-12 col-md-5'i><'col-sm-12 col-md-7'p>>"
});
// Init full extra DataTable
jQuery('.js-dataTable-full-pagination').DataTable({
pagingType: "full_numbers",
pageLength: 5,
lengthMenu: [[5, 10, 20], [5, 10, 20]],
autoWidth: false
});
// Init simple DataTable
jQuery('.js-dataTable-simple').DataTable({
pageLength: 5,
lengthMenu: false,
searching: false,
autoWidth: false,
dom: "<'row'<'col-sm-12'tr>>" +
"<'row'<'col-sm-6'i><'col-sm-6'p>>"
});
// Init responsive DataTable
jQuery('.js-dataTable-responsive').DataTable({
pagingType: "full_numbers",
pageLength: 5,
lengthMenu: [[5, 10, 20], [5, 10, 20]],
autoWidth: false,
responsive: true
});
}
/*
* Init functionality
*
*/
static init() {
this.initDataTables();
}
}
// Initialize when page loads
Dashmix.onLoad(() => pageTablesDatatables.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;
}
}

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

Loading…
Cancel
Save