feat: initial commit - Band Management application

This commit is contained in:
2026-01-06 03:11:46 +01:00
commit 34e12e00b3
24543 changed files with 3991790 additions and 0 deletions

View File

@@ -0,0 +1,8 @@
# directories
**/bin/
**/obj/
**/out/
# files
Dockerfile*
**/*.md

View File

@@ -0,0 +1,14 @@
root = true
[*]
charset = utf-8
indent_style = space
indent_size = 2
end_of_line = lf
insert_final_newline = true
trim_trailing_whitespace = true
[*.md]
max_line_length = off
trim_trailing_whitespace = false

View File

@@ -0,0 +1,209 @@
* text eol=lf
## GITATTRIBUTES FOR WEB PROJECTS
#
# These settings are for any web project.
#
# Details per file setting:
# text These files should be normalized (i.e. convert CRLF to LF).
# binary These files are binary and should be left untouched.
#
# Note that binary is a macro for -text -diff.
######################################################################
# Auto detect
## Handle line endings automatically for files detected as
## text and leave all files detected as binary untouched.
## This will handle all files NOT defined below.
* text=auto
# Source code
*.bash text eol=lf
*.bat text eol=crlf
*.cmd text eol=crlf
*.coffee text
*.css text diff=css
*.htm text diff=html
*.html text diff=html
*.inc text
*.ini text
*.js text
*.json text
*.jsx text
*.less text
*.ls text
*.map text -diff
*.od text
*.onlydata text
*.php text diff=php
*.pl text
*.ps1 text eol=crlf
*.py text diff=python
*.rb text diff=ruby
*.sass text
*.scm text
*.scss text diff=css
*.sh text eol=lf
.husky/* text eol=lf
*.sql text
*.styl text
*.tag text
*.ts text
*.tsx text
*.xml text
*.xhtml text diff=html
# Docker
Dockerfile text
# Documentation
*.ipynb text eol=lf
*.markdown text diff=markdown
*.md text diff=markdown
*.mdwn text diff=markdown
*.mdown text diff=markdown
*.mkd text diff=markdown
*.mkdn text diff=markdown
*.mdtxt text
*.mdtext text
*.txt text
AUTHORS text
CHANGELOG text
CHANGES text
CONTRIBUTING text
COPYING text
copyright text
*COPYRIGHT* text
INSTALL text
license text
LICENSE text
NEWS text
readme text
*README* text
TODO text
# Templates
*.dot text
*.ejs text
*.erb text
*.haml text
*.handlebars text
*.hbs text
*.hbt text
*.jade text
*.latte text
*.mustache text
*.njk text
*.phtml text
*.svelte text
*.tmpl text
*.tpl text
*.twig text
*.vue text
# Configs
*.cnf text
*.conf text
*.config text
.editorconfig text
.env text
.gitattributes text
.gitconfig text
.htaccess text
*.lock text -diff
package.json text eol=lf
package-lock.json text eol=lf -diff
pnpm-lock.yaml text eol=lf -diff
.prettierrc text
yarn.lock text -diff
*.toml text
*.yaml text
*.yml text
browserslist text
Makefile text
makefile text
# Heroku
Procfile text
# Graphics
*.ai binary
*.bmp binary
*.eps binary
*.gif binary
*.gifv binary
*.ico binary
*.jng binary
*.jp2 binary
*.jpg binary
*.jpeg binary
*.jpx binary
*.jxr binary
*.pdf binary
*.png binary
*.psb binary
*.psd binary
# SVG treated as an asset (binary) by default.
# *.svg text
# If you want to treat it as binary,
# use the following line instead.
*.svg binary
*.svgz binary
*.tif binary
*.tiff binary
*.wbmp binary
*.webp binary
# Audio
*.kar binary
*.m4a binary
*.mid binary
*.midi binary
*.mp3 binary
*.ogg binary
*.ra binary
# Video
*.3gpp binary
*.3gp binary
*.as binary
*.asf binary
*.asx binary
*.avi binary
*.fla binary
*.flv binary
*.m4v binary
*.mng binary
*.mov binary
*.mp4 binary
*.mpeg binary
*.mpg binary
*.ogv binary
*.swc binary
*.swf binary
*.webm binary
# Archives
*.7z binary
*.gz binary
*.jar binary
*.rar binary
*.tar binary
*.zip binary
# Fonts
*.ttf binary
*.eot binary
*.otf binary
*.woff binary
*.woff2 binary
# Executables
*.exe binary
*.pyc binary
# RC files (like .babelrc or .eslintrc)
*.*rc text
# Ignore files (like .npmignore or .gitignore)
*.*ignore text

View File

@@ -0,0 +1,418 @@
# globs
Makefile.in
*.userprefs
*.usertasks
config.make
config.status
aclocal.m4
install-sh
autom4te.cache/
*.tar.gz
tarballs/
test-results/
# Mac bundle stuff
*.dmg
*.app
# content below from: https://github.com/github/gitignore/blob/main/Global/macOS.gitignore
# General
.DS_Store
.AppleDouble
.LSOverride
# Icon must end with two \r
Icon
# Thumbnails
._*
# Files that might appear in the root of a volume
.DocumentRevisions-V100
.fseventsd
.Spotlight-V100
.TemporaryItems
.Trashes
.VolumeIcon.icns
.com.apple.timemachine.donotpresent
# Directories potentially created on remote AFP share
.AppleDB
.AppleDesktop
Network Trash Folder
Temporary Items
.apdisk
# content below from: https://github.com/github/gitignore/blob/main/Global/Windows.gitignore
# Windows thumbnail cache files
Thumbs.db
ehthumbs.db
ehthumbs_vista.db
# Dump file
*.stackdump
# Folder config file
[Dd]esktop.ini
# Recycle Bin used on file shares
$RECYCLE.BIN/
# Windows Installer files
*.cab
*.msi
*.msix
*.msm
*.msp
# Windows shortcuts
*.lnk
# content below from: https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
## Ignore Visual Studio temporary files, build results, and
## files generated by popular Visual Studio add-ons.
##
## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
# User-specific files
*.suo
*.user
*.userosscache
*.sln.docstates
# User-specific files (MonoDevelop/Xamarin Studio)
*.userprefs
# Build results
[Dd]ebug/
[Dd]ebugPublic/
[Rr]elease/
[Rr]eleases/
x64/
x86/
bld/
[Bb]in/
[Oo]bj/
[Ll]og/
# Visual Studio 2015/2017 cache/options directory
.vs/
# Uncomment if you have tasks that create the project's static files in wwwroot
# Ignoring following files/folder only for master
wwwroot/vendor/**/*.css
wwwroot/vendor/fonts/*.css
wwwroot/vendor/fonts/**/*
wwwroot/vendor/**/*.js
wwwroot/vendor/css
src/fonts/iconify-icons.css
# Visual Studio 2017 auto generated files
Generated\ Files/
# MSTest test Results
[Tt]est[Rr]esult*/
[Bb]uild[Ll]og.*
# NUNIT
*.VisualState.xml
TestResult.xml
# Build Results of an ATL Project
[Dd]ebugPS/
[Rr]eleasePS/
dlldata.c
# Benchmark Results
BenchmarkDotNet.Artifacts/
# .NET Core
project.lock.json
project.fragment.lock.json
artifacts/
# StyleCop
StyleCopReport.xml
# Files built by Visual Studio
*_i.c
*_p.c
*_h.h
*.ilk
*.meta
*.obj
*.iobj
*.pch
*.pdb
*.ipdb
*.pgc
*.pgd
*.rsp
*.sbr
*.tlb
*.tli
*.tlh
*.tmp
*.tmp_proj
*_wpftmp.csproj
*.log
*.vspscc
*.vssscc
.builds
*.pidb
*.svclog
*.scc
# Chutzpah Test files
_Chutzpah*
# Visual C++ cache files
ipch/
*.aps
*.ncb
*.opendb
*.opensdf
*.sdf
*.cachefile
*.VC.db
*.VC.VC.opendb
# Visual Studio profiler
*.psess
*.vsp
*.vspx
*.sap
# Visual Studio Trace Files
*.e2e
# TFS 2012 Local Workspace
$tf/
# Guidance Automation Toolkit
*.gpState
# ReSharper is a .NET coding add-in
_ReSharper*/
*.[Rr]e[Ss]harper
*.DotSettings.user
# JustCode is a .NET coding add-in
.JustCode
# TeamCity is a build add-in
_TeamCity*
# DotCover is a Code Coverage Tool
*.dotCover
# AxoCover is a Code Coverage Tool
.axoCover/*
!.axoCover/settings.json
# Visual Studio code coverage results
*.coverage
*.coveragexml
# NCrunch
_NCrunch_*
.*crunch*.local.xml
nCrunchTemp_*
# MightyMoose
*.mm.*
AutoTest.Net/
# Web workbench (sass)
.sass-cache/
# Installshield output folder
[Ee]xpress/
# DocProject is a documentation generator add-in
DocProject/buildhelp/
DocProject/Help/*.HxT
DocProject/Help/*.HxC
DocProject/Help/*.hhc
DocProject/Help/*.hhk
DocProject/Help/*.hhp
DocProject/Help/Html2
DocProject/Help/html
# Click-Once directory
publish/
# Publish Web Output
*.[Pp]ublish.xml
*.azurePubxml
# Note: Comment the next line if you want to checkin your web deploy settings,
# but database connection strings (with potential passwords) will be unencrypted
*.pubxml
*.publishproj
# Microsoft Azure Web App publish settings. Comment the next line if you want to
# checkin your Azure Web App publish settings, but sensitive information contained
# in these scripts will be unencrypted
PublishScripts/
# NuGet Packages
*.nupkg
# The packages folder can be ignored because of Package Restore
**/[Pp]ackages/*
# except build/, which is used as an MSBuild target.
!**/[Pp]ackages/build/
# Uncomment if necessary however generally it will be regenerated when needed
#!**/[Pp]ackages/repositories.config
# NuGet v3's project.json files produces more ignorable files
*.nuget.props
*.nuget.targets
# Microsoft Azure Build Output
csx/
*.build.csdef
# Microsoft Azure Emulator
ecf/
rcf/
# Windows Store app package directories and files
AppPackages/
BundleArtifacts/
Package.StoreAssociation.xml
_pkginfo.txt
*.appx
# Visual Studio cache files
# files ending in .cache can be ignored
*.[Cc]ache
# but keep track of directories ending in .cache
!*.[Cc]ache/
# Others
ClientBin/
~$*
*~
*.dbmdl
*.dbproj.schemaview
*.jfm
*.pfx
*.publishsettings
orleans.codegen.cs
# Including strong name files can present a security risk
# (https://github.com/github/gitignore/pull/2483#issue-259490424)
#*.snk
# Since there are multiple workflows, uncomment next line to ignore bower_components
# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
#bower_components/
# RIA/Silverlight projects
Generated_Code/
# Backup & report files from converting an old project file
# to a newer Visual Studio version. Backup files are not needed,
# because we have git ;-)
_UpgradeReport_Files/
Backup*/
UpgradeLog*.XML
UpgradeLog*.htm
ServiceFabricBackup/
*.rptproj.bak
# SQL Server files
*.mdf
*.ldf
*.ndf
# Business Intelligence projects
*.rdl.data
*.bim.layout
*.bim_*.settings
*.rptproj.rsuser
# Microsoft Fakes
FakesAssemblies/
# GhostDoc plugin setting file
*.GhostDoc.xml
# Node.js Tools for Visual Studio
.ntvs_analysis.dat
node_modules/
# Visual Studio 6 build log
*.plg
# Visual Studio 6 workspace options file
*.opt
# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
*.vbw
# Visual Studio LightSwitch build output
**/*.HTMLClient/GeneratedArtifacts
**/*.DesktopClient/GeneratedArtifacts
**/*.DesktopClient/ModelManifest.xml
**/*.Server/GeneratedArtifacts
**/*.Server/ModelManifest.xml
_Pvt_Extensions
# Paket dependency manager
.paket/paket.exe
paket-files/
# FAKE - F# Make
.fake/
# JetBrains Rider
.idea/
*.sln.iml
# CodeRush personal settings
.cr/personal
# Python Tools for Visual Studio (PTVS)
__pycache__/
*.pyc
# Cake - Uncomment if you are using it
# tools/**
# !tools/packages.config
# Tabs Studio
*.tss
# Telerik's JustMock configuration file
*.jmconfig
# BizTalk build output
*.btp.cs
*.btm.cs
*.odx.cs
*.xsd.cs
# OpenCover UI analysis results
OpenCover/
# Azure Stream Analytics local run output
ASALocalRun/
# MSBuild Binary and Structured Log
*.binlog
# NVidia Nsight GPU debugger configuration file
*.nvuser
# MFractors (Xamarin productivity tool) working folder
.mfractor/
# Local History for Visual Studio
.localhistory/
# wal and shm files - SQLite
*-wal
*-shm

View File

@@ -0,0 +1,3 @@
dist
node_modules
assets/vendor

View File

@@ -0,0 +1,19 @@
{
"arrowParens": "avoid",
"bracketSpacing": true,
"bracketSameLine": true,
"htmlWhitespaceSensitivity": "css",
"insertPragma": false,
"jsxSingleQuote": true,
"printWidth": 120,
"proseWrap": "preserve",
"quoteProps": "as-needed",
"requirePragma": false,
"semi": true,
"singleQuote": true,
"tabWidth": 2,
"trailingComma": "none",
"useTabs": false,
"endOfLine": "lf",
"embeddedLanguageFormatting": "auto"
}

View File

@@ -0,0 +1,8 @@
{
"recommendations": [
"ms-dotnettools.csharp",
"jorgeserrano.vscode-csharp-snippets",
"esbenp.prettier-vscode",
"editorconfig.editorconfig"
]
}

View File

@@ -0,0 +1,44 @@
{
"editor.wordWrap": "off",
"editor.formatOnSave": true,
"files.trimFinalNewlines": true,
"diffEditor.ignoreTrimWhitespace": false,
"cSpell.language": "en",
"search.exclude": {
"**/node_modules": true,
"**/_temp": true,
"**/bower_components": true,
"*.min.js": true,
"*.min.css": true
},
// JS
"javascript.updateImportsOnFileMove.enabled": "always",
// JSON
"[json]": {
"editor.defaultFormatter": "vscode.json-language-features"
},
// Extension: Prettier
"prettier.requireConfig": true,
"prettier.configPath": ".prettierrc.json",
"prettier.ignorePath": ".prettierignore",
"[javascript]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
},
"[typescript]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
},
"[markdown]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
},
"[scss]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
},
"[css]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
},
// Extension: Git
"git.rebaseWhenSync": true,
"git.enableSmartCommit": true,
// Extension: npm
"npm.packageManager": "yarn",
}

View File

@@ -0,0 +1,24 @@
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>net9.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="9.0.0" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="9.0.0">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
<PackageReference Include="Microsoft.EntityFrameworkCore.SQLite" Version="9.0.0" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="9.0.0">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
<PackageReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Design" Version="9.0.0" />
<PackageReference Include="Microsoft.Data.Sqlite" Version="9.0.0" />
<None Update="AspnetCoreMvcFullContext.db">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
</ItemGroup>
</Project>

View File

@@ -0,0 +1,25 @@
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.8.34322.80
MinimumVisualStudioVersion = 10.0.40219.1
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AspnetCoreMvcStarter", "AspnetCoreMvcStarter.csproj", "{F937201A-3A7A-4D06-8DA6-1D8B0D03C354}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{F937201A-3A7A-4D06-8DA6-1D8B0D03C354}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{F937201A-3A7A-4D06-8DA6-1D8B0D03C354}.Debug|Any CPU.Build.0 = Debug|Any CPU
{F937201A-3A7A-4D06-8DA6-1D8B0D03C354}.Release|Any CPU.ActiveCfg = Release|Any CPU
{F937201A-3A7A-4D06-8DA6-1D8B0D03C354}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {C2A041B0-85FC-4251-9C0F-E6B5862D4B3C}
EndGlobalSection
EndGlobal

View File

@@ -0,0 +1,31 @@
using System.Diagnostics;
using Microsoft.AspNetCore.Mvc;
using AspnetCoreMvcStarter.Models;
namespace AspnetCoreMvcStarter.Controllers;
public class HomeController : Controller
{
private readonly ILogger<HomeController> _logger;
public HomeController(ILogger<HomeController> logger)
{
_logger = logger;
}
public IActionResult Index()
{
return View();
}
public IActionResult Privacy()
{
return View();
}
[ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)]
public IActionResult Error()
{
return View(new ErrorViewModel { RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier });
}
}

View File

@@ -0,0 +1,10 @@
using System.Diagnostics;
using Microsoft.AspNetCore.Mvc;
using AspnetCoreMvcStarter.Models;
namespace AspnetCoreMvcStarter.Controllers;
public class Page2 : Controller
{
public IActionResult Index() => View();
}

View File

@@ -0,0 +1,27 @@
# Use the .NET 9 SDK image for building the application
FROM mcr.microsoft.com/dotnet/sdk:9.0 AS build-env
WORKDIR /AspnetCoreMvcStarter
# Copy everything
COPY . ./
# Restore as distinct layers
RUN dotnet restore
# Copy the entire project and build
RUN dotnet publish -c Release -o out
# Build runtime image
FROM mcr.microsoft.com/dotnet/aspnet:9.0
WORKDIR /AspnetCoreMvcStarter
COPY --from=build-env /AspnetCoreMvcStarter/out ./
# Expose port 5050 for the application
EXPOSE 80
# Set the entry point for the container
ENTRYPOINT ["dotnet", "AspnetCoreMvcStarter.dll"]
# Display a message in the terminal during build
RUN echo -----------------------------------------------
RUN echo Application is running at http://localhost:5050
RUN echo -----------------------------------------------

View File

@@ -0,0 +1,285 @@
const path = require('path');
const merge = require('merge-stream');
// Config
// -------------------------------------------------------------------------------
const env = require('gulp-environment');
process.env.NODE_ENV = env.current.name;
const conf = (() => {
const _conf = require('./build-config');
return require('deepmerge').all([{}, _conf.base || {}, _conf[process.env.NODE_ENV] || {}]);
})();
conf.distPath = path.resolve(__dirname, conf.distPath).replace(/\\/g, '/');
// Modules
// -------------------------------------------------------------------------------
const { src, dest, parallel, series, watch } = require('gulp');
const webpack = require('webpack');
const sass = require('gulp-dart-sass');
const localSass = require('sass');
const autoprefixer = require('gulp-autoprefixer');
const exec = require('gulp-exec');
const rename = require('gulp-rename');
const uglify = require('gulp-uglify');
const gulpIf = require('gulp-if');
const sourcemaps = require('gulp-sourcemaps');
const { deleteAsync } = require('del');
const colors = require('ansi-colors');
const log = require('fancy-log');
const browserSync = require('browser-sync').create();
colors.enabled = require('color-support').hasBasic;
// Utilities
// -------------------------------------------------------------------------------
function normalize(p) {
return p.replace(/\\/g, '/');
}
function root(p) {
return p.startsWith('!')
? normalize(`!${path.join(__dirname, 'src', p.slice(1))}`)
: normalize(path.join(__dirname, 'src', p));
}
function srcGlob(...src) {
return src.map(p => root(p)).concat(conf.exclude.map(d => `!${root(d)}/**/*`));
}
// Tasks
// -------------------------------------------------------------------------------
// Build CSS
// -------------------------------------------------------------------------------
const buildCssTask = function (cb) {
return src(srcGlob('**/*.scss', '!**/_*.scss'))
.pipe(gulpIf(conf.sourcemaps, sourcemaps.init()))
.pipe(
// If sass is installed on your local machine, it will use command line to compile sass else it will use dart sass npm which 3 time slower
gulpIf(
localSass,
exec(
// If conf.minify == true, generate compressed style without sourcemap
gulpIf(
conf.minify,
`sass --load-path=node_modules/ src/site.scss:${conf.distPath}/css/site.css src/scss:${conf.distPath}/vendor/css src/fonts:${conf.distPath}/vendor/fonts src/libs:${conf.distPath}/vendor/libs --style compressed --no-source-map`,
`sass --load-path=node_modules/ src/site.scss:${conf.distPath}/css/site.css src/scss:${conf.distPath}/vendor/css src/fonts:${conf.distPath}/vendor/fonts src/libs:${conf.distPath}/vendor/libs --no-source-map`
),
function (err) {
cb(err);
}
),
sass
.sync({
includePaths: ['node_modules'], // Add this line to include node_modules
outputStyle: conf.minify ? 'compressed' : 'expanded'
})
.on('error', sass.logError)
)
)
.pipe(gulpIf(conf.sourcemaps, sourcemaps.write()))
.pipe(autoprefixer())
.pipe(rename({ extname: '.css' }))
.pipe(
rename(function (path) {
path.dirname = path.dirname.replace('scss', 'css');
})
)
.pipe(dest(conf.distPath))
.pipe(browserSync.stream());
};
// Build JS
// -------------------------------------------------------------------------------
const webpackJsTask = function (cb) {
setTimeout(function () {
webpack(require('./webpack.config'), (err, stats) => {
if (err) {
log(colors.gray('Webpack error:'), colors.red(err.stack || err));
if (err.details) log(colors.gray('Webpack error details:'), err.details);
return cb();
}
const info = stats.toJson();
if (stats.hasErrors()) {
info.errors.forEach(e => log(colors.gray('Webpack compilation error:'), colors.red(e)));
}
if (stats.hasWarnings()) {
info.warnings.forEach(w => log(colors.gray('Webpack compilation warning:'), colors.yellow(w)));
}
// Print log
log(
stats.toString({
colors: colors.enabled,
hash: false,
timings: false,
chunks: false,
chunkModules: false,
modules: false,
children: true,
version: true,
cached: false,
cachedAssets: false,
reasons: false,
source: false,
errorDetails: false
})
);
cb();
browserSync.reload();
});
}, 1);
};
const pageJsTask = function () {
return src(conf.distPath + `/js/**/*.js`)
.pipe(gulpIf(conf.minify, uglify()))
.pipe(dest(conf.distPath + `/js`));
};
// Build fonts
// -------------------------------------------------------------------------------
const FONT_TASKS = [
{
name: 'fontawesome',
path: 'node_modules/@fortawesome/fontawesome-free/webfonts/*'
},
{
name: 'flags',
path: 'node_modules/flag-icons/flags/**/*'
},
{
name: 'tabler',
path: 'node_modules/@tabler/icons/iconfont/fonts/*'
}
].reduce(function (tasks, font) {
const functionName = `buildFonts${font.name.replace(/^./, m => m.toUpperCase())}Task`;
const taskFunction = function () {
// return src(root(font.path))
return (
src(font.path)
// .pipe(dest(normalize(path.join(conf.distPath, 'fonts', font.name))))
.pipe(dest(path.join(conf.distPath + `/vendor/`, 'fonts', font.name)))
);
};
Object.defineProperty(taskFunction, 'name', {
value: functionName
});
return tasks.concat([taskFunction]);
}, []);
// Formula module requires KaTeX - Quill Editor
const KATEX_FONT_TASK = [
{
name: 'katex',
path: 'node_modules/katex/dist/fonts/*'
}
].reduce(function (tasks, font) {
const functionName = `buildFonts${font.name.replace(/^./, m => m.toUpperCase())}Task`;
const taskFunction = function () {
return src(font.path).pipe(dest(path.join(conf.distPath, 'vendor/libs/quill/fonts')));
};
Object.defineProperty(taskFunction, 'name', {
value: functionName
});
return tasks.concat([taskFunction]);
}, []);
const buildFontsTask = parallel(FONT_TASKS, KATEX_FONT_TASK);
// Copy task for third party plugins until we use npm packages
const buildPluginCopyTask = function () {
return merge(
src('src/libs/jstree/themes/**/*.*').pipe(dest(path.join(conf.distPath, 'vendor/libs/jstree/themes/'))),
src('src/libs/leaflet/images/**/*.*').pipe(dest(path.join(conf.distPath, 'vendor/libs/leaflet/images/'))),
src('src/fonts/tabler/**/*.*').pipe(dest(path.join(conf.distPath, 'vendor/fonts/tabler/')))
);
};
// Iconify task
// -------------------------------------------------------------------------------
const buildIconifyTask = function (cb) {
// Create required directories without copying files
const fs = require('fs');
const directories = ['./src/fonts/iconify', './src/fonts'];
directories.forEach(dir => {
if (!fs.existsSync(dir)) {
fs.mkdirSync(dir, { recursive: true });
}
});
const iconify = require('child_process').spawn('node', ['./src/fonts/iconify/iconify.js'], {
cwd: __dirname
});
iconify.stdout.on('data', data => {
console.log(data.toString());
});
iconify.stderr.on('data', data => {
console.error(data.toString());
});
iconify.on('close', code => {
cb();
});
};
// Clean build directory
// -------------------------------------------------------------------------------
const cleanTask = function () {
return deleteAsync([`${conf.distPath}/vendor/**/*`], {
force: true
});
};
const cleanSourcemapsTask = function () {
return deleteAsync([`${conf.distPath}/**/*.map`], {
force: true
});
};
const cleanAllTask = parallel(cleanTask, cleanSourcemapsTask);
// Watch
// -------------------------------------------------------------------------------
const watchTask = function () {
watch(srcGlob('**/*.scss'), buildCssTask);
watch(srcGlob('**/*.js', '!js/**/*.js'), webpackJsTask);
watch(srcGlob('/js/**/*.js'), pageJsTask);
};
// Build (Dev & Prod)
// -------------------------------------------------------------------------------
const buildJsTask = series(webpackJsTask, pageJsTask, buildPluginCopyTask);
const buildTasks = [buildCssTask, buildJsTask, buildFontsTask, buildIconifyTask];
const buildTask = conf.cleanDist
? series(cleanAllTask, parallel(buildTasks))
: series(cleanAllTask, cleanSourcemapsTask, parallel(buildTasks));
// Exports
// -------------------------------------------------------------------------------
module.exports = {
default: buildTask,
clean: cleanAllTask,
'build:js': buildJsTask,
'build:css': buildCssTask,
'build:fonts': buildFontsTask,
'build:iconify': buildIconifyTask,
build: buildTask,
watch: watchTask
};

View File

@@ -0,0 +1,8 @@
namespace AspnetCoreMvcStarter.Models;
public class ErrorViewModel
{
public string? RequestId { get; set; }
public bool ShowRequestId => !string.IsNullOrEmpty(RequestId);
}

View File

@@ -0,0 +1,29 @@
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
// Add services to the container.
builder.Services.AddControllersWithViews();
var app = builder.Build();
// Configure the HTTP request pipeline.
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Home/Error");
// The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseAuthorization();
app.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
app.Run();

View File

@@ -0,0 +1,37 @@
{
"iisSettings": {
"windowsAuthentication": false,
"anonymousAuthentication": true,
"iisExpress": {
"applicationUrl": "http://localhost:6445",
"sslPort": 44383
}
},
"profiles": {
"http": {
"commandName": "Project",
"dotnetRunMessages": true,
"launchBrowser": true,
"applicationUrl": "http://localhost:5055",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
},
"https": {
"commandName": "Project",
"dotnetRunMessages": true,
"launchBrowser": true,
"applicationUrl": "https://localhost:7230;http://localhost:5055",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
},
"IIS Express": {
"commandName": "IISExpress",
"launchBrowser": true,
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
}
}
}

View File

@@ -0,0 +1,6 @@
@{
ViewData["Title"] = "Page 1 - Starter Kit";
}
<h4 class="py-3 mb-4">Home Page</h4>
<p>For more layout options refer <a href='@TempData.Peek("documentation")' target="_blank" rel="noopener noreferrer">documentation</a>.</p>

View File

@@ -0,0 +1,7 @@
@{
Layout = "_BlankLayout";
ViewData["Title"] = "Privacy Policy";
}
<h1>@ViewData["Title"]</h1>
<p>Use this page to detail your site's privacy policy.</p>

View File

@@ -0,0 +1,8 @@
@{
ViewData["Title"] = "Page 2 - Starter Kit";
}
@* ************** Content ************** *@
<h4 class="py-4 mb-6">Page 2</h4>
<p>Sample page.<br />For more layout options, refer <a href="https://demos.pixinvent.com/vuexy-html-admin-template/documentation/net-core-mvc-init-layout.html" target="_blank" class="fw-medium">Layout docs</a>.</p>

View File

@@ -0,0 +1,25 @@
@model ErrorViewModel
@{
ViewData["Title"] = "Error";
}
<h1 class="text-danger">Error.</h1>
<h2 class="text-danger">An error occurred while processing your request.</h2>
@if (Model.ShowRequestId)
{
<p>
<strong>Request ID:</strong> <code>@Model.RequestId</code>
</p>
}
<h3>Development Mode</h3>
<p>
Swapping to <strong>Development</strong> environment will display more detailed information about the error that occurred.
</p>
<p>
<strong>The Development environment shouldn't be enabled for deployed applications.</strong>
It can result in displaying sensitive information from exceptions to end users.
For local debugging, enable the <strong>Development</strong> environment by setting the <strong>ASPNETCORE_ENVIRONMENT</strong> environment variable to <strong>Development</strong>
and restarting the app.
</p>

View File

@@ -0,0 +1,26 @@
@{
TempData.Keep();
ViewData["containerNav"] ??= "container-fluid";
}
<!-- Footer -->
<footer class="content-footer footer bg-footer-theme">
<div class="@ViewData["containerNav"]">
<div class="footer-container d-flex align-items-center justify-content-between py-4 flex-md-row flex-column">
<div class="text-body">
&#169;
<script>
document.write(new Date().getFullYear());
</script>
, made with ❤️ by <a href="@TempData.Peek("authorUrl")" target="_blank" class="footer-link">@TempData.Peek("authorName")</a>
</div>
<div class="d-none d-lg-inline-block">
<a href='@TempData.Peek("licenseUrl")' class="footer-link me-4" target="_blank">License</a>
<a href='@TempData.Peek("moreThemes")' target="_blank" class="footer-link me-4">More Themes</a>
<a href='@TempData.Peek("documentation_menu_link")' target="_blank" class="footer-link me-4">Documentation</a>
<a href='@TempData.Peek("support")' target="_blank" class="footer-link d-none d-sm-inline-block">Support</a>
</div>
</div>
</div>
</footer>
<!-- / Footer -->

View File

@@ -0,0 +1,27 @@
@{
TempData.Keep();
string? currentPage = ViewContext.HttpContext.Request.Path;
ViewData["containerNav"] ??= "container-fluid";
}
<!-- Menu -->
<aside id="layout-menu" class="layout-menu-horizontal menu-horizontal menu flex-grow-0">
<div class='@ViewData["containerNav"] d-flex h-100'>
@* ! Starter Kit menu-items *@
<ul class="menu-inner py-1">
<li class='menu-item@(currentPage == "/" ? " active" : "")'>
<a asp-controller="Home" asp-action="Index" class="menu-link">
<i class="menu-icon icon-base ti tabler-smart-home"></i>
<div data-i18n="Home">Home</div>
</a>
</li>
<li class='menu-item@(currentPage == "/Page2" ? " active" : "")'>
<a asp-controller="Page2" asp-action="Index" class="menu-link">
<i class="menu-icon icon-base ti tabler-app-window"></i>
<div data-i18n="Page2">Page2</div>
</a>
</li>
</ul>
</div>
</aside>
<!-- / Menu -->

View File

@@ -0,0 +1,44 @@
@{
TempData.Keep();
string? currentPage = ViewContext.HttpContext.Request.Path;
}
<!-- Menu -->
@* ! Do this simple *@
<aside id="layout-menu" class="layout-menu menu-vertical menu">
@* ! Hide app brand if navbar-full *@
<div class='app-brand demo @((@ViewData["navbarFull"] != null && Convert.ToBoolean(@ViewData["navbarFull"])) ? "d-xl-none" : "")'>
<a asp-controller="Home" asp-action="Index" class="app-brand-link">
<span class="app-brand-logo demo">
@await Html.PartialAsync("../_Partials/_Macros")
</span>
<span class="app-brand-text demo menu-text fw-bold ms-3">@TempData.Peek("appName")</span>
</a>
<a href="javascript:void(0);" class="layout-menu-toggle menu-link text-large ms-auto">
<i class="icon-base ti menu-toggle-icon d-none d-xl-block"></i>
<i class="icon-base ti tabler-x d-block d-xl-none"></i>
</a>
</div>
<div class="menu-inner-shadow"></div>
@* ! Starter Kit menu-items *@
<ul class="menu-inner py-1">
<li class='menu-item@(currentPage == "/" ? " active" : "")'>
<a asp-controller="Home" asp-action="Index" class="menu-link">
<i class="menu-icon icon-base ti tabler-smart-home"></i>
<div data-i18n="Home">Home</div>
</a>
</li>
<li class='menu-item@(currentPage == "/Page2" ? " active" : "")'>
<a asp-controller="Page2" asp-action="Index" class="menu-link">
<i class="menu-icon icon-base ti tabler-app-window"></i>
<div data-i18n="Page 2">Page 2</div>
</a>
</li>
</ul>
</aside>
<!-- / Menu -->

View File

@@ -0,0 +1,23 @@
@{
TempData.Keep();
ViewData["navbarDetached"] = (ViewData["navbarDetached"] ??= null);
ViewData["containerNav"] = (ViewData["containerNav"] ??= "container-fluid");
}
@if (@ViewData["navbarDetached"] != null)
{
<nav
class='layout-navbar @((@ViewData["navbarDetached"] != null) ? @ViewData["navbarDetached"] : "") @((@ViewData["navbarDetached"] != null) ? @ViewData["containerNav"] : "") navbar navbar-expand-xl align-items-center bg-navbar-theme'
id="layout-navbar">
@await Html.PartialAsync("Sections/Navbar/_NavbarPartial")
</nav>
}
else
{
<nav
class='layout-navbar @((@ViewData["navbarDetached"] != null) ? @ViewData["navbarDetached"] : "") @((@ViewData["navbarDetached"] != null) ? @ViewData["containerNav"] : "") navbar navbar-expand-xl align-items-center'
id="layout-navbar">
<div class='@((@ViewData["navbarDetached"] == null) ? @ViewData["containerNav"] : "")'>
@await Html.PartialAsync("Sections/Navbar/_NavbarPartial")
</div>
</nav>
}

View File

@@ -0,0 +1,115 @@
@* ! Brand demo (display only for navbar-full and hide on below xl) *@
@if (ViewData["navbarFull"] != null)
{
<div class="navbar-brand app-brand demo d-none d-xl-flex py-0 me-4 ms-0">
<a asp-controller="Home" asp-action="Index" class="app-brand-link">
<span class="app-brand-logo demo">
@await Html.PartialAsync("../_Partials/_Macros")
</span>
<span class="app-brand-text demo menu-text fw-bold">@TempData.Peek("appName")</span>
</a>
@* ! Display menu close icon only for horizontal-menu with navbar-full *@
@if (Convert.ToBoolean(@TempData.Peek("menuHorizontal")).ToString() == "True")
{
<a href="javascript:void(0);" class="layout-menu-toggle menu-link text-large ms-auto d-xl-none">
<i class="icon-base ti tabler-x icon-sm d-flex align-items-center justify-content-center"></i>
</a>
}
</div>
}
@* ! Not required for layout-without-menu *@
@if (ViewData["navbarHideToggle"] == null)
{
<div class='layout-menu-toggle navbar-nav align-items-xl-center me-3 me-xl-0 @((Convert.ToBoolean(@TempData.Peek("menuHorizontal")).ToString() == "True") ? "d-xl-none" : "") @((@ViewData["contentNavbar"] != null && Convert.ToBoolean(@ViewData["contentNavbar"])) ? "" : "d-xl-none")'>
<a class="nav-item nav-link px-0 me-xl-6" href="javascript:void(0)">
<i class="icon-base ti tabler-menu-2 icon-md"></i>
</a>
</div>
}
<div class="navbar-nav-right d-flex align-items-center" id="navbar-collapse">
<!-- Style Switcher -->
<div class="navbar-nav align-items-center">
<div class="nav-item dropdown">
<a class="nav-link dropdown-toggle hide-arrow btn btn-icon btn-text-secondary rounded-pill" id="nav-theme" href="javascript:void(0);" data-bs-toggle="dropdown">
<i class="icon-base ti tabler-sun icon-22px theme-icon-active text-heading"></i>
<span class="d-none ms-2" id="nav-theme-text">Toggle theme</span>
</a>
<ul class="dropdown-menu dropdown-menu-start" aria-labelledby="nav-theme-text">
<li>
<button type="button" class="dropdown-item align-items-center active" data-bs-theme-value="light" aria-pressed="false">
<span><i class="icon-base ti tabler-sun icon-22px me-3" data-icon="sun"></i>Light</span>
</button>
</li>
<li>
<button type="button" class="dropdown-item align-items-center" data-bs-theme-value="dark" aria-pressed="true">
<span><i class="icon-base ti tabler-moon-stars icon-22px me-3" data-icon="moon-stars"></i>Dark</span>
</button>
</li>
<li>
<button type="button" class="dropdown-item align-items-center" data-bs-theme-value="system" aria-pressed="false">
<span><i class="icon-base ti tabler-device-desktop-analytics icon-22px me-3" data-icon="device-desktop-analytics"></i>System</span>
</button>
</li>
</ul>
</div>
</div>
<!-- / Style Switcher-->
<ul class="navbar-nav flex-row align-items-center ms-auto">
<!-- User -->
<li class="nav-item navbar-dropdown dropdown-user dropdown">
<a class="nav-link dropdown-toggle hide-arrow p-0" href="javascript:void(0);" data-bs-toggle="dropdown">
<div class="avatar avatar-online">
<img src="~/img/avatars/1.png" alt class="rounded-circle" />
</div>
</a>
<ul class="dropdown-menu dropdown-menu-end">
<li>
<a class="dropdown-item mt-0" href="javascript:void(0);">
<div class="d-flex align-items-center">
<div class="flex-shrink-0 me-2">
<div class="avatar avatar-online">
<img src="~/img/avatars/1.png" alt class="rounded-circle" />
</div>
</div>
<div class="flex-grow-1">
<h6 class="mb-0">John Doe</h6>
<small class="text-body-secondary">Admin</small>
</div>
</div>
</a>
</li>
<li>
<div class="dropdown-divider my-1 mx-n2"></div>
</li>
<li>
<a class="dropdown-item" href="javascript:void(0);"> <i class="icon-base ti tabler-user me-3 icon-md"></i><span class="align-middle">My Profile</span> </a>
</li>
<li>
<a class="dropdown-item" href="javascript:void(0);"> <i class="icon-base ti tabler-settings me-3 icon-md"></i><span class="align-middle">Settings</span> </a>
</li>
<li>
<a class="dropdown-item" href="javascript:void(0);">
<span class="d-flex align-items-center align-middle">
<i class="flex-shrink-0 icon-base ti tabler-file-dollar me-3 icon-md"></i><span class="flex-grow-1 align-middle">Billing</span>
<span class="flex-shrink-0 badge bg-danger d-flex align-items-center justify-content-center">4</span>
</span>
</a>
</li>
<li>
<div class="d-grid px-2 pt-2 pb-1">
<a class="btn btn-sm btn-danger d-flex" href="javascript:void(0);">
<small class="align-middle">Logout</small>
<i class="icon-base ti tabler-logout ms-2 icon-14px"></i>
</a>
</div>
</li>
</ul>
</li>
<!--/ User -->
</ul>
</div>

View File

@@ -0,0 +1,34 @@
<environment include="Development">
<script src="~/vendor/libs/jquery/jquery.js"></script>
<script src="~/vendor/libs/popper/popper.js"></script>
<script src="~/vendor/js/bootstrap.js"></script>
<!-- node-waves required for animation on button click -->
<script src="~/vendor/libs/node-waves/node-waves.js"></script>
<script src="~/vendor/libs/%40algolia/autocomplete-js.js"></script>
<script src="~/vendor/libs/pickr/pickr.js"></script>
<!-- `perfect-scrollbar` library required by SideNav plugin -->
<script src="~/vendor/libs/perfect-scrollbar/perfect-scrollbar.js"></script>
<!-- node-waves required for animation on button click -->
<script src="~/vendor/libs/node-waves/node-waves.js"></script>
<!-- `hammer` required for swipe guesture -->
<script src="~/vendor/libs/hammer/hammer.js"></script>
<!-- `i18n` required for translation -->
<script src="~/vendor/libs/i18n/i18n.js"></script>
<script src="~/vendor/js/menu.js"></script>
<script src="~/js/site.js"></script>
</environment>
<environment exclude="Development">
<script src="~/vendor/libs/jquery/jquery.js" asp-append-version="true"></script>
<script src="~/vendor/libs/popper/popper.js" asp-append-version="true"></script>
<script src="~/vendor/js/bootstrap.js" asp-append-version="true"></script>
<script src="~/vendor/libs/node-waves/node-waves.js" asp-append-version="true"></script>
<script src="~/vendor/libs/%40algolia/autocomplete-js.js" asp-append-version="true"></script>
<script src="~/vendor/libs/pickr/pickr.js" asp-append-version="true"></script>
<script src="~/vendor/libs/perfect-scrollbar/perfect-scrollbar.js" asp-append-version="true"></script>
<script src="~/vendor/libs/node-waves/node-waves.js"></script>
<script src="~/vendor/libs/hammer/hammer.js" asp-append-version="true"></script>
<script src="~/vendor/libs/i18n/i18n.js" asp-append-version="true"></script>
<script src="~/vendor/js/menu.js" asp-append-version="true"></script>
<script src="~/js/site.js" asp-append-version="true"></script>
</environment>

View File

@@ -0,0 +1,15 @@
<environment include="Development">
<script src="~/vendor/libs/popper/popper.js"></script>
<script src="~/vendor/js/bootstrap.js"></script>
<!-- node-waves required for animation on button click -->
<script src="~/vendor/libs/node-waves/node-waves.js"></script>
<script src="~/vendor/libs/pickr/pickr.js"></script>
<script src="~/js/site.js"></script>
</environment>
<environment exclude="Development">
<script src="~/vendor/libs/popper/popper.js" asp-append-version="true"></script>
<script src="~/vendor/js/bootstrap.js" asp-append-version="true"></script>
<script src="~/vendor/libs/node-waves/node-waves.js" asp-append-version="true"></script>
<script src="~/vendor/libs/pickr/pickr.js" asp-append-version="true"></script>
<script src="~/js/site.js" asp-append-version="true"></script>
</environment>

View File

@@ -0,0 +1,14 @@
<environment include="Development">
@* Template helper js *@
<script src="~/vendor/js/helpers.js"></script>
@* Template customizer js *@
<script src="~/vendor/js/template-customizer.js"></script>
@* Config file contain global vars & default theme options, Set your preferred theme option in this file. *@
<script src="~/js/config.js"></script>
</environment>
<environment exclude="Development">
<script src="~/vendor/js/helpers.js" asp-append-version="true"></script>
<script src="~/vendor/js/template-customizer.js" asp-append-version="true"></script>
<script src="~/js/config.js" asp-append-version="true"></script>
</environment>

View File

@@ -0,0 +1,20 @@
<environment include="Development">
@* Template helper js *@
<script src="~/vendor/js/helpers.js"></script>
@* Template customizer js *@
<script src="~/vendor/js/template-customizer.js"></script>
@* Config file contain global vars & default theme options, Set your preferred theme option in this file. *@
<script src='~/js/front-config.js'></script>
<script src="~/vendor/js/dropdown-hover.js"></script>
<script src="~/vendor/js/mega-dropdown.js"></script>
</environment>
<environment exclude="Development">
<script src="~/vendor/js/helpers.js" asp-append-version="true"></script>
<script src="~/vendor/js/template-customizer.js" asp-append-version="true"></script>
<script src='~/js/front-config.js' asp-append-version="true"></script>
<script src="~/vendor/js/dropdown-hover.js" asp-append-version="true"></script>
<script src="~/vendor/js/mega-dropdown.js" asp-append-version="true"></script>
</environment>

View File

@@ -0,0 +1,37 @@
<!-- Fonts -->
<link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
<link href="https://fonts.googleapis.com/css2?family=Public+Sans:ital,wght@0,300;0,400;0,500;0,600;0,700;1,300;1,400;1,500;1,600;1,700&ampdisplay=swap" rel="stylesheet" />
<environment include="Development">
<!-- Iconify icons -->
<link rel="stylesheet" href="~/vendor/fonts/iconify-icons.css" />
<link rel="stylesheet" href="~/vendor/libs/node-waves/node-waves.css" />
<link rel="stylesheet" href="~/vendor/libs/pickr/pickr-themes.css" />
<!-- Core CSS -->
<link rel="stylesheet" href="~/vendor/css/core.css" />
<link rel="stylesheet" href="~/css/demo.css" />
<!-- `perfect-scrollbar` library required by SideNav plugin -->
<link rel="stylesheet" href="~/vendor/libs/perfect-scrollbar/perfect-scrollbar.css" />
<!-- Application stylesheets -->
<link rel="stylesheet" href="~/css/site.css" />
</environment>
<environment exclude="Development">
<!-- Iconify icons -->
<link rel="stylesheet" href="~/vendor/fonts/iconify-icons.css" asp-append-version="true" />
<link rel="stylesheet" href="~/vendor/libs/node-waves/node-waves.css" asp-append-version="true" />
<link rel="stylesheet" href="~/vendor/libs/pickr/pickr-themes.css" asp-append-version="true" />
<!-- Core CSS -->
<link rel="stylesheet" href="~/vendor/css/core.css" asp-append-version="true" />
<link rel="stylesheet" href="~/css/demo.css" />
<!-- `perfect-scrollbar` library required by SideNav plugin -->
<link rel="stylesheet" href="~/vendor/libs/perfect-scrollbar/perfect-scrollbar.css" asp-append-version="true" />
<!-- Application stylesheets -->
<link rel="stylesheet" href="~/css/site.css" asp-append-version="true" />
</environment>

View File

@@ -0,0 +1,34 @@
<!-- Fonts -->
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Public+Sans:ital,wght@0,300;0,400;0,500;0,600;0,700;1,300;1,400;1,500;1,600;1,700&ampdisplay=swap" rel="stylesheet" />
<environment include="Development">
<!-- Iconify icons -->
<link rel="stylesheet" href="~/vendor/fonts/iconify-icons.css" />
<link rel="stylesheet" href="~/vendor/libs/node-waves/node-waves.css" />
<!-- Core CSS -->
<link rel="stylesheet" href="~/vendor/css/core.css" />
<link rel="stylesheet" href="~/css/demo.css" />
<link rel="stylesheet" href="~/vendor/libs/pickr/pickr-themes.css" />
<link rel="stylesheet" href="~/vendor/css/pages/front-page.css" />
<!-- Application stylesheets -->
<link rel="stylesheet" href="~/css/site.css" />
</environment>
<environment exclude="Development">
<!-- Iconify icons -->
<link rel="stylesheet" href="~/vendor/fonts/iconify-icons.css" asp-append-version="true" />
<link rel="stylesheet" href="~/vendor/libs/node-waves/node-waves.css" asp-append-version="true" />
<!-- Core CSS -->
<link rel="stylesheet" href="~/vendor/css/core.css" asp-append-version="true" />
<link rel="stylesheet" href="~/css/demo.css" asp-append-version="true" />
<link rel="stylesheet" href="~/vendor/libs/pickr/pickr-themes.css" asp-append-version="true" />
<link rel="stylesheet" href="~/vendor/css/pages/front-page.css" asp-append-version="true" />
<!-- Application stylesheets -->
<link rel="stylesheet" href="~/css/site.css" asp-append-version="true" />
</environment>

View File

@@ -0,0 +1,29 @@
@{
TempData["appName"] = "Vuexy";
TempData["creatorName"] = "Pixinvent";
TempData["appUrl"] = "https://pixinvent.com";
TempData["description"] = "Vuexy is the best bootstrap 5 dashboard for responsive web apps. Streamline your app development process with ease.";
TempData["main"] = "main";
TempData["keywords"] = "Vuexy bootstrap dashboard, vuexy bootstrap 5 dashboard, themeselection, html dashboard, web dashboard, frontend dashboard, responsive bootstrap theme";
TempData["ogTitle"] = "Vuexy Dashboard PRO by Pixinvent";
TempData["ogType"] = "website";
TempData["ogUrl"] = "https://themeforest.net/item/vuexy-vuejs-html-laravel-admin-dashboard-template/23328599";
TempData["ogImage"] = "https://ts-assets.b-cdn.net/pi-assets/vuexy/admin-template/banner/banner-main.png";
TempData["ogDescription"] = "Vuexy is the best bootstrap 5 dashboard for responsive web apps. Streamline your app development process with ease.";
TempData["canonical"] = "https://themeforest.net/item/vuexy-vuejs-html-laravel-admin-dashboard-template/23328599";
@* Footer & Misc urls *@
TempData["authorName"] = "Pixinvent";
TempData["authorUrl"] = "https://pixinvent.com";
TempData["licenseUrl"] = "https://pixinvent.ticksy.com/";
TempData["productPage"] = "https://themeforest.net/item/vuexy-vuejs-html-laravel-admin-dashboard-template/23328599";
TempData["livePreview"] = "https://demos.pixinvent.com/vuexy-html-admin-template/html/vertical-menu-template/";
TempData["support"] = "https://pixinvent.ticksy.com/";
TempData["documentation"] = "https://demos.pixinvent.com/vuexy-html-admin-template/documentation/";
TempData["documentation_menu_link"] = "https://demos.pixinvent.com/vuexy-html-admin-template/documentation/net-core-introduction.html";
TempData["moreThemes"] = "https://themeforest.net/user/pixinvent/portfolio";
TempData["twitterUrl"] = "https://x.com/pixinvents";
TempData["instagramUrl"] = "https://www.instagram.com/pixinvents/";
TempData["githubUrl"] = "https://github.com/pixinvent";
TempData["facebookUrl"] = "https://www.facebook.com/pixinvents/";
}

View File

@@ -0,0 +1,14 @@
@{
Layout = "_CommonMasterLayout";
ViewData["customizerHidden"] = (ViewData["customizerHidden"] ??= "customizer-hide");
}
@section VendorStyles { @RenderSection("VendorStyles", required: false) }
@section PageStyles { @RenderSection("PageStyles", required: false) }
@RenderBody()
@section VendorScripts { @RenderSection("VendorScripts", required: false) }
@section PageScripts { @RenderSection("PageScripts", required: false) }

View File

@@ -0,0 +1,69 @@
@{
@* using this variables to load front pages assets *@
bool isFront = ViewData["isFront"] is bool isFrontValue ? isFrontValue : false;
ViewData["main"] = isFront ? "front-" : "";
ViewData["frontVar"] = isFront ? "Front" : "";
@* Compact/Fluid class *@
ViewData["contentType"] = ViewData["container"] is string container && container == "container-xxl" ? "layout-compact" : "layout-wide";
}
@inject IHttpContextAccessor httpContextAccessor
<!DOCTYPE html>
<html lang="en" class="@(ViewData["navbarType"] is string navbarType ? navbarType : "")
@(ViewData["menuFixed"] is string menuFixed ? menuFixed : "")
@(ViewData["menuCollapsed"] is string menuCollapsed ? menuCollapsed : "")
@(ViewData["contentType"] is string contentType ? contentType : "")
@(ViewData["footerFixed"] is string footerFixed ? footerFixed : "")
@(ViewData["customizerHidden"] is string customizerHidden ? customizerHidden : "")" dir="ltr" data-skin="default" data-bs-theme="light" data-assets-path='@((httpContextAccessor.HttpContext?.Request.PathBase ?? "") + "/")' data-template='@(isFront ? "front-page" : (Convert.ToBoolean(TempData.Peek("menuHorizontal")?.ToString()) ? "horizontal-menu-template" : "vertical-menu-template"))'>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0" />
<meta name="robots" content="noindex, nofollow" />
@{
string title = ViewData["title"] as string ?? "";
string appName = TempData.Peek("appName") as string ?? "";
string productPage = TempData.Peek("productPage") as string ?? "";
}
<title>@title | @appName - Asp.Net Core MVC Admin Template</title>
<meta name="description" content="" />
<!-- Canonical SEO -->
<link rel="canonical" href='@productPage'>
<!-- Favicon -->
<link rel="icon" type="image/x-icon" href="~/img/favicon/favicon.ico" />
<!-- Core Styles -->
@await Html.PartialAsync("Sections/_Styles" + ViewData["frontVar"])
<!-- Vendor Styles -->
@RenderSection("VendorStyles", required: false)
<!-- Page Styles -->
@RenderSection("PageStyles", required: false)
<!-- Include Scripts for customizer, helper, analytics, config -->
@await Html.PartialAsync("Sections/_ScriptsIncludes" + ViewData["frontVar"])
</head>
<body>
<!-- Layout Content -->
@RenderBody()
<!--/ Layout Content -->
<!-- Core Scripts -->
@await Html.PartialAsync("Sections/_Scripts" + ViewData["frontVar"])
<!-- Vendor Scripts -->
@RenderSection("VendorScripts", required: false)
<script src='~/js/@ViewData["main"]main.js'></script>
<!-- Page Scripts-->
@RenderSection("PageScripts", required: false)
</body>
</html>

View File

@@ -0,0 +1,86 @@
@await Html.PartialAsync("Sections/_Variables")
@{
TempData.Keep();
Layout = "_CommonMasterLayout";
TempData["menuHorizontal"] = false;
ViewData["contentNavbar"] = false;
@* Display elements *@
ViewData["isNavbar"] = (ViewData["isNavbar"] ??= true);
ViewData["isMenu"] = (ViewData["isMenu"] ??= true);
ViewData["isFlex"] = (ViewData["isFlex"] ??= false);
ViewData["isFooter"] = (ViewData["isFooter"] ??= true);
@* ViewData["customizerHidden"] = (ViewData["customizerHidden"] ??= "customizer-hide"); *@
@*HTML Classes *@
ViewData["navbarDetached"] = (ViewData["navbarDetached"] ?? "navbar-detached");
ViewData["menuFixed"] = (ViewData["menuFixed"] ?? "layout-menu-fixed");
ViewData["navbarType"] = (ViewData["navbarType"] ?? "layout-navbar-fixed");
@*Content classes *@
ViewData["container"] = (ViewData["container"] ?? "container-xxl");
ViewData["containerNav"] = (ViewData["containerNav"] ?? "container-xxl");
}
@section VendorStyles{ @RenderSection("VendorStyles", required: false) }
@section PageStyles{ @RenderSection("PageStyles", required: false) }
@section VendorScripts{ @RenderSection("VendorScripts", required: false) }
@section PageScripts{ @RenderSection("PageScripts", required: false) }
@{
bool isMenu = ViewData["isMenu"] != null && Convert.ToBoolean(ViewData["isMenu"]);
}
<div class='layout-wrapper layout-content-navbar @(isMenu ? "" : "layout-without-menu")'>
<div class='layout-container'>
@if (isMenu)
{
@await Html.PartialAsync("Sections/Menu/_VerticalMenu")
}
<!-- Layout page -->
<div class="layout-page">
<!-- Navbar -->
@if (@ViewData["isNavbar"] != null && Convert.ToBoolean(@ViewData["isNavbar"]))
{
@await Html.PartialAsync("Sections/Navbar/_Navbar")
}
<!-- / Navbar -->
<!-- Content wrapper -->
<div class="content-wrapper">
<!-- Content -->
<div class='@ViewData["container"] @(Convert.ToBoolean(@ViewData["isFlex"]) ? "d-flex align-items-stretch flex-grow-1 p-0" : "flex-grow-1 container-p-y")'>
@RenderBody()
</div>
<!-- / Content -->
<!-- Footer -->
@if (@ViewData["isFooter"] != null && Convert.ToBoolean(@ViewData["isFooter"]))
{
@await Html.PartialAsync("Sections/Footer/_Footer")
}
<!-- / Footer -->
<div class="content-backdrop fade"></div>
</div>
<!--/ Content wrapper -->
</div>
<!-- / Layout page -->
</div>
<!-- Overlay -->
@if (@ViewData["isMenu"] != null && Convert.ToBoolean(@ViewData["isMenu"]))
{
<div class="layout-overlay layout-menu-toggle"></div>
}
<!-- Drag Target Area To SlideIn Menu On Small Screens -->
<div class="drag-target"></div>
</div>

View File

@@ -0,0 +1,24 @@
@{
Layout = "_CommonMasterLayout";
ViewData["navbarType"] = (ViewData["navbarType"] ?? "layout-navbar-fixed");
ViewData["isFront"] = (ViewData["isFront"] ??= true);
}
@section VendorStyles { @RenderSection("VendorStyles", required: false) }
@section PageStyles { @RenderSection("PageStyles", required: false) }
<!-- Navbar -->
@await Html.PartialAsync("Sections/Navbar/_NavbarFront")
<!-- / Navbar -->
@RenderBody()
<!-- Footer -->
@await Html.PartialAsync("Sections/Footer/_FooterFront")
<!-- / Footer -->
@section VendorScripts { @RenderSection("VendorScripts", required: false) }
@section PageScripts { @RenderSection("PageScripts", required: false) }

View File

@@ -0,0 +1,80 @@
@{
Layout = "_CommonMasterLayout";
TempData["menuHorizontal"] = true;
ViewData["navbarFull"] = true;
@* Display elements *@
ViewData["isNavbar"] = (ViewData["isNavbar"] ??= true);
ViewData["isMenu"] = (ViewData["isMenu"] ??= true);
ViewData["isFlex"] = (ViewData["isFlex"] ??= false);
ViewData["isFooter"] = (ViewData["isFooter"] ??= true);
@* HTML Classes *@
ViewData["menuFixed"] = (ViewData["menuFixed"] ?? "layout-menu-fixed");
@* ViewData["navbarFixed"] = (ViewData["navbarFixed"] ?? "layout-navbar-fixed");
ViewData["navbarType"] = (ViewData["navbarType"] ?? "layout-navbar-fixed");
ViewData["footerFixed"] = (ViewData["footerFixed"] ?? "layout-footer-fixed"); *@
@*Content classes *@
ViewData["container"] = (ViewData["container"] ?? "container-xxl");
ViewData["containerNav"] = (ViewData["containerNav"] ?? "container-xxl");
TempData.Keep();
}
@section VendorStyles{ @RenderSection("VendorStyles", required: false)}
@section PageStyles{ @RenderSection("PageStyles", required: false)}
@section VendorScripts{ @RenderSection("VendorScripts", required: false)}
@section PageScripts{ @RenderSection("PageScripts", required: false)}
<div class='layout-wrapper layout-navbar-full layout-horizontal layout-without-menu'>
<div class='layout-container'>
<!-- Navbar -->
@if (Convert.ToBoolean(@ViewData["isNavbar"]))
{
@await Html.PartialAsync("Sections/Navbar/_Navbar")
}
<!-- / Navbar -->
<!-- Layout page -->
<div class="layout-page">
<!-- Content wrapper -->
<div class="content-wrapper">
@if (Convert.ToBoolean(@ViewData["isMenu"]))
{
@await Html.PartialAsync("Sections/Menu/_HorizontalMenu")
}
<!-- Content -->
<div class='@ViewData["container"] @((Convert.ToBoolean(@ViewData["isFlex"])) ? "d-flex align-items-stretch flex-grow-1 p-0" : "flex-grow-1 container-p-y")'>
@RenderBody()
</div>
<!-- / Content -->
<!-- Footer -->
@if (Convert.ToBoolean(@ViewData["isFooter"]))
{
@await Html.PartialAsync("Sections/Footer/_Footer")
}
<!-- / Footer -->
<div class="content-backdrop fade"></div>
</div>
<!--/ Content wrapper -->
</div>
<!-- / Layout page -->
</div>
</div>
<!-- Overlay -->
@if (Convert.ToBoolean(@ViewData["isMenu"]))
{
<div class="layout-overlay layout-menu-toggle"></div>
}
<!-- Drag Target Area To SlideIn Menu On Small Screens -->
<div class="drag-target"></div>

View File

@@ -0,0 +1,82 @@
@{
Layout = "_CommonMasterLayout";
TempData["menuHorizontal"] = false;
ViewData["navbarFull"] = true;
@* Display elements *@
ViewData["isNavbar"] = (ViewData["isNavbar"] ??= true);
ViewData["isMenu"] = (ViewData["isMenu"] ??= true);
ViewData["isFlex"] = (ViewData["isFlex"] ??= false);
ViewData["isFooter"] = (ViewData["isFooter"] ??= true);
@*HTML Classes *@
ViewData["menuFixed"] = (ViewData["menuFixed"] ?? "layout-menu-fixed");
ViewData["navbarType"] = (ViewData["navbarType"] ?? "layout-navbar-fixed");
@* ViewData["footerFixed"] = (ViewData["footerFixed"] ?? "layout-footer-fixed");
ViewData["menuCollapsed"] = (ViewData["menuCollapsed"] ?? "layout-menu-collapsed");
ViewData["menuFlipped"] = (ViewData["menuFlipped"] ?? "layout-menu-flipped");
ViewData["menuOffcanvas"] = (ViewData["menuOffcanvas"] ?? "layout-menu-offcanvas"); *@
@*Content classes *@
ViewData["container"] = (ViewData["container"] ?? "container-fluid");
TempData.Keep();
}
@section VendorStyles{ @RenderSection("VendorStyles", required: false)}
@section PageStyles{ @RenderSection("PageStyles", required: false)}
@section VendorScripts{ @RenderSection("VendorScripts", required: false)}
@section PageScripts{ @RenderSection("PageScripts", required: false)}
<div class='layout-wrapper layout-navbar-full @((@ViewData["isMenu"] != null && Convert.ToBoolean(@ViewData["isMenu"])) ? "" : "layout-without-menu")'>
<div class='layout-container'>
<!-- Navbar -->
@if (Convert.ToBoolean(@ViewData["isNavbar"]))
{
@await Html.PartialAsync("Sections/Navbar/_Navbar")
}
<!-- / Navbar -->
<!-- Layout page -->
<div class="layout-page">
@if (Convert.ToBoolean(@ViewData["isMenu"]))
{
@await Html.PartialAsync("Sections/Menu/_VerticalMenu")
}
<!-- Content wrapper -->
<div class="content-wrapper">
<!-- Content -->
<div class='@ViewData["container"] @((Convert.ToBoolean(@ViewData["isFlex"])) ? "d-flex align-items-stretch flex-grow-1 p-0" : "flex-grow-1 container-p-y")'>
@RenderBody()
</div>
<!-- / Content -->
<!-- Footer -->
@if (Convert.ToBoolean(@ViewData["isFooter"]))
{
@await Html.PartialAsync("Sections/Footer/_Footer")
}
<!-- / Footer -->
</div>
<!--/ Content wrapper -->
<div class="content-backdrop fade"></div>
</div>
<!-- / Layout page -->
</div>
<!-- Overlay -->
@if (Convert.ToBoolean(@ViewData["isMenu"]))
{
<div class="layout-overlay layout-menu-toggle"></div>
}
<!-- Drag Target Area To SlideIn Menu On Small Screens -->
<div class="drag-target"></div>
</div>

View File

@@ -0,0 +1,2 @@
<script src="~/lib/jquery-validation/dist/jquery.validate.min.js"></script>
<script src="~/lib/jquery-validation-unobtrusive/jquery.validate.unobtrusive.min.js"></script>

View File

@@ -0,0 +1,12 @@
@{
var svgWidth = "32";
var svgHeight = "22";
}
<span class="text-primary">
<svg width="@svgWidth" height="@svgHeight" viewBox="0 0 32 22" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M0.00172773 0V6.85398C0.00172773 6.85398 -0.133178 9.01207 1.98092 10.8388L13.6912 21.9964L19.7809 21.9181L18.8042 9.88248L16.4951 7.17289L9.23799 0H0.00172773Z" fill="currentColor" />
<path opacity="0.06" fill-rule="evenodd" clip-rule="evenodd" d="M7.69824 16.4364L12.5199 3.23696L16.5541 7.25596L7.69824 16.4364Z" fill="#161616" />
<path opacity="0.06" fill-rule="evenodd" clip-rule="evenodd" d="M8.07751 15.9175L13.9419 4.63989L16.5849 7.28475L8.07751 15.9175Z" fill="#161616" />
<path fill-rule="evenodd" clip-rule="evenodd" d="M7.77295 16.3566L23.6563 0H32V6.88383C32 6.88383 31.8262 9.17836 30.6591 10.4057L19.7824 22H13.6938L7.77295 16.3566Z" fill="currentColor" />
</svg>
</span>

View File

@@ -0,0 +1,3 @@
@using AspnetCoreMvcStarter
@using AspnetCoreMvcStarter.Models
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers

View File

@@ -0,0 +1,8 @@
@{
// Availabel Layout option added for this template :
// _ContentNavbarLayout : Vertical Layout
// _BlankLayout : Blank Layout
// _HorizontalLayout : Horizontal Layout
// _NavbarFullLayout : Full Navbar Layout
Layout = "_ContentNavbarLayout";
}

View File

@@ -0,0 +1,8 @@
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
}
}

View File

@@ -0,0 +1,12 @@
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
},
"AllowedHosts": "*",
"ConnectionStrings": {
"AspnetCoreMvcStarterContext": "Data Source=AspnetCoreMvcStarterContext.db"
}
}

View File

@@ -0,0 +1,35 @@
module.exports = {
base: {
// Excludes folders relative to `root` directory.
exclude: ['node_modules', 'fonts']
},
development: {
// Build path can be both relative or absolute.
// Current dist path is `./assets/vendor` which will be used by templates from `html\` directory. Set distPath: './dist' to generate assets in dist folder.
distPath: './wwwroot',
// Minify assets.
minify: false,
// Generate sourcemaps.
sourcemaps: false,
// https://webpack.js.org/configuration/devtool/#development
devtool: 'eval-source-map'
},
production: {
// Build path can be both relative or absolute.
// Current dist path is `./assets/vendor` which will be used by templates from `html\` directory. Set distPath: './dist' to generate assets in dist folder.
distPath: './wwwroot',
// Minify assets.
// Note: Webpack will minify js sources in production mode regardless to this option
minify: true,
// Generate sourcemaps.
sourcemaps: false,
// https://webpack.js.org/configuration/devtool/#production
devtool: '#source-map'
}
};

View File

@@ -0,0 +1,26 @@
version: '3.9'
services:
web:
container_name: dotnet-mvc-starter-app # Name your container
build:
context: . # The directory that contains the Dockerfile
dockerfile: Dockerfile # Path to the Dockerfile
ports:
- '5050:80' # Map container port 80 to host port 5050
environment:
- ASPNETCORE_URLS=http://+:80 # Set the environment variable to configure the app's URLs
- DB_CONNECTION_STRING=${DB_CONNECTION_STRING} # Example of using environment variables from .env
volumes:
- ./data:/app/data # Persist app data
restart: always # Automatically restart the container on failure
depends_on:
- db # If your app depends on a database service (example)
db:
image: postgres:latest # Example of a database service
environment:
POSTGRES_USER: exampleuser
POSTGRES_PASSWORD: examplepassword
POSTGRES_DB: exampledb
volumes:
- ./db-data:/var/lib/postgresql/data # Persist database data

View File

@@ -0,0 +1,218 @@
{
"name": "Vuexy",
"version": "2.0.0",
"private": true,
"license": "Commercial",
"scripts": {
"build": "npx gulp build",
"build:js": "npx gulp build:js",
"build:css": "npx gulp build:css",
"build:fonts": "npx gulp build:fonts",
"build:prod": "npx gulp build --env=production",
"build:prod:js": "npx gulp build:js --env=production",
"build:prod:css": "npx gulp build:css --env=production",
"build:prod:fonts": "npx gulp build:fonts --env=production",
"watch": "npx gulp watch",
"serve": "npx gulp serve",
"format:scss": "npx stylelint --fix \"**/*.scss\""
},
"dependencies": {
"@algolia/autocomplete-js": "1.19.2",
"@algolia/autocomplete-theme-classic": "1.19.2",
"@form-validation/bundle": "2.4.0",
"@form-validation/core": "2.4.0",
"@form-validation/plugin-alias": "2.4.0",
"@form-validation/plugin-auto-focus": "2.4.0",
"@form-validation/plugin-bootstrap5": "2.4.0",
"@form-validation/plugin-excluded": "2.4.0",
"@form-validation/plugin-field-status": "2.4.0",
"@form-validation/plugin-framework": "2.4.0",
"@form-validation/plugin-message": "2.4.0",
"@fortawesome/fontawesome-free": "6.7.2",
"@fullcalendar/core": "6.1.18",
"@fullcalendar/daygrid": "6.1.18",
"@fullcalendar/interaction": "6.1.18",
"@fullcalendar/list": "6.1.18",
"@fullcalendar/timegrid": "6.1.18",
"@fullcalendar/timeline": "6.1.18",
"@iconify/json": "2.2.363",
"@iconify/tools": "4.1.2",
"@iconify/types": "2.0.0",
"@iconify/utils": "2.3.0",
"@popperjs/core": "2.11.8",
"@simonwep/pickr": "1.9.1",
"@yaireo/tagify": "4.32.2",
"animate.css": "4.1.1",
"aos": "2.3.4",
"apexcharts": "4.2.0",
"bloodhound-js": "1.2.3",
"bootstrap": "5.3.7",
"bootstrap-daterangepicker": "3.1.0",
"bootstrap-select": "1.14.0-beta3",
"bs-stepper": "1.7.0",
"chart.js": "4.4.9",
"cleave-zen": "0.0.17",
"clipboard": "2.0.11",
"datatables.net-bs5": "2.1.8",
"datatables.net-buttons": "3.2.4",
"datatables.net-buttons-bs5": "3.2.4",
"datatables.net-fixedcolumns-bs5": "5.0.4",
"datatables.net-fixedheader-bs5": "4.0.3",
"datatables.net-responsive": "3.0.5",
"datatables.net-responsive-bs5": "3.0.5",
"datatables.net-rowgroup-bs5": "1.5.2",
"datatables.net-select-bs5": "2.1.0",
"dropzone": "5.9.3",
"flag-icons": "7.5.0",
"flatpickr": "4.6.13",
"hammerjs": "2.0.8",
"highlight.js": "11.10.0",
"i18next": "24.1.2",
"i18next-browser-languagedetector": "8.0.5",
"i18next-http-backend": "3.0.2",
"jkanban": "1.3.1",
"jquery": "3.7.1",
"jquery-idletimer": "1.0.0",
"jquery.repeater": "1.2.1",
"jstree": "3.3.17",
"jszip": "3.10.1",
"katex": "0.16.22",
"leaflet": "1.9.4",
"mapbox-gl": "3.8.0",
"masonry-layout": "4.2.2",
"moment": "2.30.1",
"node-waves": "0.7.6",
"notiflix": "3.2.8",
"notyf": "3.10.0",
"nouislider": "15.8.1",
"numeral": "2.0.6",
"pdfmake": "0.2.20",
"perfect-scrollbar": "1.5.6",
"plyr": "3.7.8",
"quill": "2.0.3",
"raty-js": "4.3.0",
"select2": "4.0.13",
"shepherd.js": "14.3.0",
"sortablejs": "1.15.6",
"spinkit": "2.0.1",
"sweetalert2": "11.14.5",
"swiper": "11.1.15",
"timepicker": "1.14.1",
"typeahead.js": "0.11.1",
"jquery-validation-unobtrusive": "4.0.0"
},
"devDependencies": {
"@babel/core": "7.26.10",
"@babel/plugin-transform-destructuring": "7.23.3",
"@babel/plugin-transform-object-rest-spread": "7.23.4",
"@babel/plugin-transform-template-literals": "7.23.3",
"@babel/preset-env": "7.26.9",
"@stylistic/stylelint-config": "1.0.1",
"@stylistic/stylelint-plugin": "2.1.3",
"ajv": "8.17.1",
"ansi-colors": "4.1.3",
"babel-loader": "9.1.3",
"browser-sync": "3.0.4",
"color-support": "1.1.3",
"css-loader": "6.9.1",
"deepmerge": "4.3.1",
"del": "8.0.0",
"eslint": "9.16.0",
"eslint-config-airbnb-base": "15.0.0",
"eslint-config-prettier": "9.1.2",
"eslint-plugin-import": "2.32.0",
"eslint-plugin-prettier": "5.5.3",
"fancy-log": "2.0.0",
"gulp": "4.0.2",
"gulp-autoprefixer": "8.0.0",
"gulp-dart-sass": "1.1.0",
"gulp-environment": "1.5.2",
"gulp-exec": "5.0.0",
"gulp-if": "3.0.0",
"gulp-purgecss": "7.0.2",
"gulp-rename": "2.0.0",
"gulp-replace": "1.1.4",
"gulp-sourcemaps": "3.0.0",
"gulp-uglify": "3.0.2",
"gulp-useref": "5.0.0",
"html-loader": "4.2.0",
"js-beautify": "1.15.4",
"prettier": "3.6.2",
"sass": "1.76.0",
"sass-loader": "14.0.0",
"string-replace-webpack-plugin": "0.1.3",
"style-loader": "3.3.4",
"stylelint": "16.22.0",
"stylelint-config-idiomatic-order": "10.0.0",
"stylelint-config-standard-scss": "13.1.0",
"stylelint-use-logical-spec": "5.0.1",
"terser-webpack-plugin": "5.3.14",
"webpack": "5.89.0",
"yarn": "1.22.22",
"@babel/plugin-proposal-object-rest-spread": "7.20.7"
},
"overrides": {
"algoliasearch": "5.17.1",
"@algolia/client-search": "5.17.1",
"@algolia/autocomplete-plugin-algolia-insights": "1.18.1",
"prop-types": "15.8.1",
"datatables.net": "2.1.8",
"datatables.net-bs5": "2.1.8",
"datatables.net-buttons": "3.2.4",
"datatables.net-buttons-bs5": "3.2.4",
"datatables.net-fixedcolumns": "5.0.4",
"datatables.net-fixedheader": "4.0.3",
"datatables.net-responsive": "3.0.5",
"datatables.net-rowgroup": "1.5.2",
"datatables.net-select": "2.1.0",
"postcss": "8.5.6",
"search-insights": "2.17.3",
"superagent": "3.8.3",
"chokidar": "3.6.0",
"source-map-resolve": "0.6.0",
"sass": "1.76.0",
"rimraf": "4.0.0"
},
"resolutions": {
"algoliasearch": "5.17.1",
"@algolia/client-search": "5.17.1",
"@algolia/autocomplete-plugin-algolia-insights": "1.18.1",
"prop-types": "15.8.1",
"datatables.net": "2.1.8",
"datatables.net-bs5": "2.1.8",
"datatables.net-buttons": "3.2.4",
"datatables.net-buttons-bs5": "3.2.4",
"datatables.net-fixedcolumns": "5.0.4",
"datatables.net-fixedheader": "4.0.3",
"datatables.net-responsive": "3.0.5",
"datatables.net-rowgroup": "1.5.2",
"datatables.net-select": "2.1.0",
"postcss": "8.5.6",
"search-insights": "2.17.3",
"superagent": "3.8.3",
"chokidar": "3.6.0",
"source-map-resolve": "0.6.0",
"sass": "1.76.0",
"rimraf": "4.0.0",
"eslint": "9.16.0",
"react": "19.1.0",
"react-dom": "19.1.0"
},
"gulp-environment": {
"environments": [
{
"name": "development",
"aliases": [
"dev"
]
},
{
"name": "production",
"aliases": [
"prod"
]
}
],
"default": "development"
}
}

View File

@@ -0,0 +1,7 @@
$flag-icons-path: "../fonts/flags";
@import "../../node_modules/flag-icons/sass/flag-icons";
.fi {
vertical-align: middle;
}

View File

@@ -0,0 +1,7 @@
$fa-font-path: "fontawesome";
$fa-font-size-base: 16px;
@import "../../node_modules/@fortawesome/fontawesome-free/scss/fontawesome";
@import "../../node_modules/@fortawesome/fontawesome-free/scss/regular";
@import "../../node_modules/@fortawesome/fontawesome-free/scss/solid";
@import "../../node_modules/@fortawesome/fontawesome-free/scss/brands";

View File

@@ -0,0 +1,151 @@
const fs = require('fs').promises;
const path = require('path');
const deepmerge = require('deepmerge');
const env = require('gulp-environment');
const { importDirectory, cleanupSVG, parseColors, isEmptyColor, runSVGO } = require('@iconify/tools');
const { getIcons, stringToIcon, getIconsCSS } = require('@iconify/utils');
// Set environment variable
process.env.NODE_ENV = env.current.name;
let serverPath;
let templatePath;
let buildPath;
// Load configuration
const conf = (() => {
const _conf = require('../../../build-config');
serverPath = _conf.base.serverPath;
templatePath = _conf.base.buildTemplatePath;
buildPath = _conf.base.buildPath;
return deepmerge.all([{}, _conf.base || {}, _conf[process.env.NODE_ENV] || {}]);
})();
// Icon sources
const sources = {
json: [require.resolve('@iconify/json/json/tabler.json')]
};
// CSS target path for generated icons
const cssTarget = path.resolve(__dirname, '../iconify-icons.css');
// Main function to generate CSS
(async function () {
try {
const allIcons = [];
// Process JSON sources
if (sources.json) {
for (let i = 0; i < sources.json.length; i++) {
const item = sources.json[i];
const filename = typeof item === 'string' ? item : item.filename;
const content = JSON.parse(await fs.readFile(filename, 'utf8'));
// Filter icons if specific icons are provided
if (typeof item !== 'string' && item.icons?.length) {
const filteredContent = getIcons(content, item.icons);
if (!filteredContent) {
throw new Error(`Cannot find required icons in ${filename}`);
}
allIcons.push(filteredContent);
} else {
allIcons.push(content);
}
}
}
// Process SVG sources if provided
if (sources.svg) {
for (let i = 0; i < sources.svg.length; i++) {
const source = sources.svg[i];
const iconSet = await importDirectory(source.dir, {
prefix: source.prefix
});
// Iterate over icons and process each SVG
await iconSet.forEach(async (name, type) => {
if (type !== 'icon') {
return;
}
const svg = iconSet.toSVG(name);
if (!svg) {
iconSet.remove(name);
return;
}
try {
// Clean up and optimize SVG
await cleanupSVG(svg);
if (source.monotone) {
await parseColors(svg, {
defaultColor: 'currentColor',
callback: (attr, colorStr, color) => {
return !color || isEmptyColor(color) ? colorStr : 'currentColor';
}
});
}
await runSVGO(svg);
} catch (err) {
console.error(`Error parsing ${name} from ${source.dir}:`, err);
iconSet.remove(name);
return;
}
iconSet.fromSVG(name, svg);
allIcons.push(iconSet.export());
});
}
}
// Generate the CSS content from all collected icons
const cssContent = allIcons
.map(iconSet =>
getIconsCSS(iconSet, Object.keys(iconSet.icons), {
iconSelector: '.{prefix}-{name}',
commonSelector: '.ti',
format: conf.minify ? 'compressed' : 'expanded'
})
)
.join('\n');
// Write the generated CSS to the target file
await fs.writeFile(cssTarget, cssContent, 'utf8');
console.log(`Saved CSS to ${cssTarget}`);
} catch (err) {
console.error('Error during icon CSS generation:', err);
}
})();
/**
* Organizes a list of icons by prefix.
* @param {Array} icons - Array of icon names
* @returns {Object} - Sorted icons grouped by prefix
*/
function organizeIconsList(icons) {
const sorted = {};
icons.forEach(icon => {
const item = stringToIcon(icon);
if (!item) {
return;
}
const prefix = item.prefix;
const prefixList = sorted[prefix] ? sorted[prefix] : (sorted[prefix] = []);
const name = item.name;
if (prefixList.indexOf(name) === -1) {
prefixList.push(name);
}
});
return sorted;
}

View File

@@ -0,0 +1,101 @@
<div id="template-customizer" class="card rounded-0">
<a href="javascript:void(0)" class="template-customizer-open-btn" tabindex="-1"></a>
<div class="p-6 m-0 lh-1 border-bottom template-customizer-header position-relative py-4">
<h6 class="template-customizer-t-panel_header mb-1"></h6>
<p class="template-customizer-t-panel_sub_header mb-0 small"></p>
<div class="d-flex align-items-center gap-2 position-absolute end-0 top-0 mt-6 me-5">
<a
href="javascript:void(0)"
class="template-customizer-reset-btn text-heading"
data-bs-toggle="tooltip"
data-bs-placement="bottom"
title="Reset Customizer"
><i class="icon-base ti tabler-refresh icon-lg"></i
><span class="badge rounded-pill bg-danger badge-dot badge-notifications d-none"></span
></a>
<a href="javascript:void(0)" class="template-customizer-close-btn fw-light text-heading" tabindex="-1">
<i class="icon-base ti tabler-x icon-lg"></i>
</a>
</div>
</div>
<div class="template-customizer-inner pt-6">
<!-- Theming -->
<div class="template-customizer-theming">
<h5 class="m-0 px-6 pb-6">
<span class="template-customizer-t-theming_header bg-label-primary rounded-1 py-1 px-3 small"></span>
</h5>
<!-- Color -->
<div class="m-0 px-6 pb-6 template-customizer-color w-100">
<label for="customizerColor" class="form-label d-block template-customizer-t-color_label mb-2"></label>
<div class="row template-customizer-colors-options"></div>
</div>
<!-- Theme -->
<div class="m-0 px-6 pb-6 template-customizer-theme w-100">
<label for="customizerTheme" class="form-label d-block template-customizer-t-theme_label mb-2"></label>
<div class="row px-1 template-customizer-themes-options"></div>
</div>
<!-- Skins -->
<div class="m-0 px-6 pb-6 template-customizer-skins w-100">
<label for="customizerSkin" class="form-label template-customizer-t-skin_label mb-2"></label>
<div class="row px-1 template-customizer-skins-options"></div>
</div>
<!-- Semi Dark -->
<div class="m-0 px-6 template-customizer-semiDark w-100 d-flex justify-content-between pe-12">
<span class="form-label template-customizer-t-semiDark_label"></span>
<label class="switch template-customizer-t-semiDark_label">
<input type="checkbox" class="template-customizer-semi-dark-switch switch-input" />
<span class="switch-toggle-slider">
<span class="switch-on"></span>
<span class="switch-off"></span>
</span>
</label>
</div>
<hr class="m-0 px-6 my-6" />
</div>
<!--/ Theming -->
<!-- Layout -->
<div class="template-customizer-layout">
<h5 class="m-0 px-6 pb-6">
<span class="template-customizer-t-layout_header bg-label-primary rounded-2 py-1 px-3 small"></span>
</h5>
<!-- Layout(Menu) -->
<div class="m-0 px-6 pb-6 d-block template-customizer-layouts">
<label for="customizerStyle" class="form-label d-block template-customizer-t-layout_label mb-2"></label>
<div class="row px-1 template-customizer-layouts-options"></div>
</div>
<!-- Header Options for Horizontal -->
<div class="m-0 px-6 pb-6 template-customizer-headerOptions w-100">
<label for="customizerHeader" class="form-label template-customizer-t-layout_header_label mb-2"></label>
<div class="row px-1 template-customizer-header-options"></div>
</div>
<!-- Fixed navbar -->
<div class="m-0 px-6 pb-6 template-customizer-layoutNavbarOptions w-100">
<label for="customizerNavbar" class="form-label template-customizer-t-layout_navbar_label mb-2"></label>
<div class="row px-1 template-customizer-navbar-options"></div>
</div>
<!-- Content -->
<div class="m-0 px-6 pb-6 template-customizer-content w-100">
<label for="customizerContent" class="form-label template-customizer-t-content_label mb-2"></label>
<div class="row px-1 template-customizer-content-options"></div>
</div>
<!-- Directions -->
<div class="m-0 px-6 pb-6 template-customizer-directions w-100">
<label for="customizerDirection" class="form-label template-customizer-t-direction_label mb-2"></label>
<div class="row px-1 template-customizer-directions-options"></div>
</div>
</div>
<!--/ Layout -->
</div>
</div>

View File

@@ -0,0 +1,219 @@
/*
* Template Customizer Style
**/
$customizer-width: 400px;
$customizer-hide-width: 1200px;
$customizer-spacer: 20px;
$customizer-font-size: inherit;
$open-btn-size: 38px;
$open-btn-spacer: 0;
$open-btn-font-size: 18px;
$open-btn-top: 180px;
$open-btn-color: #fff;
$open-btn-border-radius: .375rem;
#template-customizer {
position: fixed;
z-index: 99999999;
display: flex;
flex-direction: column;
block-size: 100%;
-webkit-box-direction: normal;
-webkit-box-orient: vertical;
box-shadow: 0 .3125rem 1.375rem 0 rgba(34, 48, 62, .18);
font-family: "Public Sans", -apple-system, blinkmacsystemfont, "Segoe UI", Oxygen, Ubuntu, Cantarell, "Fira Sans", "Droid Sans", "Helvetica Neue", sans-serif;
font-size: $customizer-font-size;
inline-size: $customizer-width;
inset-block-start: 0;
inset-inline-end: 0;
transform: translateX($customizer-width + $customizer-spacer);
transition: transform .2s ease-in;
[data-bs-theme="dark"] & {
box-shadow: 0 .3125rem 1.375rem 0 rgba(20, 20, 29, .26);
}
h5 {
position: relative;
font-size: 11px;
}
.form-label {
font-size: .9375rem;
font-weight: 500;
}
/* Color option styles */
.template-customizer-colors-options{
display: flex;
flex-direction: row;
justify-content: space-around;
margin: 0;
gap: .3rem;
.custom-option{
inline-size: 50px;
.custom-option-content{
padding: 0;
min-block-size: 46px;
.pcr-button{
padding: .625rem;
block-size: 30px;
inline-size: 30px;
&::before,
&::after{
border-radius: .5rem;
}
&:focus{
box-shadow: none;
}
}
}
}
.custom-option-body{
border-radius: .5rem;
block-size: 30px;
inline-size: 30px;
}
}
/* Font Icons sizing and alignments */
.custom-option-icon{
padding: 0;
.custom-option-content {
display: flex;
align-items: center;
justify-content: center;
min-block-size: 50px;
}
}
/* border-color for hr */
hr{
border-color: var(--bs-border-color);
}
/* To update svg image's color */
.custom-option{
border-width: 2px;
margin: 0;
&.custom-option-image .custom-option-content .custom-option-body svg {
inline-size: 100%;
}
}
&.template-customizer-open {
transform: none;
transition-delay: .1s;
.template-customizer-theme .custom-option.checked{
background-color: rgba(var(--bs-primary-rgb), .08);
*,
*::before,
*::after{
color: var(--bs-primary);
}
}
.custom-option.checked {
border-width: 2px;
color: var(--bs-primary);
.custom-option-content {
border: none;
}
}
}
.template-customizer-header {
a:hover {
&,
.icon-base {
color: inherit !important;
}
}
}
/* Customizer button */
.template-customizer-open-btn {
position: absolute;
z-index: -1;
display: block;
background: var(--bs-primary);
block-size: $open-btn-size;
border-end-start-radius: $open-btn-border-radius;
border-start-start-radius: $open-btn-border-radius;
box-shadow: 0 .125rem .25rem 0 rgba(var(--bs-primary-rgb), .4);
color: $open-btn-color;
font-size: $open-btn-font-size;
inline-size: $open-btn-size;
inset-block-start: $open-btn-top;
inset-inline-start: 0;
line-height: $open-btn-size;
opacity: 1;
text-align: center;
transform: translateX(-($open-btn-size + $customizer-spacer + $open-btn-spacer));
transition: all .1s linear .2s;
&::before {
position: absolute;
display: block;
background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAYAAABXAvmHAAAAAXNSR0IArs4c6QAABClJREFUaEPtmY1RFEEQhbsjUCIQIhAiUCNQIxAiECIQIxAiECIAIpAMhAiECIQI2vquZqnZvp6fhb3SK5mqq6Ju92b69bzXf6is+dI1t1+eAfztG5z1BsxsU0S+ici2iPB3vm5E5EpEDlSVv2dZswFIxv8UkZcNy+5EZGcuEHMCOBeR951uvVDVD53vVl+bE8DvDu8Pxtyo6ta/BsByg1R15Bwzqz5/LJgn34CZwfnPInI4BUB6/1hV0cSjVxcAM4PbcBZjL0XklIPN7Is3fLCkdQPpPYw/VNXj5IhPIvJWRIhSl6p60ULWBGBm30Vk123EwRxCuIzWkkjNrCZywith10ewE1Xdq4GoAjCz/RTXW44Ynt+LyBEfT43kYfbj86J3w5Q32DNcRQDpwF+dkQXDMey8xem0L3TEqB4g3PZWad8agBMRgZPeu96D1/C2Zbh3X0p80Op1xxloztN48bMQQNoc7+eLEuAoPSPiIDY4Ooo+E6ixeNXM+D3GERz2U3CIqMstLJUgJQDe+7eq6mub0NYEkLAKwEHkiBQDCZtddZCZ8d6r7JDwFkoARklHRPZUFVDVZWbwGuNrC4EfdOzFrRABh3Wnqhv+d70AEBLGFROPmeHlnM81G69UdSd6IUuM0GgUVn1uqWmg5EmMfBeEyB7Pe3txBkY+rGT8j0J+WXq/BgDkUCaqLgEAnwcRog0veMIqFAAwCy2wnw+bI2GaGboBgF9k5N0o0rUSGUb4eO0BeO9j/GYhkSHMHMTIqwGARX6p6a+nlPBl8kZuXMD9j6pKfF9aZuaFOdJCEL5D4eYb9wCYVCanrBmGyii/tIq+SLj/HQBCaM5bLzwfPqdQ6FpVHyra4IbuVbXaY7dETC2ESPNNWiIOi69CcdgSMXsh4tNSUiklMgwmC0aNd08Y5WAES6HHehM4gu97wyhBgWpgqXsrASglprDy7CwhehMZOSbK6JMSma+Fio1KltCmlBIj7gfZOGx8ppQSXrhzFnOhJ/31BDkjFHRvOd09x0mRBA9SFgxUgHpQg0q0t5ymPMlL+EnldFTfDA0NAmf+OTQ0X0sRouf7NNkYGhrOYNrxtIaGg83MNzVDSe3LXLhP7O/yrCsCz1zlWTpjWkuZAOBpX3yVnLqI1yLCOKU6qMrmP7SSrUEw54XF4WBIK5FxCMOr3lVsfGqNSmPzBXUnJTIX1jyVBq9wO6UObOpgC5GjO98vFKnTdQMZXxEsWZlDiCZMIxAbNxQOqlpVZtobejBaZNoBnRDzMFpkxvTQOD36BlrcySZuI6p1ACB6LU3wWuf5581+oHfD1vi89bz3nFUC8Nm7ZlP3nKkFbM4bWPt/MSFwklprYItwt6cmvpWJ2IVcQBCz6bLysSCv3SaANCiTsnaNRrNRqMXVVT1/BrAqz/buu/Y38Ad3KC5PARej0QAAAABJRU5ErkJggg==");
background-size: 100% 100%;
block-size: 22px;
content: "";
inline-size: 22px;
inset-block-start: 50%;
inset-inline-start: 50%;
transform: translate(-50%, -50%);
:dir(rtl) & {
margin-inline-start: 2px;
transform: translate(50%, -50%);
}
}
/* Customizer Hidden */
.customizer-hide & {
display: none;
}
:dir(rtl) & {
transform: translateX($open-btn-size + $customizer-spacer + $open-btn-spacer);
}
}
&.template-customizer-open .template-customizer-open-btn {
opacity: 0;
transform: none;
transition-delay: 0s;
}
/* Customizer inner */
.template-customizer-inner {
position: relative;
overflow: auto;
flex: 0 1 auto;
-webkit-box-flex: 0;
opacity: 1;
transition: opacity .2s;
}
}
@media (max-width: $customizer-hide-width) {
#template-customizer {
display: none;
visibility: hidden;
}
}
.layout-menu-100vh #template-customizer {
block-size: 100dvh;
}
/* RTL */
:dir(rtl) {
#template-customizer:not(.template-customizer-open){
transform: translateX(-($customizer-width + $customizer-spacer));
}
}

View File

@@ -0,0 +1,7 @@
import * as bootstrap from 'bootstrap'
try {
window.bootstrap = bootstrap
} catch (e) {}
export { bootstrap }

View File

@@ -0,0 +1,73 @@
// Add onHover event for dropdowns
;(function ($) {
if (!$ || !$.fn) return
const SELECTOR = '[data-bs-toggle=dropdown][data-trigger=hover]'
const TIMEOUT = 150
function openDropdown($i) {
let t = $i.data('dd-timeout')
if (t) {
clearTimeout(t)
t = null
$i.data('dd-timeout', t)
}
if ($i.attr('aria-expanded') !== 'true') $i.dropdown('toggle')
}
function closeDropdown($i) {
let t = $i.data('dd-timeout')
if (t) clearTimeout(t)
t = setTimeout(() => {
let t2 = $i.data('dd-timeout')
if (t2) {
clearTimeout(t2)
t2 = null
$i.data('dd-timeout', t2)
}
if ($i.attr('aria-expanded') === 'true') $i.dropdown('toggle')
}, TIMEOUT)
$i.data('dd-timeout', t)
}
$(function () {
$('body')
.on('mouseenter', `${SELECTOR}, ${SELECTOR} ~ .dropdown-menu`, function () {
const $toggle = $(this).hasClass('dropdown-toggle') ? $(this) : $(this).prev('.dropdown-toggle')
const $dropdown = $(this).hasClass('dropdown-menu') ? $(this) : $(this).next('.dropdown-menu')
if (window.getComputedStyle($dropdown[0], null).getPropertyValue('position') === 'static') return
// Set hovered flag
if ($(this).is(SELECTOR)) {
$(this).data('hovered', true)
}
openDropdown($(this).hasClass('dropdown-toggle') ? $(this) : $(this).prev('.dropdown-toggle'))
})
.on('mouseleave', `${SELECTOR}, ${SELECTOR} ~ .dropdown-menu`, function () {
const $toggle = $(this).hasClass('dropdown-toggle') ? $(this) : $(this).prev('.dropdown-toggle')
const $dropdown = $(this).hasClass('dropdown-menu') ? $(this) : $(this).next('.dropdown-menu')
if (window.getComputedStyle($dropdown[0], null).getPropertyValue('position') === 'static') return
// Remove hovered flag
if ($(this).is(SELECTOR)) {
$(this).data('hovered', false)
}
closeDropdown($(this).hasClass('dropdown-toggle') ? $(this) : $(this).prev('.dropdown-toggle'))
})
.on('hide.bs.dropdown', function (e) {
if ($(this).find(SELECTOR).data('hovered')) e.preventDefault()
})
})
})(window.jQuery)

View File

@@ -0,0 +1,206 @@
const TIMEOUT = 150
class MegaDropdown {
constructor(element, options = {}) {
this._onHover = options.trigger === 'hover' || element.getAttribute('data-trigger') === 'hover'
this._container = MegaDropdown._findParent(element, 'mega-dropdown')
if (!this._container) return
this._menu = this._container.querySelector('.dropdown-toggle ~ .dropdown-menu')
if (!this._menu) return
element.setAttribute('aria-expanded', 'false')
this._el = element
this._bindEvents()
}
open() {
if (this._timeout) {
clearTimeout(this._timeout)
this._timeout = null
}
if (this._focusTimeout) {
clearTimeout(this._focusTimeout)
this._focusTimeout = null
}
if (this._el.getAttribute('aria-expanded') !== 'true') {
this._triggerEvent('show')
this._container.classList.add('show')
this._menu.classList.add('show')
this._el.setAttribute('aria-expanded', 'true')
this._el.focus()
this._triggerEvent('shown')
}
}
close(force) {
if (this._timeout) {
clearTimeout(this._timeout)
this._timeout = null
}
if (this._focusTimeout) {
clearTimeout(this._focusTimeout)
this._focusTimeout = null
}
if (this._onHover && !force) {
this._timeout = setTimeout(() => {
if (this._timeout) {
clearTimeout(this._timeout)
this._timeout = null
}
this._close()
}, TIMEOUT)
} else {
this._close()
}
}
toggle() {
// eslint-disable-next-line no-unused-expressions
this._el.getAttribute('aria-expanded') === 'true' ? this.close(true) : this.open()
}
destroy() {
this._unbindEvents()
this._el = null
if (this._timeout) {
clearTimeout(this._timeout)
this._timeout = null
}
if (this._focusTimeout) {
clearTimeout(this._focusTimeout)
this._focusTimeout = null
}
}
_close() {
if (this._el.getAttribute('aria-expanded') === 'true') {
this._triggerEvent('hide')
this._container.classList.remove('show')
this._menu.classList.remove('show')
this._el.setAttribute('aria-expanded', 'false')
this._triggerEvent('hidden')
}
}
_bindEvents() {
this._elClickEvnt = e => {
e.preventDefault()
this.toggle()
}
this._el.addEventListener('click', this._elClickEvnt)
this._bodyClickEvnt = e => {
if (!this._container.contains(e.target) && this._container.classList.contains('show')) {
this.close(true)
}
}
document.body.addEventListener('click', this._bodyClickEvnt, true)
this._menuClickEvnt = e => {
if (e.target.classList.contains('mega-dropdown-link')) {
this.close(true)
}
}
this._menu.addEventListener('click', this._menuClickEvnt, true)
this._focusoutEvnt = () => {
if (this._focusTimeout) {
clearTimeout(this._focusTimeout)
this._focusTimeout = null
}
if (this._el.getAttribute('aria-expanded') !== 'true') return
this._focusTimeout = setTimeout(() => {
if (
document.activeElement.tagName.toUpperCase() !== 'BODY' &&
MegaDropdown._findParent(document.activeElement, 'mega-dropdown') !== this._container
) {
this.close(true)
}
}, 100)
}
this._container.addEventListener('focusout', this._focusoutEvnt, true)
if (this._onHover) {
this._enterEvnt = () => {
if (window.getComputedStyle(this._menu, null).getPropertyValue('position') === 'static') return
this.open()
}
this._leaveEvnt = () => {
if (window.getComputedStyle(this._menu, null).getPropertyValue('position') === 'static') return
this.close()
}
this._el.addEventListener('mouseenter', this._enterEvnt)
this._menu.addEventListener('mouseenter', this._enterEvnt)
this._el.addEventListener('mouseleave', this._leaveEvnt)
this._menu.addEventListener('mouseleave', this._leaveEvnt)
}
}
_unbindEvents() {
if (this._elClickEvnt) {
this._el.removeEventListener('click', this._elClickEvnt)
this._elClickEvnt = null
}
if (this._bodyClickEvnt) {
document.body.removeEventListener('click', this._bodyClickEvnt, true)
this._bodyClickEvnt = null
}
if (this._menuClickEvnt) {
this._menu.removeEventListener('click', this._menuClickEvnt, true)
this._menuClickEvnt = null
}
if (this._focusoutEvnt) {
this._container.removeEventListener('focusout', this._focusoutEvnt, true)
this._focusoutEvnt = null
}
if (this._enterEvnt) {
this._el.removeEventListener('mouseenter', this._enterEvnt)
this._menu.removeEventListener('mouseenter', this._enterEvnt)
this._enterEvnt = null
}
if (this._leaveEvnt) {
this._el.removeEventListener('mouseleave', this._leaveEvnt)
this._menu.removeEventListener('mouseleave', this._leaveEvnt)
this._leaveEvnt = null
}
}
static _findParent(el, cls) {
if (el.tagName.toUpperCase() === 'BODY') return null
el = el.parentNode
while (el.tagName.toUpperCase() !== 'BODY' && !el.classList.contains(cls)) {
el = el.parentNode
}
return el.tagName.toUpperCase() !== 'BODY' ? el : null
}
_triggerEvent(event) {
if (document.createEvent) {
let customEvent
if (typeof Event === 'function') {
customEvent = new Event(event)
} else {
customEvent = document.createEvent('Event')
customEvent.initEvent(event, false, true)
}
this._container.dispatchEvent(customEvent)
} else {
this._container.fireEvent(`on${event}`, document.createEventObject())
}
}
}
window.MegaDropdown = MegaDropdown
export { MegaDropdown }

View File

@@ -0,0 +1,975 @@
const TRANSITION_EVENTS = ['transitionend', 'webkitTransitionEnd', 'oTransitionEnd']
const DELTA = 5
class Menu {
constructor(el, config = {}, _PS = null) {
this._el = el
this._horizontal = config.orientation === 'horizontal'
this._animate = config.animate !== false
this._accordion = config.accordion !== false
this._showDropdownOnHover = Boolean(config.showDropdownOnHover)
this._closeChildren = Boolean(config.closeChildren)
this._rtl = document.documentElement.getAttribute('dir') === 'rtl' || document.body.getAttribute('dir') === 'rtl'
this._onOpen = config.onOpen || (() => {})
this._onOpened = config.onOpened || (() => {})
this._onClose = config.onClose || (() => {})
this._onClosed = config.onClosed || (() => {})
this._psScroll = null
this._topParent = null
this._menuBgClass = null
el.classList.add('menu')
el.classList[this._animate ? 'remove' : 'add']('menu-no-animation')
if (!this._horizontal) {
el.classList.add('menu-vertical')
el.classList.remove('menu-horizontal')
const PerfectScrollbarLib = _PS || window.PerfectScrollbar
if (PerfectScrollbarLib) {
this._scrollbar = new PerfectScrollbarLib(el.querySelector('.menu-inner'), {
suppressScrollX: true,
wheelPropagation: !Menu._hasClass('layout-menu-fixed layout-menu-fixed-offcanvas')
})
window.Helpers.menuPsScroll = this._scrollbar
} else {
el.querySelector('.menu-inner').classList.add('overflow-auto')
}
} else {
el.classList.add('menu-horizontal')
el.classList.remove('menu-vertical')
this._inner = el.querySelector('.menu-inner')
const container = this._inner.parentNode
this._prevBtn = el.querySelector('.menu-horizontal-prev')
if (!this._prevBtn) {
this._prevBtn = document.createElement('a')
this._prevBtn.href = '#'
this._prevBtn.className = 'menu-horizontal-prev'
container.appendChild(this._prevBtn)
}
this._wrapper = el.querySelector('.menu-horizontal-wrapper')
if (!this._wrapper) {
this._wrapper = document.createElement('div')
this._wrapper.className = 'menu-horizontal-wrapper'
this._wrapper.appendChild(this._inner)
container.appendChild(this._wrapper)
}
this._nextBtn = el.querySelector('.menu-horizontal-next')
if (!this._nextBtn) {
this._nextBtn = document.createElement('a')
this._nextBtn.href = '#'
this._nextBtn.className = 'menu-horizontal-next'
container.appendChild(this._nextBtn)
}
this._innerPosition = 0
this.update()
}
// Switch to vertical menu on small screen for horizontal menu layout on page load
if (this._horizontal && window.innerWidth < window.Helpers.LAYOUT_BREAKPOINT) {
this.switchMenu('vertical')
} else {
this._bindEvents()
}
// Link menu instance to element
el.menuInstance = this
const semiDarkEl = localStorage.getItem(`templateCustomizer-${templateName}--SemiDark`)
if (semiDarkEl === 'true') {
document.querySelector('#layout-menu').setAttribute('data-bs-theme', 'dark')
}
}
_bindEvents() {
// Click Event
this._evntElClick = e => {
// Find top parent element
if (e.target.closest('ul') && e.target.closest('ul').classList.contains('menu-inner')) {
const menuItem = Menu._findParent(e.target, 'menu-item', false)
// eslint-disable-next-line prefer-destructuring
if (menuItem) this._topParent = menuItem.childNodes[0]
}
const toggleLink = e.target.classList.contains('menu-toggle')
? e.target
: Menu._findParent(e.target, 'menu-toggle', false)
if (toggleLink) {
e.preventDefault()
if (toggleLink.getAttribute('data-hover') !== 'true') {
this.toggle(toggleLink)
}
}
}
if ((!this._showDropdownOnHover && this._horizontal) || !this._horizontal || window.Helpers.isMobileDevice)
this._el.addEventListener('click', this._evntElClick)
this._evntWindowResize = () => {
this.update()
if (this._lastWidth !== window.innerWidth) {
this._lastWidth = window.innerWidth
this.update()
}
const horizontalMenuTemplate = document.querySelector("[data-template^='horizontal-menu']")
if (!this._horizontal && !horizontalMenuTemplate) this.manageScroll()
}
window.addEventListener('resize', this._evntWindowResize)
if (this._horizontal) {
this._evntPrevBtnClick = e => {
e.preventDefault()
if (this._prevBtn.classList.contains('disabled')) return
this._slide('prev')
}
this._prevBtn.addEventListener('click', this._evntPrevBtnClick)
this._evntNextBtnClick = e => {
e.preventDefault()
if (this._nextBtn.classList.contains('disabled')) return
this._slide('next')
}
this._nextBtn.addEventListener('click', this._evntNextBtnClick)
this._evntBodyClick = e => {
if (!this._inner.contains(e.target) && this._el.querySelectorAll('.menu-inner > .menu-item.open').length)
this.closeAll()
}
document.body.addEventListener('click', this._evntBodyClick)
if (this._showDropdownOnHover) {
/** ***********************************************
* Horizontal Menu Mouse Over Event
* ? e.target !== e.currentTarget condition to disable mouseover event on whole menu navbar
* ? !e.target.parentNode.classList.contains('open') to disable mouseover events on icon, text and dropdown arrow
*/
this._evntElMouseOver = e => {
if (e.target !== e.currentTarget && !e.target.parentNode.classList.contains('open')) {
const toggleLink = e.target.classList.contains('menu-toggle') ? e.target : null
if (toggleLink) {
e.preventDefault()
if (toggleLink.getAttribute('data-hover') !== 'true') {
this.toggle(toggleLink)
}
}
}
e.stopPropagation()
}
if (this._horizontal && window.screen.width > window.Helpers.LAYOUT_BREAKPOINT) {
this._el.addEventListener('mouseover', this._evntElMouseOver)
}
/** ***********************************************
* Horizontal Menu Mouse Out Event
* ? e.target !== e.currentTarget condition to disable mouseout event on whole menu navbar
* ? mouseOutEl.parentNode.classList.contains('open') to check if the mouseout element has open class or not
* ? !mouseOutEl.classList.contains('menu-toggle') to check if mouseout was from single menu item and not from the one which has submenu
* ? !mouseOverEl.parentNode.classList.contains('menu-link') to disable mouseout event for icon, text and dropdown arrow
*/
this._evntElMouseOut = e => {
const mainEl = e.currentTarget
const mouseOutEl = e.target
const mouseOverEl = e.toElement || e.relatedTarget
// Find absolute parent of any menu item from which mouseout event triggered
if (mouseOutEl.closest('ul') && mouseOutEl.closest('ul').classList.contains('menu-inner')) {
this._topParent = mouseOutEl
}
if (
mouseOutEl !== mainEl &&
(mouseOutEl.parentNode.classList.contains('open') || !mouseOutEl.classList.contains('menu-toggle')) &&
mouseOverEl &&
mouseOverEl.parentNode &&
!mouseOverEl.parentNode.classList.contains('menu-link')
) {
// When mouse goes totally out of menu items, check mouse over element to confirm it's not the child of menu, once confirmed close the menu
if (this._topParent && !Menu.childOf(mouseOverEl, this._topParent.parentNode)) {
const toggleLink = this._topParent.classList.contains('menu-toggle') ? this._topParent : null
if (toggleLink) {
e.preventDefault()
if (toggleLink.getAttribute('data-hover') !== 'true') {
this.toggle(toggleLink)
this._topParent = null
}
}
}
// When mouse enter the sub menu, check if it's child of the initially mouse overed menu item(Actual Parent),
// if it's the parent do not close the sub menu else close the sub menu
if (Menu.childOf(mouseOverEl, mouseOutEl.parentNode)) {
return
}
const toggleLink = mouseOutEl.classList.contains('menu-toggle') ? mouseOutEl : null
if (toggleLink) {
e.preventDefault()
if (toggleLink.getAttribute('data-hover') !== 'true') {
this.toggle(toggleLink)
}
}
}
e.stopPropagation()
}
if (this._horizontal && window.screen.width > window.Helpers.LAYOUT_BREAKPOINT) {
this._el.addEventListener('mouseout', this._evntElMouseOut)
}
}
}
}
static childOf(/* child node */ c, /* parent node */ p) {
// returns boolean
if (c.parentNode) {
while ((c = c.parentNode) && c !== p);
return !!c
}
return false
}
_unbindEvents() {
if (this._evntElClick) {
this._el.removeEventListener('click', this._evntElClick)
this._evntElClick = null
}
if (this._evntElMouseOver) {
this._el.removeEventListener('mouseover', this._evntElMouseOver)
this._evntElMouseOver = null
}
if (this._evntElMouseOut) {
this._el.removeEventListener('mouseout', this._evntElMouseOut)
this._evntElMouseOut = null
}
if (this._evntWindowResize) {
window.removeEventListener('resize', this._evntWindowResize)
this._evntWindowResize = null
}
if (this._evntBodyClick) {
document.body.removeEventListener('click', this._evntBodyClick)
this._evntBodyClick = null
}
if (this._evntInnerMousemove) {
this._inner.removeEventListener('mousemove', this._evntInnerMousemove)
this._evntInnerMousemove = null
}
if (this._evntInnerMouseleave) {
this._inner.removeEventListener('mouseleave', this._evntInnerMouseleave)
this._evntInnerMouseleave = null
}
}
static _isRoot(item) {
return !Menu._findParent(item, 'menu-item', false)
}
static _findParent(el, cls, throwError = true) {
if (el.tagName.toUpperCase() === 'BODY') return null
el = el.parentNode
while (el.tagName.toUpperCase() !== 'BODY' && !el.classList.contains(cls)) {
el = el.parentNode
}
el = el.tagName.toUpperCase() !== 'BODY' ? el : null
if (!el && throwError) throw new Error(`Cannot find \`.${cls}\` parent element`)
return el
}
static _findChild(el, cls) {
const items = el.childNodes
const found = []
for (let i = 0, l = items.length; i < l; i++) {
if (items[i].classList) {
let passed = 0
for (let j = 0; j < cls.length; j++) {
if (items[i].classList.contains(cls[j])) passed += 1
}
if (cls.length === passed) found.push(items[i])
}
}
return found
}
static _findMenu(item) {
let curEl = item.childNodes[0]
let menu = null
while (curEl && !menu) {
if (curEl.classList && curEl.classList.contains('menu-sub')) menu = curEl
curEl = curEl.nextSibling
}
if (!menu) throw new Error('Cannot find `.menu-sub` element for the current `.menu-toggle`')
return menu
}
// Has class
static _hasClass(cls, el = window.Helpers.ROOT_EL) {
let result = false
cls.split(' ').forEach(c => {
if (el.classList.contains(c)) result = true
})
return result
}
open(el, closeChildren = this._closeChildren) {
const item = this._findUnopenedParent(Menu._getItem(el, true), closeChildren)
if (!item) return
const toggleLink = Menu._getLink(item, true)
Menu._promisify(this._onOpen, this, item, toggleLink, Menu._findMenu(item))
.then(() => {
if (!this._horizontal || !Menu._isRoot(item)) {
if (this._animate && !this._horizontal) {
window.requestAnimationFrame(() => this._toggleAnimation(true, item, false))
if (this._accordion) this._closeOther(item, closeChildren)
} else if (this._animate) {
this._toggleDropdown(true, item, closeChildren)
// eslint-disable-next-line no-unused-expressions
this._onOpened && this._onOpened(this, item, toggleLink, Menu._findMenu(item))
} else {
item.classList.add('open')
// eslint-disable-next-line no-unused-expressions
this._onOpened && this._onOpened(this, item, toggleLink, Menu._findMenu(item))
if (this._accordion) this._closeOther(item, closeChildren)
}
} else {
this._toggleDropdown(true, item, closeChildren)
// eslint-disable-next-line no-unused-expressions
this._onOpened && this._onOpened(this, item, toggleLink, Menu._findMenu(item))
}
})
.catch(() => {})
}
close(el, closeChildren = this._closeChildren, _autoClose = false) {
const item = Menu._getItem(el, true)
const toggleLink = Menu._getLink(el, true)
if (!item.classList.contains('open') || item.classList.contains('disabled')) return
Menu._promisify(this._onClose, this, item, toggleLink, Menu._findMenu(item), _autoClose)
.then(() => {
if (!this._horizontal || !Menu._isRoot(item)) {
if (this._animate && !this._horizontal) {
window.requestAnimationFrame(() => this._toggleAnimation(false, item, closeChildren))
} else {
item.classList.remove('open')
if (closeChildren) {
const opened = item.querySelectorAll('.menu-item.open')
for (let i = 0, l = opened.length; i < l; i++) opened[i].classList.remove('open')
}
// eslint-disable-next-line no-unused-expressions
this._onClosed && this._onClosed(this, item, toggleLink, Menu._findMenu(item))
}
} else {
this._toggleDropdown(false, item, closeChildren)
// eslint-disable-next-line no-unused-expressions
this._onClosed && this._onClosed(this, item, toggleLink, Menu._findMenu(item))
}
})
.catch(() => {})
}
_closeOther(item, closeChildren) {
const opened = Menu._findChild(item.parentNode, ['menu-item', 'open'])
for (let i = 0, l = opened.length; i < l; i++) {
if (opened[i] !== item) this.close(opened[i], closeChildren)
}
}
toggle(el, closeChildren = this._closeChildren) {
const item = Menu._getItem(el, true)
if (item.classList.contains('open')) this.close(item, closeChildren)
else this.open(item, closeChildren)
}
_toggleDropdown(show, item, closeChildren) {
const menu = Menu._findMenu(item)
const actualItem = item
let subMenuItem = false
if (show) {
if (Menu._findParent(item, 'menu-sub', false)) {
subMenuItem = true
item = this._topParent ? this._topParent.parentNode : item
}
const wrapperWidth = Math.round(this._wrapper.getBoundingClientRect().width)
const position = this._innerPosition
const itemOffset = this._getItemOffset(item)
const itemWidth = Math.round(item.getBoundingClientRect().width)
if (itemOffset - DELTA <= -1 * position) {
this._innerPosition = -1 * itemOffset
} else if (itemOffset + position + itemWidth + DELTA >= wrapperWidth) {
if (itemWidth > wrapperWidth) {
this._innerPosition = -1 * itemOffset
} else {
this._innerPosition = -1 * (itemOffset + itemWidth - wrapperWidth)
}
}
actualItem.classList.add('open')
const menuWidth = Math.round(menu.getBoundingClientRect().width)
if (subMenuItem) {
if (
itemOffset + this._innerPosition + menuWidth * 2 > wrapperWidth &&
menuWidth < wrapperWidth &&
menuWidth >= itemWidth
) {
menu.style.left = [this._rtl ? '100%' : '-100%']
}
} else if (
itemOffset + this._innerPosition + menuWidth > wrapperWidth &&
menuWidth < wrapperWidth &&
menuWidth > itemWidth
) {
menu.style[this._rtl ? 'marginRight' : 'marginLeft'] = `-${menuWidth - itemWidth}px`
}
this._closeOther(actualItem, closeChildren)
this._updateSlider()
} else {
const toggle = Menu._findChild(item, ['menu-toggle'])
// eslint-disable-next-line no-unused-expressions
toggle.length && toggle[0].removeAttribute('data-hover', 'true')
item.classList.remove('open')
menu.style[this._rtl ? 'marginRight' : 'marginLeft'] = null
if (closeChildren) {
const opened = menu.querySelectorAll('.menu-item.open')
for (let i = 0, l = opened.length; i < l; i++) opened[i].classList.remove('open')
}
}
}
_slide(direction) {
const wrapperWidth = Math.round(this._wrapper.getBoundingClientRect().width)
const innerWidth = this._innerWidth
let newPosition
if (direction === 'next') {
newPosition = this._getSlideNextPos()
if (innerWidth + newPosition < wrapperWidth) {
newPosition = wrapperWidth - innerWidth
}
} else {
newPosition = this._getSlidePrevPos()
if (newPosition > 0) newPosition = 0
}
this._innerPosition = newPosition
this.update()
}
_getSlideNextPos() {
const wrapperWidth = Math.round(this._wrapper.getBoundingClientRect().width)
const position = this._innerPosition
let curItem = this._inner.childNodes[0]
let left = 0
while (curItem) {
if (curItem.tagName) {
const curItemWidth = Math.round(curItem.getBoundingClientRect().width)
if (left + position - DELTA <= wrapperWidth && left + position + curItemWidth + DELTA >= wrapperWidth) {
if (curItemWidth > wrapperWidth && left === -1 * position) left += curItemWidth
break
}
left += curItemWidth
}
curItem = curItem.nextSibling
}
return -1 * left
}
_getSlidePrevPos() {
const wrapperWidth = Math.round(this._wrapper.getBoundingClientRect().width)
const position = this._innerPosition
let curItem = this._inner.childNodes[0]
let left = 0
while (curItem) {
if (curItem.tagName) {
const curItemWidth = Math.round(curItem.getBoundingClientRect().width)
if (left - DELTA <= -1 * position && left + curItemWidth + DELTA >= -1 * position) {
if (curItemWidth <= wrapperWidth) left = left + curItemWidth - wrapperWidth
break
}
left += curItemWidth
}
curItem = curItem.nextSibling
}
return -1 * left
}
static _getItem(el, toggle) {
let item = null
const selector = toggle ? 'menu-toggle' : 'menu-link'
if (el.classList.contains('menu-item')) {
if (Menu._findChild(el, [selector]).length) item = el
} else if (el.classList.contains(selector)) {
item = el.parentNode.classList.contains('menu-item') ? el.parentNode : null
}
if (!item) {
throw new Error(`${toggle ? 'Toggable ' : ''}\`.menu-item\` element not found.`)
}
return item
}
static _getLink(el, toggle) {
let found = []
const selector = toggle ? 'menu-toggle' : 'menu-link'
if (el.classList.contains(selector)) found = [el]
else if (el.classList.contains('menu-item')) found = Menu._findChild(el, [selector])
if (!found.length) throw new Error(`\`${selector}\` element not found.`)
return found[0]
}
_findUnopenedParent(item, closeChildren) {
let tree = []
let parentItem = null
while (item) {
if (item.classList.contains('disabled')) {
parentItem = null
tree = []
} else {
if (!item.classList.contains('open')) parentItem = item
tree.push(item)
}
item = Menu._findParent(item, 'menu-item', false)
}
if (!parentItem) return null
if (tree.length === 1) return parentItem
tree = tree.slice(0, tree.indexOf(parentItem))
for (let i = 0, l = tree.length; i < l; i++) {
tree[i].classList.add('open')
if (this._accordion) {
const openedItems = Menu._findChild(tree[i].parentNode, ['menu-item', 'open'])
for (let j = 0, k = openedItems.length; j < k; j++) {
if (openedItems[j] !== tree[i]) {
openedItems[j].classList.remove('open')
if (closeChildren) {
const openedChildren = openedItems[j].querySelectorAll('.menu-item.open')
for (let x = 0, z = openedChildren.length; x < z; x++) {
openedChildren[x].classList.remove('open')
}
}
}
}
}
}
return parentItem
}
_toggleAnimation(open, item, closeChildren) {
const toggleLink = Menu._getLink(item, true)
const menu = Menu._findMenu(item)
Menu._unbindAnimationEndEvent(item)
const linkHeight = Math.round(toggleLink.getBoundingClientRect().height)
item.style.overflow = 'hidden'
const clearItemStyle = () => {
item.classList.remove('menu-item-animating')
item.classList.remove('menu-item-closing')
item.style.overflow = null
item.style.height = null
if (!this._horizontal) this.update()
}
if (open) {
item.style.height = `${linkHeight}px`
item.classList.add('menu-item-animating')
item.classList.add('open')
Menu._bindAnimationEndEvent(item, () => {
clearItemStyle()
this._onOpened(this, item, toggleLink, menu)
})
setTimeout(() => {
item.style.height = `${linkHeight + Math.round(menu.getBoundingClientRect().height)}px`
}, 50)
} else {
item.style.height = `${linkHeight + Math.round(menu.getBoundingClientRect().height)}px`
item.classList.add('menu-item-animating')
item.classList.add('menu-item-closing')
Menu._bindAnimationEndEvent(item, () => {
item.classList.remove('open')
clearItemStyle()
if (closeChildren) {
const opened = item.querySelectorAll('.menu-item.open')
for (let i = 0, l = opened.length; i < l; i++) opened[i].classList.remove('open')
}
this._onClosed(this, item, toggleLink, menu)
})
setTimeout(() => {
item.style.height = `${linkHeight}px`
}, 50)
}
}
static _bindAnimationEndEvent(el, handler) {
const cb = e => {
if (e.target !== el) return
Menu._unbindAnimationEndEvent(el)
handler(e)
}
let duration = window.getComputedStyle(el).transitionDuration
duration = parseFloat(duration) * (duration.indexOf('ms') !== -1 ? 1 : 1000)
el._menuAnimationEndEventCb = cb
TRANSITION_EVENTS.forEach(ev => el.addEventListener(ev, el._menuAnimationEndEventCb, false))
el._menuAnimationEndEventTimeout = setTimeout(() => {
cb({ target: el })
}, duration + 50)
}
_getItemOffset(item) {
let curItem = this._inner.childNodes[0]
let left = 0
while (curItem !== item) {
if (curItem.tagName) {
left += Math.round(curItem.getBoundingClientRect().width)
}
curItem = curItem.nextSibling
}
return left
}
_updateSlider(wrapperWidth = null, innerWidth = null, position = null) {
const _wrapperWidth = wrapperWidth !== null ? wrapperWidth : Math.round(this._wrapper.getBoundingClientRect().width)
const _innerWidth = innerWidth !== null ? innerWidth : this._innerWidth
const _position = position !== null ? position : this._innerPosition
if (_innerWidth < _wrapperWidth || window.innerWidth < window.Helpers.LAYOUT_BREAKPOINT) {
this._prevBtn.classList.add('d-none')
this._nextBtn.classList.add('d-none')
} else {
this._prevBtn.classList.remove('d-none')
this._nextBtn.classList.remove('d-none')
}
if (_innerWidth > _wrapperWidth && window.innerWidth > window.Helpers.LAYOUT_BREAKPOINT) {
if (_position === 0) this._prevBtn.classList.add('disabled')
else this._prevBtn.classList.remove('disabled')
if (_innerWidth + _position <= _wrapperWidth) this._nextBtn.classList.add('disabled')
else this._nextBtn.classList.remove('disabled')
}
}
static _promisify(fn, ...args) {
const result = fn(...args)
if (result instanceof Promise) {
return result
}
if (result === false) {
return Promise.reject()
}
return Promise.resolve()
}
get _innerWidth() {
const items = this._inner.childNodes
let width = 0
for (let i = 0, l = items.length; i < l; i++) {
if (items[i].tagName) {
width += Math.round(items[i].getBoundingClientRect().width)
}
}
return width
}
get _innerPosition() {
return parseInt(this._inner.style[this._rtl ? 'marginRight' : 'marginLeft'] || '0px', 10)
}
set _innerPosition(value) {
this._inner.style[this._rtl ? 'marginRight' : 'marginLeft'] = `${value}px`
return value
}
static _unbindAnimationEndEvent(el) {
const cb = el._menuAnimationEndEventCb
if (el._menuAnimationEndEventTimeout) {
clearTimeout(el._menuAnimationEndEventTimeout)
el._menuAnimationEndEventTimeout = null
}
if (!cb) return
TRANSITION_EVENTS.forEach(ev => el.removeEventListener(ev, cb, false))
el._menuAnimationEndEventCb = null
}
closeAll(closeChildren = this._closeChildren) {
const opened = this._el.querySelectorAll('.menu-inner > .menu-item.open')
for (let i = 0, l = opened.length; i < l; i++) this.close(opened[i], closeChildren)
}
static setDisabled(el, disabled) {
Menu._getItem(el, false).classList[disabled ? 'add' : 'remove']('disabled')
}
static isActive(el) {
return Menu._getItem(el, false).classList.contains('active')
}
static isOpened(el) {
return Menu._getItem(el, false).classList.contains('open')
}
static isDisabled(el) {
return Menu._getItem(el, false).classList.contains('disabled')
}
update() {
if (!this._horizontal) {
if (this._scrollbar) {
this._scrollbar.update()
}
} else {
this.closeAll()
const wrapperWidth = Math.round(this._wrapper.getBoundingClientRect().width)
const innerWidth = this._innerWidth
let position = this._innerPosition
if (wrapperWidth - position > innerWidth) {
position = wrapperWidth - innerWidth
if (position > 0) position = 0
this._innerPosition = position
}
this._updateSlider(wrapperWidth, innerWidth, position)
}
}
manageScroll() {
const { PerfectScrollbar } = window
const menuInner = document.querySelector('.menu-inner')
if (window.innerWidth < window.Helpers.LAYOUT_BREAKPOINT) {
if (this._scrollbar !== null) {
this._scrollbar.destroy()
this._scrollbar = null
}
menuInner.classList.add('overflow-auto')
} else {
if (this._scrollbar === null) {
const menuScroll = new PerfectScrollbar(document.querySelector('.menu-inner'), {
suppressScrollX: true,
wheelPropagation: false
})
this._scrollbar = menuScroll
}
menuInner.classList.remove('overflow-auto')
}
}
switchMenu(menu) {
// Unbind Events
this._unbindEvents()
// const html = document.documentElement
const navbar = document.querySelector('nav.layout-navbar')
const navbarCollapse = document.querySelector('#navbar-collapse')
const asideMenuWrapper = document.querySelector('#layout-menu div')
const asideMenu = document.querySelector('#layout-menu')
const horzMenuClasses = ['layout-menu-horizontal', 'menu', 'menu-horizontal', 'container-fluid', 'flex-grow-0']
const vertMenuClasses = ['layout-menu', 'menu', 'menu-vertical']
const horzMenuWrapper = document.querySelector('.menu-horizontal-wrapper')
const menuInner = document.querySelector('.menu-inner')
const brand = document.querySelector('.app-brand')
const menuToggler = document.querySelector('.layout-menu-toggle')
const activeMenuItems = document.querySelectorAll('.menu-inner .active')
const { PerfectScrollbar } = window
if (menu === 'vertical') {
this._horizontal = false
asideMenuWrapper.insertBefore(brand, horzMenuWrapper)
asideMenuWrapper.insertBefore(menuInner, horzMenuWrapper)
asideMenuWrapper.classList.add('flex-column', 'p-0')
asideMenu.classList.remove(...asideMenu.classList)
asideMenu.classList.add(...vertMenuClasses, this._menuBgClass)
brand.classList.remove('d-none', 'd-lg-flex')
menuToggler.classList.remove('d-none')
if (PerfectScrollbar !== undefined) {
this._psScroll = new PerfectScrollbar(document.querySelector('.menu-inner'), {
suppressScrollX: true,
wheelPropagation: !Menu._hasClass('layout-menu-fixed layout-menu-fixed-offcanvas')
})
}
menuInner.classList.add('overflow-auto')
// Add open class to active items
for (let i = 0; i < activeMenuItems.length - 1; ++i) {
activeMenuItems[i].classList.add('open')
}
} else {
this._horizontal = true
navbar.children[0].insertBefore(brand, navbarCollapse)
brand.classList.add('d-none', 'd-lg-flex')
horzMenuWrapper.appendChild(menuInner)
asideMenuWrapper.classList.remove('flex-column', 'p-0')
asideMenu.classList.remove(...asideMenu.classList)
asideMenu.classList.add(...horzMenuClasses, this._menuBgClass)
menuToggler.classList.add('d-none')
menuInner.classList.remove('overflow-auto')
// Remove open class from active items
for (let i = 0; i < activeMenuItems.length; ++i) {
activeMenuItems[i].classList.remove('open')
}
}
const semiDarkEl = localStorage.getItem(`templateCustomizer-${templateName}--SemiDark`)
if (semiDarkEl) {
asideMenu.setAttribute('data-bs-theme', 'dark')
}
this._bindEvents()
}
destroy() {
if (!this._el) return
this._unbindEvents()
const items = this._el.querySelectorAll('.menu-item')
for (let i = 0, l = items.length; i < l; i++) {
Menu._unbindAnimationEndEvent(items[i])
items[i].classList.remove('menu-item-animating')
items[i].classList.remove('open')
items[i].style.overflow = null
items[i].style.height = null
}
const menus = this._el.querySelectorAll('.menu-menu')
for (let i2 = 0, l2 = menus.length; i2 < l2; i2++) {
menus[i2].style.marginRight = null
menus[i2].style.marginLeft = null
}
this._el.classList.remove('menu-no-animation')
if (this._wrapper) {
this._prevBtn.parentNode.removeChild(this._prevBtn)
this._nextBtn.parentNode.removeChild(this._nextBtn)
this._wrapper.parentNode.insertBefore(this._inner, this._wrapper)
this._wrapper.parentNode.removeChild(this._wrapper)
this._inner.style.marginLeft = null
this._inner.style.marginRight = null
}
this._el.menuInstance = null
delete this._el.menuInstance
this._el = null
this._horizontal = null
this._animate = null
this._accordion = null
this._showDropdownOnHover = null
this._closeChildren = null
this._rtl = null
this._onOpen = null
this._onOpened = null
this._onClose = null
this._onClosed = null
if (this._scrollbar) {
this._scrollbar.destroy()
this._scrollbar = null
}
this._inner = null
this._prevBtn = null
this._wrapper = null
this._nextBtn = null
}
}
window.Menu = Menu
export { Menu }

View File

@@ -0,0 +1,9 @@
// import { autocomplete } from '@algolia/autocomplete-js';
import { autocomplete, getAlgoliaResults } from '@algolia/autocomplete-js';
try {
window.autocomplete = autocomplete;
} catch (e) {}
export { autocomplete };

View File

@@ -0,0 +1,7 @@
import { AutoFocus } from '@form-validation/plugin-auto-focus';
try {
FormValidation.plugins.AutoFocus = AutoFocus;
} catch (e) {}
export { AutoFocus };

View File

@@ -0,0 +1,7 @@
import { Bootstrap5 } from '@form-validation/plugin-bootstrap5';
try {
FormValidation.plugins.Bootstrap5 = Bootstrap5;
} catch (e) {}
export { Bootstrap5 };

View File

@@ -0,0 +1,4 @@
@import "@form-validation/core/lib/styles/index";
@import "@form-validation/plugin-framework/lib/styles/index";
@import "@form-validation/plugin-message/lib/styles/index";
@import "@form-validation/plugin-bootstrap5/lib/styles/index";

View File

@@ -0,0 +1,8 @@
import FormValidation from '@form-validation/bundle/popular'
try {
window.FormValidation = FormValidation;
} catch (e) {}
export { FormValidation };

View File

@@ -0,0 +1,414 @@
@-webkit-keyframes spin {
0% {
-webkit-transform: rotate(0);
transform: rotate(0);
}
100% {
-webkit-transform: rotate(359deg);
transform: rotate(359deg);
}
}
@keyframes spin {
0% {
-webkit-transform: rotate(0);
transform: rotate(0);
}
100% {
-webkit-transform: rotate(359deg);
transform: rotate(359deg);
}
}
@-webkit-keyframes burst {
0% {
-webkit-transform: scale(1);
transform: scale(1);
opacity: 1;
}
90% {
-webkit-transform: scale(1.5);
transform: scale(1.5);
opacity: 0;
}
}
@keyframes burst {
0% {
-webkit-transform: scale(1);
transform: scale(1);
opacity: 1;
}
90% {
-webkit-transform: scale(1.5);
transform: scale(1.5);
opacity: 0;
}
}
@-webkit-keyframes flashing {
0% {
opacity: 1;
}
45% {
opacity: 0;
}
90% {
opacity: 1;
}
}
@keyframes flashing {
0% {
opacity: 1;
}
45% {
opacity: 0;
}
90% {
opacity: 1;
}
}
@-webkit-keyframes fade-left {
0% {
-webkit-transform: translateX(0);
transform: translateX(0);
opacity: 1;
}
75% {
-webkit-transform: translateX(-20px);
transform: translateX(-20px);
opacity: 0;
}
}
@keyframes fade-left {
0% {
-webkit-transform: translateX(0);
transform: translateX(0);
opacity: 1;
}
75% {
-webkit-transform: translateX(-20px);
transform: translateX(-20px);
opacity: 0;
}
}
@-webkit-keyframes fade-right {
0% {
-webkit-transform: translateX(0);
transform: translateX(0);
opacity: 1;
}
75% {
-webkit-transform: translateX(20px);
transform: translateX(20px);
opacity: 0;
}
}
@keyframes fade-right {
0% {
-webkit-transform: translateX(0);
transform: translateX(0);
opacity: 1;
}
75% {
-webkit-transform: translateX(20px);
transform: translateX(20px);
opacity: 0;
}
}
@-webkit-keyframes fade-up {
0% {
-webkit-transform: translateY(0);
transform: translateY(0);
opacity: 1;
}
75% {
-webkit-transform: translateY(-20px);
transform: translateY(-20px);
opacity: 0;
}
}
@keyframes fade-up {
0% {
-webkit-transform: translateY(0);
transform: translateY(0);
opacity: 1;
}
75% {
-webkit-transform: translateY(-20px);
transform: translateY(-20px);
opacity: 0;
}
}
@-webkit-keyframes fade-down {
0% {
-webkit-transform: translateY(0);
transform: translateY(0);
opacity: 1;
}
75% {
-webkit-transform: translateY(20px);
transform: translateY(20px);
opacity: 0;
}
}
@keyframes fade-down {
0% {
-webkit-transform: translateY(0);
transform: translateY(0);
opacity: 1;
}
75% {
-webkit-transform: translateY(20px);
transform: translateY(20px);
opacity: 0;
}
}
@-webkit-keyframes tada {
from {
-webkit-transform: scale3d(1, 1, 1);
transform: scale3d(1, 1, 1);
}
10%,
20% {
-webkit-transform: scale3d(0.95, 0.95, 0.95) rotate3d(0, 0, 1, -10deg);
transform: scale3d(0.95, 0.95, 0.95) rotate3d(0, 0, 1, -10deg);
}
30%,
50%,
70%,
90% {
-webkit-transform: scale3d(1, 1, 1) rotate3d(0, 0, 1, 10deg);
transform: scale3d(1, 1, 1) rotate3d(0, 0, 1, 10deg);
}
40%,
60%,
80% {
-webkit-transform: scale3d(1, 1, 1) rotate3d(0, 0, 1, -10deg);
transform: scale3d(1, 1, 1) rotate3d(0, 0, 1, -10deg);
}
to {
-webkit-transform: scale3d(1, 1, 1);
transform: scale3d(1, 1, 1);
}
}
@keyframes tada {
from {
-webkit-transform: scale3d(1, 1, 1);
transform: scale3d(1, 1, 1);
}
10%,
20% {
-webkit-transform: scale3d(0.95, 0.95, 0.95) rotate3d(0, 0, 1, -10deg);
transform: scale3d(0.95, 0.95, 0.95) rotate3d(0, 0, 1, -10deg);
}
30%,
50%,
70%,
90% {
-webkit-transform: scale3d(1, 1, 1) rotate3d(0, 0, 1, 10deg);
transform: scale3d(1, 1, 1) rotate3d(0, 0, 1, 10deg);
}
40%,
60%,
80% {
-webkit-transform: rotate3d(0, 0, 1, -10deg);
transform: rotate3d(0, 0, 1, -10deg);
}
to {
-webkit-transform: scale3d(1, 1, 1);
transform: scale3d(1, 1, 1);
}
}
.ti-spin {
-webkit-animation: spin 2s linear infinite;
animation: spin 2s linear infinite;
}
.ti-spin-hover:hover {
-webkit-animation: spin 2s linear infinite;
animation: spin 2s linear infinite;
}
.ti-tada {
-webkit-animation: tada 1.5s ease infinite;
animation: tada 1.5s ease infinite;
}
.ti-tada-hover:hover {
-webkit-animation: tada 1.5s ease infinite;
animation: tada 1.5s ease infinite;
}
.ti-flashing {
-webkit-animation: flashing 1.5s infinite linear;
animation: flashing 1.5s infinite linear;
}
.ti-flashing-hover:hover {
-webkit-animation: flashing 1.5s infinite linear;
animation: flashing 1.5s infinite linear;
}
.ti-burst {
-webkit-animation: burst 1.5s infinite linear;
animation: burst 1.5s infinite linear;
}
.ti-burst-hover:hover {
-webkit-animation: burst 1.5s infinite linear;
animation: burst 1.5s infinite linear;
}
.ti-fade-up {
-webkit-animation: fade-up 1.5s infinite linear;
animation: fade-up 1.5s infinite linear;
}
.ti-fade-up-hover:hover {
-webkit-animation: fade-up 1.5s infinite linear;
animation: fade-up 1.5s infinite linear;
}
.ti-fade-down {
-webkit-animation: fade-down 1.5s infinite linear;
animation: fade-down 1.5s infinite linear;
}
.ti-fade-down-hover:hover {
-webkit-animation: fade-down 1.5s infinite linear;
animation: fade-down 1.5s infinite linear;
}
.ti-fade-left {
-webkit-animation: fade-left 1.5s infinite linear;
animation: fade-left 1.5s infinite linear;
}
.ti-fade-left-hover:hover {
-webkit-animation: fade-left 1.5s infinite linear;
animation: fade-left 1.5s infinite linear;
}
.ti-fade-right {
-webkit-animation: fade-right 1.5s infinite linear;
animation: fade-right 1.5s infinite linear;
}
.ti-fade-right-hover:hover {
-webkit-animation: fade-right 1.5s infinite linear;
animation: fade-right 1.5s infinite linear;
}
.ti-xs {
font-size: 1rem !important;
}
.ti-sm {
font-size: 1.125rem !important;
}
.ti-md {
font-size: 1.375rem !important;
}
.ti-lg {
font-size: 1.5rem !important;
}
.ti-xl {
font-size: 2.25rem !important;
}
.ti-10px {
&,
&:before {
font-size: 10px;
}
}
.ti-12px {
&,
&:before {
font-size: 12px;
}
}
.ti-14px {
&,
&:before {
font-size: 14px;
}
}
.ti-16px {
&,
&:before {
font-size: 16px;
}
}
.ti-18px {
&,
&:before {
font-size: 18px;
}
}
.ti-20px {
&,
&:before {
font-size: 20px;
}
}
.ti-22px {
&,
&:before {
font-size: 22px;
}
}
.ti-24px {
&,
&:before {
font-size: 24px;
}
}
.ti-26px {
&,
&:before {
font-size: 26px;
}
}
.ti-28px {
&,
&:before {
font-size: 28px;
}
}
.ti-30px {
&,
&:before {
font-size: 30px;
}
}
.ti-32px {
&,
&:before {
font-size: 32px;
}
}
.ti-36px {
&,
&:before {
font-size: 36px;
}
}
.ti-40px {
&,
&:before {
font-size: 40px;
}
}
.ti-42px {
&,
&:before {
font-size: 42px;
}
}
.ti-48px {
&,
&:before {
font-size: 48px;
}
}

View File

@@ -0,0 +1 @@
@import "animate.css/animate";

View File

@@ -0,0 +1,7 @@
import AOS from 'aos/dist/aos';
try {
window.AOS = AOS;
} catch (e) {}
export { AOS };

View File

@@ -0,0 +1,89 @@
/**
* Apex Charts
*/
@import "../../scss/_bootstrap-extended/include";
@import "apexcharts/dist/apexcharts";
.apexcharts-canvas {
.apexcharts-tooltip {
box-shadow: var(--#{$prefix}box-shadow);
&.apexcharts-theme-light {
border-color: var(--#{$prefix}border-color);
background: var(--#{$prefix}paper-bg);
color: var(--#{$prefix}heading-color);
.apexcharts-tooltip-title {
background: var(--#{$prefix}paper-bg);
border-block-end-color: var(--#{$prefix}border-color);
font-family: $font-family-base !important;
font-weight: $headings-font-weight;
}
}
&.apexcharts-theme-dark {
background: transparent;
}
}
.apexcharts-xaxistooltip,
.apexcharts-yaxistooltip {
border-color: var(--#{$prefix}border-color);
background: var(--#{$prefix}paper-bg);
color: var(--#{$prefix}heading-color);
&.apexcharts-xaxistooltip-bottom,
&.apexcharts-yaxistooltip-bottom {
&::after {
border-block-end-color: var(--#{$prefix}paper-bg);
}
&::before {
border-block-end-color: var(--#{$prefix}border-color);
}
}
&.apexcharts-xaxistooltip-left,
&.apexcharts-yaxistooltip-left {
&::after {
border-inline-start-color: var(--#{$prefix}paper-bg);
}
&::before {
border-inline-start-color: var(--#{$prefix}border-color);
}
}
&.apexcharts-xaxistooltip-right,
&.apexcharts-yaxistooltip-right {
&::after {
border-inline-end-color: var(--#{$prefix}paper-bg);
}
&::before {
border-inline-end-color: var(--#{$prefix}border-color);
}
}
&.apexcharts-xaxistooltip-top,
&.apexcharts-yaxistooltip-top {
&::after {
border-block-start-color: var(--#{$prefix}paper-bg);
}
&::before {
border-block-start-color: var(--#{$prefix}border-color);
}
}
}
.apexcharts-tooltip-text {
font-family: $font-family-base !important;
}
.apexcharts-legend-marker,
.apexcharts-tooltip-marker {
margin-inline: 0 .1875rem;
}
}
:dir(rtl) {
.apexcharts-canvas {
.apexcharts-legend {
direction: rtl !important;
}
}
}

View File

@@ -0,0 +1,7 @@
import ApexCharts from 'apexcharts';
try {
window.ApexCharts = ApexCharts;
} catch (e) {}
export { ApexCharts };

View File

@@ -0,0 +1,7 @@
import Bloodhound from 'typeahead.js/dist/bloodhound';
try {
window.Bloodhound = Bloodhound;
} catch (e) {}
export { Bloodhound };

View File

@@ -0,0 +1,18 @@
import 'bootstrap-daterangepicker/daterangepicker';
// Patch detect when weeks are shown
const fnDaterangepicker = $.fn.daterangepicker;
$.fn.daterangepicker = function (options, callback) {
fnDaterangepicker.call(this, options, callback);
if (options && (options.showWeekNumbers || options.showISOWeekNumbers)) {
this.each(function () {
const instance = $(this).data('daterangepicker');
if (instance && instance.container) instance.container.addClass('with-week-numbers');
});
}
return this;
};

View File

@@ -0,0 +1,352 @@
@import "../../scss/_bootstrap-extended/include";
@import "../../scss/_components/include";
.daterangepicker {
position: absolute;
z-index: $picker-zindex;
display: none;
background-color: $picker-bg;
box-shadow: $picker-box-shadow;
margin-block-start: $picker-spacer;
@include border-radius($picker-border-radius);
.calendar-table{
/* prev & next arrow wrapper styles */
.next,
.prev {
position: absolute;
display: flex;
align-items: center;
justify-content: center;
background-color: $picker-arrow-bg;
block-size: $picker-arrow-wrapper-size;
inline-size: $picker-arrow-wrapper-size;
inset-block-start: .65rem;
min-inline-size: unset;
@include border-radius($picker-cell-border-radius);
}
/* prev & next arrow default styles with border */
.next span,
.prev span {
display: inline-block;
border-width: 0 1.9px 1.9px 0;
border-style: solid;
border-color: $picker-arrow-color;
block-size: $picker-arrow-size;
inline-size: $picker-arrow-size;
@include border-radius(0);
}
.prev span {
margin-inline-end: -$picker-arrow-size * .5;
transform: rotate(135deg);
:dir(rtl) & {
transform: rotate(-45deg);
}
}
.next span {
margin-inline-start: -$picker-arrow-size * .5;
transform: rotate(-45deg);
:dir(rtl) & {
margin-inline: 0;
transform: rotate(135deg);
}
}
/* picker table styles */
table {
border: 0;
margin: 0;
border-collapse: collapse;
border-spacing: 0;
inline-size: 100%;
thead {
tr:first-child {
position: relative;
block-size: $picker-header-size;
}
tr:last-child th {
color: $picker-header-color;
font-size: $font-size-sm;
font-weight: $font-weight-medium;
@include border-radius(0);
}
th select{
background-color: transparent;
}
}
th.month {
inline-size: auto;
}
td {
inline-size: $picker-cell-size;
@include border-radius($picker-cell-border-radius);
&.start-date:not(.end-date) {
@include border-end-radius(0);
}
&.end-date:not(.start-date) {
@include border-start-radius(0);
}
&.start-date:not(.end-date, .off),
&.end-date:not(.start-date, .off) {
border: 0;
background-color: $picker-cell-active-bg;
color: $picker-cell-active-color;
&:hover {
background-color: $picker-cell-active-bg;
}
}
&.off{
color: $picker-disabled-color;
}
/* week header styles */
&.week{
color: $picker-header-color;
font-weight: $font-weight-normal;
}
/* active date styles */
&.active.today.start-date:not(.off),
&.active.today.end-date:not(.off),
&.active:not(.off){
background: $picker-cell-active-bg;
box-shadow: $picker-cell-active-shadow;
color: $picker-cell-active-color;
}
/* today date styles */
&.today,
&.today.active,
&.today:hover {
background: $picker-cell-today-bg;
color: $picker-cell-today-color;
}
&.in-range:not(.start-date, .end-date) {
@include border-radius(0);
box-shadow: none;
}
/* hover & not in range date styles */
&.in-range:not(.start-date, .end-date, .off) {
&,
&:hover {
background-color: $picker-range-active-bg;
color: $picker-range-active-color;
}
}
}
th {
block-size: $picker-cell-size + .5rem;
}
th,
td {
block-size: $picker-cell-size;
cursor: pointer;
line-height: calc(#{$picker-cell-size} - 2px);
min-inline-size: $picker-cell-size;
text-align: center;
vertical-align: middle;
white-space: nowrap;
}
td.available:not(.active, .in-range):hover {
background-color: $picker-cell-hover-bg;
}
td.disabled,
option.disabled {
color: $picker-disabled-color;
cursor: not-allowed;
text-decoration: line-through;
}
}
}
.input-mini.active {
border-color: $picker-cell-active-bg;
}
/* dual date range picker styles */
.drp-calendar:not(.single){
&.left{
.prev{
inset-inline-start: .625rem;
}
}
&.right{
.next{
inset-inline-end: .625rem;
}
}
}
.drp-calendar.single{
.prev{
inset-inline-start: .4rem;
}
}
&:not(.single) {
/* responsive above md */
@include media-breakpoint-up(md) {
.drp-calendar {
float: inline-start;
}
}
.drp-selected {
display: inline-block;
padding: 0;
inline-size: auto;
}
}
/* selected date range styles */
.drp-selected{
display: block;
font-size: $font-size-sm;
inline-size: 100%;
padding-block-end: $picker-padding;
}
&.auto-apply .drp-buttons {
display: none;
}
&.show-calendar .drp-calendar,
&.show-calendar .drp-buttons {
display: block;
}
.drp-calendar {
display: none;
padding: $picker-padding;
&.single .calendar-table {
border: 0;
}
}
&.single {
.drp-selected {
display: none;
}
.daterangepicker .ranges,
.drp-calendar {
float: none;
}
}
/* select dropdown styles */
select {
&.monthselect,
&.yearselect {
padding: 1px;
border: 0;
margin: 0;
block-size: auto;
cursor: default;
}
&:focus-visible {
outline: 0;
}
&.hourselect,
&.minuteselect,
&.secondselect,
&.ampmselect {
padding: 2px;
border: 1px solid transparent;
background: $picker-select-bg;
color: $picker-color;
font-size: $font-size-sm;
inline-size: $picker-select-width;
margin-block: 0;
margin-inline: auto;
outline: 0;
@include border-radius($picker-select-timer-radius);
option {
background: $picker-bg;
}
}
&.monthselect {
margin-inline-end: 4%;
}
&.yearselect {
inline-size: 40%;
}
}
/* time picker styles */
.calendar-time {
position: relative;
line-height: 30px;
margin-block: 0;
margin-inline: auto;
text-align: center;
select.disabled {
color: $picker-disabled-color;
cursor: not-allowed;
}
}
.drp-buttons {
display: none;
padding: $picker-padding;
clear: both;
text-align: end;
vertical-align: middle;
.btn {
margin-inline-start: $picker-padding * 1.2;
}
}
/* ranges styles */
.ranges {
margin: 0;
float: inline-start;
text-align: start;
ul {
padding: .5rem;
inline-size: 100%;
list-style: none;
margin-block: 0;
margin-inline: auto;
li{
@include border-radius($picker-border-radius);
cursor: pointer;
padding-block: $dropdown-item-padding-y;
padding-inline: $dropdown-item-padding-x;
&:not(:first-child) {
margin-block-start: .125rem;
}
&:hover {
background-color: $picker-cell-hover-bg;
}
&.active {
background-color: $picker-cell-active-bg;
color: $picker-cell-active-color;
}
}
}
}
&.show-calendar .ranges {
&:empty {
display: none;
}
}
}

View File

@@ -0,0 +1 @@
import 'bootstrap-select/js/bootstrap-select';

View File

@@ -0,0 +1,170 @@
// Bootstrap Select
// *******************************************************************************
@import "../../scss/_bootstrap-extended/include";
@import "bootstrap-select/sass/bootstrap-select";
/* Common Styles */
.bootstrap-select *,
.bootstrap-select .dropdown-toggle:focus {
outline: 0 !important;
}
.bootstrap-select {
--#{$prefix}bootstrap-select-arrow-position: 23px;
.bs-searchbox,
.bs-actionsbox,
.bs-donebutton {
padding-block: 0 .5rem;
padding-inline: 0;
}
> .dropdown-toggle {
&.bs-placeholder {
&,
&:hover,
&:focus,
&:active {
color: $input-placeholder-color;
}
}
}
.dropdown-toggle {
border: $input-border-width solid $input-border-color;
@include border-radius($input-border-radius);
color: $input-color;
padding-block: calc($input-padding-y - $input-border-width);
padding-inline: $input-padding-x;
transition: none;
.filter-option {
float: inline-start;
inset-inline: 0 auto;
text-align: start;
}
&::after {
position: absolute;
margin: 0;
inset-block-start: 50%;
inset-inline-end: var(--#{$prefix}bootstrap-select-arrow-position);
transform: rotate(45deg) translateY(-100%);
:dir(rtl) & {
transform: rotate(-45deg) translateY(-100%);
}
}
&.show,
&:focus,
&:active {
border-width: $input-focus-border-width;
border-color: $input-focus-border-color;
box-shadow: $input-focus-box-shadow;
padding-block: calc($input-padding-y - $input-focus-border-width);
padding-inline: calc($input-padding-x - $input-border-width);
&::after {
inset-inline-end: calc(var(--#{$prefix}bootstrap-select-arrow-position) - $input-border-width);
}
}
.filter-option-inner-inner {
float: inline-start;
line-height: $input-line-height;
}
}
.dropdown-menu li small,
.filter-option small {
position: relative;
float: inline-end;
inset-block-start: 2px;
padding-inline: .5em 0;
}
.dropdown-menu {
.notify {
border-color: color-mix(in sRGB, var(--#{$prefix}base-color) 16%, var(--#{$prefix}paper-bg));
background: color-mix(in sRGB, var(--#{$prefix}base-color) 6%, var(--#{$prefix}paper-bg));
}
/* For header dropdown close btn */
.popover-header {
display: flex;
flex-direction: row-reverse;
align-items: center;
justify-content: space-between;
margin-inline: var(--#{$prefix}dropdown-item-padding-x);
button {
padding: 0;
border: none;
background: transparent;
color: var(--#{$prefix}body-color);
font-size: $h4-font-size;
}
}
a[aria-selected="true"] {
background: $component-active-bg;
color: var(--#{$prefix}primary-contrast);
}
li.active small,
li:active small {
color: var(--#{$prefix}primary-contrast) !important;
}
.dropdown-item.selected span::before,
.dropdown-item:active,
.dropdown-toggle.show {
background: $component-active-bg;
color: var(--#{$prefix}primary-contrast);
}
}
.btn {
&:disabled,
&.disabled {
color: $input-disabled-color;
}
&:hover {
transform: none;
}
}
.is-invalid {
~ .dropdown-toggle {
&::after {
inset-inline-end: calc(var(--#{$prefix}bootstrap-select-arrow-position) - $input-border-width);
}
}
}
&.dropup {
--#{$prefix}bootstrap-select-arrow-position: 14px;
.dropdown-toggle {
&::after {
transform: rotate(317deg) translateY(-30%);
:dir(rtl) & {
transform: rotate(-317deg) translateY(-30%);
}
}
}
}
/* Menu Position */
&.show-tick {
.dropdown-menu {
li {
a {
position: relative;
span.text {
margin-inline: 0 2.125rem;
}
}
}
.selected span.check-mark {
inset-block-start: 50%;
inset-inline: auto 1rem;
inset-inline-end: 1rem;
transform: translateY(-50%);
}
}
}
&:not(.input-group-btn),
&[class*="col-"] {
display: block;
}
}
html[class] .bootstrap-select.form-select {
padding: 0;
border: 0;
margin: 0;
background: none;
}

View File

@@ -0,0 +1,37 @@
import Stepper from 'bs-stepper/dist/js/bs-stepper';
const bsStepper = document.querySelectorAll('.bs-stepper');
// Adds crossed class
bsStepper.forEach(el => {
el.addEventListener('show.bs-stepper', function (event) {
var index = event.detail.indexStep;
var numberOfSteps = el.querySelectorAll('.line').length;
var line = el.querySelectorAll('.step');
// The first for loop is for increasing the steps,
// the second is for turning them off when going back
// and the third with the if statement because the last line
// can't seem to turn off when I press the first item. ¯\_(ツ)_/¯
for (let i = 0; i < index; i++) {
line[i].classList.add('crossed');
for (let j = index; j < numberOfSteps; j++) {
line[j].classList.remove('crossed');
}
}
if (event.detail.to == 0) {
for (let k = index; k < numberOfSteps; k++) {
line[k].classList.remove('crossed');
}
line[0].classList.remove('crossed');
}
});
});
try {
window.Stepper = Stepper;
} catch (e) {}
export { Stepper };

View File

@@ -0,0 +1,374 @@
@import "../../scss/_bootstrap-extended/include";
@import "bs-stepper/dist/css/bs-stepper";
$bs-stepper-header-padding-y: 1.5rem !default;
$bs-stepper-header-padding-x: $bs-stepper-header-padding-y !default;
$bs-stepper-content-padding-x: 1.5rem !default;
$bs-stepper-content-padding-y: $bs-stepper-content-padding-x !default;
$bd-stepper-circle-size: 2.375rem !default;
$bs-stepper-trigger-padding: 1.25rem !default;
$bs-stepper-trigger-padding-vertical: .6rem !default;
$bs-stepper-label-max-width: 224px !default;
$bs-stepper-svg-icon-height: 3.75rem !default;
$bs-stepper-svg-icon-width: 3.75rem !default;
$bs-stepper-icon-font-size: 1.6rem !default;
$bs-stepper-vertical-header-min-width: 18rem !default;
$bs-stepper-crossed-bg: var(--#{$prefix}primary-bg-subtle) !default;
$bs-stepper-active-bg: var(--#{$prefix}primary) !default;
$bs-stepper-active-color: var(--#{$prefix}primary-contrast) !default;
$bs-stepper-active-shadow: 0 .125rem .375rem 0 rgba(var(--#{$prefix}primary-rgb), .3) !default;
/* Default Styles */
.bs-stepper {
@include border-radius($border-radius);
background-color: var(--#{$prefix}paper-bg);
.line {
flex: 0;
margin: 0;
background-color: transparent;
min-block-size: auto;
min-inline-size: auto;
}
.bs-stepper-header {
border-block-end: 1px solid var(--#{$prefix}border-color);
padding-block: $bs-stepper-header-padding-y;
padding-inline: $bs-stepper-header-padding-x;
.line {
.icon-base {
:dir(rtl) &{
transform: rotate(180deg);
}
}
}
.step {
.step-trigger {
flex-wrap: nowrap;
padding: 0;
font-weight: $font-weight-medium;
gap: .5rem;
.bs-stepper-label {
display: inline-grid;
overflow: hidden;
margin: 0;
color: var(--#{$prefix}heading-color);
font-size: $font-size-base;
font-weight: $font-weight-medium;
line-height: $h6-line-height;
max-inline-size: $bs-stepper-label-max-width;
text-align: start;
text-overflow: ellipsis;
.bs-stepper-title {
color: var(--#{$prefix}heading-color);
font-weight: $font-weight-medium;
}
.bs-stepper-subtitle {
color: var(--#{$prefix}body-color);
font-size: $small-font-size;
font-weight: $font-weight-base;
}
}
&:hover {
background-color: transparent;
}
&:focus{
color: var(--#{$prefix}heading-color);
}
@include media-breakpoint-down(lg) {
padding-block: calc($bs-stepper-trigger-padding * .5);
padding-inline: 0;
}
}
&.active{
.bs-stepper-circle{
background-color: $bs-stepper-active-bg;
box-shadow: $bs-stepper-active-shadow;
color: $bs-stepper-active-color;
}
.bs-stepper-icon svg{
fill: $bs-stepper-active-bg;
}
.bs-stepper-icon i{
color: $bs-stepper-active-bg;
}
}
&:not(.active) {
.bs-stepper-circle {
background-color: rgba(var(--#{$prefix}base-color-rgb), .06);
color: var(--#{$prefix}heading-color);
}
}
&.crossed {
.step-trigger {
.bs-stepper-label .bs-stepper-subtitle,
.bs-stepper-title {
color: var(--#{$prefix}secondary-color);
}
.bs-stepper-circle {
background-color: $bs-stepper-crossed-bg;
color: $bs-stepper-active-bg;
}
/* stepper icons color */
.bs-stepper-icon svg {
fill: $bs-stepper-active-bg;
}
.bs-stepper-icon .icon-base {
color: $bs-stepper-active-bg;
}
}
+ .line {
.icon-base {
color: var(--#{$prefix}body-color);
}
}
}
/* stepper circle / pill styles */
.bs-stepper-circle {
display: flex;
align-items: center;
justify-content: center;
@include border-radius($border-radius);
block-size: $bd-stepper-circle-size;
font-size: $h5-font-size;
font-weight: $font-weight-medium;
inline-size: $bd-stepper-circle-size;
.icon-base {
font-size: $bd-stepper-circle-size - 1rem;
}
}
}
}
/* stepper content padding */
.bs-stepper-content {
padding-block: $bs-stepper-content-padding-y;
padding-inline: $bs-stepper-content-padding-x;
.btn-next,
.btn-prev {
.icon-base:not(.tabler-check) {
:dir(rtl) & {
transform: rotate(180deg);
}
}
}
}
&.vertical {
.bs-stepper-header {
border-block-end: none;
min-inline-size: $bs-stepper-vertical-header-min-width;
@include media-breakpoint-down(lg) {
border-block-end: 1px solid var(--#{$prefix}border-color);
}
.step {
.step-trigger {
padding-block: $bs-stepper-trigger-padding-vertical;
padding-inline: 0;
}
&:first-child {
.step-trigger {
padding-block-start: 0;
}
}
&:last-child {
.step-trigger {
padding-block-end: 0;
}
}
}
.line {
position: relative;
min-block-size: 1px;
}
}
.bs-stepper-content {
inline-size: 100%;
.content {
&:not(.active) {
display: none;
}
}
}
&.wizard-icons {
.step {
padding-block: .75rem;
padding-inline: 0;
text-align: center;
}
}
}
&.wizard-icons {
.bs-stepper-header {
justify-content: center;
.step {
.step-trigger {
flex-direction: column;
padding: $bs-stepper-trigger-padding;
gap: .5rem;
.bs-stepper-icon {
svg {
block-size: $bs-stepper-svg-icon-height;
fill: var(--#{$prefix}heading-color);
inline-size: $bs-stepper-svg-icon-width;
}
.icon-base {
fill: var(--#{$prefix}heading-color);
font-size: $bs-stepper-icon-font-size;
}
}
}
&.active{
.step-trigger{
.bs-stepper-icon svg{
fill: $bs-stepper-active-bg;
}
.bs-stepper-label,
.bs-stepper-icon .icon-base {
color: $bs-stepper-active-bg;
}
}
}
}
@include media-breakpoint-up(lg) {
justify-content: space-around;
gap: 1rem;
}
}
.step.crossed {
.step-trigger{
.bs-stepper-label {
color: $bs-stepper-active-bg;
}
.bs-stepper-icon svg {
fill: $bs-stepper-active-bg;
}
.bs-stepper-icon .icon-base {
color: $bs-stepper-active-bg;
}
}
& + {
.line {
.icon-base {
color: $bs-stepper-active-bg;
}
}
}
}
}
/* Remove borders from wizard modern */
&.wizard-modern {
background-color: transparent;
.bs-stepper-header {
border-block-end: none;
}
.bs-stepper-content {
@include border-radius($border-radius);
background-color: var(--#{$prefix}paper-bg);
box-shadow: $card-box-shadow;
}
}
&:not(.wizard-modern) {
box-shadow: $card-box-shadow;
}
&:not(.vertical):not(.wizard-icons) .bs-stepper-header {
@include media-breakpoint-up(lg) {
gap: 1.25rem;
}
}
}
/* Media Queries */
@include media-breakpoint-down(lg) {
.bs-stepper {
.bs-stepper-header {
flex-direction: column;
align-items: flex-start;
.step {
.step-trigger {
flex-direction: row;
.bs-stepper-label {
margin-inline-start: .35rem;
}
}
&:first-child {
.step-trigger {
padding-block-start: 0;
}
}
&:last-child {
.step-trigger {
padding-block-end: 0;
}
}
}
}
&.vertical {
flex-direction: column;
.bs-stepper-header {
align-items: flex-start;
}
&.wizard-icons {
.bs-stepper-header {
.line::before {
inset-inline-start: .75rem;
margin-inline-start: 0;
}
}
}
}
&.wizard-icons {
.bs-stepper-header {
.step .step-trigger {
flex-direction: row;
padding-inline-start: 0;
}
}
}
&:not(.vertical) {
.bs-stepper-header {
.line {
.icon-base {
display: none;
}
}
}
}
}
}
/* Styles for Modal example Create App wizard */
#wizard-create-app {
&.vertical {
.bs-stepper-header {
min-inline-size: $bs-stepper-vertical-header-min-width - 3;
}
}
}
@media (max-width: 520px) {
/* To set minus margin in mobile screen
as that affects border */
.bs-stepper-header {
margin: 0;
}
}

View File

@@ -0,0 +1,7 @@
import Chart from 'chart.js/auto';
try {
window.Chart = Chart;
} catch (e) {}
export { Chart };

View File

@@ -0,0 +1,23 @@
/**
* chartjs Charts
*/
@import "../../scss/_bootstrap-extended/include";
.custom-legend {
.custom-legend-ul {
display: flex;
cursor: pointer;
.custom-legend-li {
display: flex;
align-items: center;
font-size: $font-size-xs;
margin-inline-end: 1.25rem;
}
.legend-box {
@include border-radius($border-radius-pill);
block-size: .5rem;
inline-size: .5rem;
margin-inline-end: 5px;
}
}
}

View File

@@ -0,0 +1,19 @@
import {
formatCreditCard,
getCreditCardType,
formatDate,
formatTime,
formatNumeral,
formatGeneral,
registerCursorTracker
} from 'cleave-zen';
export {
formatCreditCard,
getCreditCardType,
formatDate,
formatTime,
formatNumeral,
formatGeneral,
registerCursorTracker
};

View File

@@ -0,0 +1,7 @@
import ClipboardJS from 'clipboard';
try {
window.ClipboardJS = ClipboardJS;
} catch (e) {}
export { ClipboardJS };

View File

@@ -0,0 +1,27 @@
// Core libraries
import JSZip from 'jszip';
import pdfMake from 'pdfmake/build/pdfmake';
import pdfFonts from 'pdfmake/build/vfs_fonts';
// DataTables libraries (with related plugins)
import DataTable from 'datatables.net-bs5';
import 'datatables.net-fixedcolumns-bs5';
import 'datatables.net-fixedheader-bs5';
import 'datatables.net-select-bs5';
import 'datatables.net-buttons';
import 'datatables.net-buttons-bs5';
import 'datatables.net-buttons/js/buttons.html5';
import 'datatables.net-buttons/js/buttons.print';
import 'datatables.net-responsive';
import 'datatables.net-responsive-bs5';
import 'datatables.net-rowgroup-bs5';
// Attach libraries to the window object (if needed globally)
try {
window.pdfMake = pdfMake;
window.pdfFonts = pdfFonts;
window.JSZip = JSZip;
} catch (e) {}
// Export the libraries/modules
export { DataTable, JSZip, pdfMake, pdfFonts };

View File

@@ -0,0 +1,295 @@
@import "../../scss/_bootstrap-extended/include";
@import "datatables.net-bs5/css/dataTables.bootstrap5";
/* FIX: broken ui in tablet devices */
@media (hover: none) and (pointer: coarse) {
table.dataTable {
display: table;
overflow-x: auto;
}
}
/* Card header inside the datatable */
div.dt-container {
.card-header {
display: flex;
align-items: center;
justify-content: space-between;
}
.dt-buttons {
inline-size: auto;
.dt-button-down-arrow {
display: none;
}
@include media-breakpoint-down(md) {
&.btn-group {
display: block;
}
}
}
/* Remove left and right border from datatable with table-bordered class */
.table.table-bordered.dataTable {
&.dt-complex-header,
&.dt-column-search {
thead tr th {
border-width: $border-width;
&:first-child {
border-inline-start-width: 0;
}
&:last-child {
border-inline-end-width: 0;
}
}
}
th,
td {
&:last-child {
border-width: 0;
}
}
}
/* Responsive datatable in desktop screen */
@media screen and (width >= 1399.98px) {
table.table-responsive {
display: table;
}
}
div.dt-search {
input {
margin-inline: .5rem 0;
}
.form-control::-webkit-search-cancel-button {
margin-inline-start: .375rem;
}
}
div.dt-layout-end > *:not(:first-child) {
margin-inline: 0;
}
table.dataTable {
border-collapse: collapse;
inline-size: 100%;
margin-block: 0 $spacer;
/* Checkbox height & width for datatables checkboxes */
.form-check-input {
block-size: $form-datatables-check-input-size;
inline-size: $form-datatables-check-input-size;
}
thead {
> tr {
> th,
> td {
&.dt-orderable-asc,
&.dt-orderable-desc {
&:hover {
outline: none !important;
}
}
}
}
th {
/* Used while complex headers */
vertical-align: middle;
}
}
.dt-control.dt-orderable-none .dt-column-order::before {
opacity: 0;
}
td.dt-control::before {
border: 2px solid;
block-size: .55em;
border-block-start: 0;
border-inline-start: 0;
inline-size: .55em;
transform: rotate(-45deg);
:dir(rtl) & {
transform: rotate(-315deg);
}
}
tr.dt-hasChild td.dt-control::before {
border-block-start: 0;
border-inline-start: 0;
transform: rotate(45deg);
:dir(rtl) & {
transform: rotate(-45deg);
}
}
&.table tbody > tr {
&.selected,
& > .selected {
background-color: rgba(var(--#{$prefix}primary-rgb), .08);
> * {
box-shadow: none;
color: var(--#{$prefix}body-color);
}
a {
color: var(--#{$prefix}body-color);
}
}
}
}
div.dt-scroll-body {
border-block-end-width: 0;
}
@media screen and (width <= 575.98px) {
.card-header {
.dt-action-buttons {
padding-block-start: 1rem;
}
}
.dtr-bs-modal.modal {
.modal-body {
padding: 0;
.table {
margin-block-end: 0;
}
}
}
}
@media screen and (width <= 767.98px) {
div.dt-info {
padding-block: 0 $table-cell-padding-y;
}
}
div.dt-length,
div.dt-search {
margin-block: $spacer * 1.5;
}
div.dt-length select {
margin-inline: .5rem;
}
/* common style for light / dark */
div.dt-paging ul.pagination .page-link {
padding: $pagination-padding-y;
font-size: $font-size-base;
line-height: $pagination-line-height;
@include border-radius($border-radius);
}
@media screen and (width <= 575.98px) {
div.dt-paging ul.pagination .page-link {
font-size: $font-size-sm;
min-block-size:
calc(
#{"#{($font-size-sm * $pagination-line-height) + ($pagination-padding-y-sm * 2)} + calc(#{$pagination-border-width} * 2)"}
);
min-inline-size:
calc(
#{"#{($font-size-sm * $pagination-line-height) + ($pagination-padding-x-sm * 2.356)} + calc(#{$pagination-border-width} * 2)"}
);
padding-block: $pagination-padding-y-sm - .1055rem;
padding-inline: $pagination-padding-x-sm - .1055rem;
}
div.dt-paging ul.pagination {
.page-item {
.next,
.previous,
.first,
.last {
&.page-link {
padding: calc($pagination-padding-y-sm - .1055rem);
}
}
}
}
}
div.dt-info .select-info .select-item {
margin-inline: .5rem;
}
}
/* DataTable within card */
div.card-datatable {
padding-block-end: $card-spacer-x-sm;
div.dt-info {
color: var(--#{$prefix}secondary-color);
}
}
.table-bordered > :not(caption) > * > * {
border-width: 0;
}
/* overrides styles of library for rtl */
table.dataTable {
&,
thead,
tfoot {
th,
td {
&,
&.dt-type-numeric,
&.dt-type-date {
text-align: start;
}
&:first-child{
padding-inline: $card-spacer-x;
}
}
th:last-child{
padding-inline-end: $card-spacer-x-sm;
}
}
thead {
.dt-orderable-asc.dt-orderable-desc,
.dt-ordering-desc,
.dt-ordering-asc {
.dt-column-order {
inset-inline: auto 1em;
&::before,
&::after {
background-color: var(--#{$prefix}heading-color);
block-size: 1.125rem;
content: "";
inline-size: 1.125rem;
mask-repeat: no-repeat;
mask-size: 100% 100%;
visibility: hidden;
}
&::before {
mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath fill='currentColor' d='m6.293 13.293l1.414 1.414L12 10.414l4.293 4.293l1.414-1.414L12 7.586z'/%3E%3C/svg%3E");
}
&::after {
mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath fill='currentColor' d='M16.293 9.293L12 13.586L7.707 9.293l-1.414 1.414L12 16.414l5.707-5.707z'/%3E%3C/svg%3E");
}
}
&:hover {
.dt-column-order {
&::before,
&::after {
visibility: visible;
}
}
}
}
}
}
/* text align styles in modal */
.modal.dtr-bs-modal .text-xxl-center {
text-align: start !important;
}
/* Dark theme */
@if $enable-dark-mode {
@include color-mode(dark) {
div.dt-container table.dataTable tr.dt-hasChild td.dt-control::before {
border-color: rgba(var(--#{$prefix}white-rgb), .5);
}
}
}

View File

@@ -0,0 +1,27 @@
@import "../../scss/_bootstrap-extended/include";
@import "datatables.net-buttons-bs5/css/buttons.bootstrap5";
div.dt-container {
.dt-button-collection {
inline-size: auto;
}
div.dropdown-menu.dt-button-collection,
div.dt-button-collection .dt-button:not(.dt-btn-split-drop) {
min-inline-size: 8rem;
}
div.dropdown-menu.dt-button-collection .dt-button {
border-radius: $border-radius;
}
.dt-buttons {
&.btn-group {
.btn {
border-color: transparent;
}
&:not(.btn-group-vertical) > .btn-group:not(:last-child) > .btn,
&:not(.btn-group-vertical) > :not(.btn-check) + .btn {
@include border-radius($border-radius !important);
}
}
}
}

View File

@@ -0,0 +1,31 @@
@import "../../scss/_bootstrap-extended/include";
@import "datatables.net-fixedcolumns-bs5/css/fixedColumns.bootstrap5";
div.dt-container {
div.dt-scroll-body thead tr {
border-block-end-width: 0;
border-block-start-width: 0;
}
table.dataTable {
thead,
tbody {
tr > .dtfc-fixed-left,
tr > .dtfc-fixed-right {
background-color: var(--#{$prefix}paper-bg);
}
}
thead th {
text-align: center;
}
&.dtfc-scrolling-left tr > .dtfc-fixed-left,
&.dtfc-scrolling-right tr > .dtfc-fixed-right {
&::after {
box-shadow: none;
}
}
}
div.dt-scroll div.dtfc-top-blocker {
background-color: var(--#{$prefix}paper-bg);
}
}

View File

@@ -0,0 +1,36 @@
@import "../../scss/_bootstrap-extended/include";
@import "datatables.net-fixedheader-bs5/css/fixedHeader.bootstrap5";
/* Fixed header Style */
.dt-fixedheader {
&.table-bordered.table.dataTable {
&.fixedHeader-floating,
&.fixedHeader-locked {
thead > tr > th {
background-color: var(--#{$prefix}paper-bg);
}
}
}
&.dataTable.table-bordered thead tr th {
&:nth-child(2) {
border-inline-start-width: 0;
}
&:last-child {
border-inline-end: none;
:dir(rtl) & {
border-inline-start: none;
}
}
}
}
.dtfh-floatingparent-head {
border-block-end: 1px solid var(--#{$prefix}border-color);
> div {
padding: 0 !important;
}
.form-check-input {
block-size: $form-datatables-check-input-size;
inline-size: $form-datatables-check-input-size;
}
}

View File

@@ -0,0 +1,64 @@
@import "../../scss/_bootstrap-extended/include";
@import "datatables.net-responsive-bs5/css/responsive.bootstrap5";
/* Responsive table area '+' icon position */
table.dataTable {
&.dtr-column > tbody > tr {
&,
&.dtr-expanded {
& > td.control,
& > th.control {
position: relative;
&::before {
position: absolute;
box-sizing: content-box;
border: 2px solid var(--#{$prefix}paper-bg);
@include border-radius(1rem);
background-color: var(--#{$prefix}primary);
block-size: .85rem;
box-shadow: 0 0 3px var(--#{$prefix}gray-800);
color: var(--#{$prefix}white);
content: "+";
font-family: "Courier New", Courier, monospace;
font-weight: $font-weight-medium;
inline-size: .85rem;
inset-block-start: 50%;
inset-inline-start: 50%;
line-height: 1em;
text-align: center;
transform: translate(-50%, -51%);
}
}
}
}
&.table-responsive {
/* To scroll within datatable area */
@media screen and (width <= 1399.98px) {
display: block;
}
}
}
/* Modal table style */
.modal.dtr-bs-modal {
.modal-body {
padding: 0;
}
.table {
margin-block-end: 0;
tr:last-child > td {
border-block-end: 0;
}
.btn {
box-shadow: none !important;
}
.emp_name {
font-weight: $font-weight-medium;
}
}
.dropdown-item.text-danger:active {
color: var(--#{$prefix}primary) !important;
}
}

View File

@@ -0,0 +1,9 @@
@import "../../scss/_bootstrap-extended/include";
@import "datatables.net-rowgroup-bs5/css/rowGroup.bootstrap5";
table.table.dataTable > tbody > tr {
&.group,
&.group:hover {
background-color: var(--#{$prefix}gray-100);
}
}

View File

@@ -0,0 +1,2 @@
@import "../../scss/_bootstrap-extended/include";
@import "datatables.net-select-bs5/css/select.bootstrap5";

View File

@@ -0,0 +1,56 @@
import Dropzone from 'dropzone/dist/dropzone';
Dropzone.autoDiscover = false;
// File upload progress animation
Dropzone.prototype.uploadFiles = function (files) {
const minSteps = 6;
const maxSteps = 60;
const timeBetweenSteps = 100;
const bytesPerStep = 100000;
const isUploadSuccess = true;
const self = this;
for (let i = 0; i < files.length; i++) {
const file = files[i];
const totalSteps = Math.round(Math.min(maxSteps, Math.max(minSteps, file.size / bytesPerStep)));
for (let step = 0; step < totalSteps; step++) {
const duration = timeBetweenSteps * (step + 1);
setTimeout(
(function (file, totalSteps, step) {
return function () {
file.upload = {
progress: (100 * (step + 1)) / totalSteps,
total: file.size,
bytesSent: ((step + 1) * file.size) / totalSteps
};
self.emit('uploadprogress', file, file.upload.progress, file.upload.bytesSent);
if (file.upload.progress === 100) {
if (isUploadSuccess) {
file.status = Dropzone.SUCCESS;
self.emit('success', file, 'success', null);
} else {
file.status = Dropzone.ERROR;
self.emit('error', file, 'Some upload error', null);
}
self.emit('complete', file);
self.processQueue();
}
};
})(file, totalSteps, step),
duration
);
}
}
};
try {
window.Dropzone = Dropzone;
} catch (e) {}
export { Dropzone };

View File

@@ -0,0 +1,305 @@
/* Dropzone */
@import "../../scss/_bootstrap-extended/include";
$dz-box-padding: 1.25rem !default;
$dz-icon-size: 1.875rem !default;
$dz-thumbnail-width: 10rem !default;
$dz-thumbnail-height: 7.5rem !default;
$dz-preview-padding: .625rem !default;
$dz-progress-height: .5rem !default;
$dz-icon-block-size: 3.75rem !default;
$dz-overlay-bg: var(--#{$prefix}dark-rgb);
$dz-thumbnail-bg: var(--#{$prefix}gray-25);
$dz-border-color: var(--#{$prefix}border-color);
/* common styles */
.dropzone {
--#{$prefix}dz-icon-bg: #eeedf0;
position: relative;
border: 2px dashed $dz-border-color;
@include border-radius($border-radius-lg);
cursor: pointer;
inline-size: 100%;
/* Disabled */
&:not(.dz-clickable) {
cursor: not-allowed;
opacity: .5;
}
/* Hover */
&.dz-drag-hover {
border-style: solid;
border-color: var(--#{$prefix}primary);
.dz-message {
opacity: .5;
}
}
.dz-message {
color: var(--#{$prefix}heading-color);
font-size: $h4-font-size;
font-weight: $font-weight-medium;
margin-block: 8rem 3rem;
margin-inline: 0;
text-align: center;
.note {
display: block;
color: var(--#{$prefix}body-color);
font-size: $font-size-base;
font-weight: $font-weight-normal;
margin-block-start: .5rem;
}
&::before {
position: absolute;
display: inline-block;
@include border-radius(6px);
background: var(--#{$prefix}dz-icon-bg);
background-image:
str-replace(
str-replace($upload-icon, "currentColor", var(--#{$prefix}headings-color)),
"#",
"%23"
);
background-position: center;
background-repeat: no-repeat;
block-size: 40px;
content: "";
inline-size: 40px;
inset-block-start: 5rem;
inset-inline-start: calc(50% - 23px);
}
}
/* Fallback */
.dz-browser-not-supported {
&.dropzone-box {
padding: 0 !important;
border: none !important;
@include border-radius(0 !important);
cursor: default !important;
inline-size: auto !important;
min-block-size: auto !important;
transition: none;
}
.dz-message {
display: none !important;
}
}
/* Default message */
&.dz-started .dz-message {
display: none;
}
/* Preview */
.dz-preview {
position: relative;
box-sizing: content-box;
border: $card-border-width solid var(--#{$prefix}border-color);
@include border-radius($border-radius);
background: var(--#{$prefix}paper-bg);
box-shadow: var(--#{$prefix}box-shadow);
cursor: default;
font-size: .8125rem;
margin-block: calc(#{$dz-box-padding} - .25rem);
margin-inline: calc(#{$dz-box-padding} - .25rem) calc(#{$dz-box-padding} - 1rem);
@include media-breakpoint-up(sm) {
display: inline-block;
inline-size: $dz-thumbnail-width + ($dz-preview-padding * 2);
}
}
/* File information */
.dz-filename {
position: absolute;
overflow: hidden;
background: var(--#{$prefix}paper-bg);
inline-size: 100%;
padding-block: $dz-preview-padding 0;
padding-inline: $dz-preview-padding;
text-overflow: ellipsis;
white-space: nowrap;
&:hover {
text-overflow: inherit;
white-space: normal;
}
}
.dz-size {
color: var(--#{$prefix}secondary-color);
font-size: .6875rem;
font-style: italic;
padding-block: 1.875rem $dz-preview-padding;
padding-inline: $dz-preview-padding;
}
/* Progressbar */
.dz-preview .progress,
.dz-preview .progess-bar {
block-size: $dz-progress-height;
}
.dz-preview .progress {
position: absolute;
z-index: 30;
inset-block-start: 50%;
inset-inline: 1.3rem;
margin-block-start: -$dz-progress-height * .5;
}
.dz-complete .progress {
display: none;
}
/* Thumbnail */
.dz-thumbnail {
position: relative;
box-sizing: content-box;
padding: $dz-preview-padding;
background: $dz-thumbnail-bg;
block-size: $dz-thumbnail-height;
border-block-end: 1px solid var(--#{$prefix}border-color);
text-align: center;
> img,
.dz-nopreview {
position: relative;
display: block;
inset-block-start: 50%;
margin-block: 0;
margin-inline: auto;
transform: translateY(-50%) scale(1);
}
> img {
max-block-size: 100%;
max-inline-size: 100%;
}
@include border-top-radius(if($border-radius, calc(#{$border-radius} - 1px), 0));
@include media-breakpoint-up(sm) {
inline-size: $dz-thumbnail-width;
}
}
.dz-nopreview {
color: var(--#{$prefix}secondary-color);
font-size: .6875rem;
font-weight: $font-weight-medium;
text-transform: uppercase;
}
.dz-thumbnail img[src] ~ .dz-nopreview {
display: none;
}
/* Remove link */
.dz-remove {
display: block;
border-block-start: 1px solid var(--#{$prefix}border-color);
color: var(--#{$prefix}body-color);
font-size: .75rem;
padding-block: .375rem;
padding-inline: 0;
text-align: center;
&:hover,
&:focus {
background: rgba(var(--#{$prefix}base-color-rgb), .1);
border-block-start-color: transparent;
color: var(--#{$prefix}body-color);
text-decoration: none;
}
@include border-bottom-radius(if($border-radius, calc(#{$border-radius} - 1px), 0));
}
/* error/success states */
.dz-error-mark,
.dz-success-mark {
position: absolute;
display: none;
@include border-radius(50%);
background-color: rgba(var(--#{$prefix}dark-rgb), .5);
background-position: center center;
background-repeat: no-repeat;
background-size: $dz-icon-size $dz-icon-size;
block-size: $dz-icon-block-size;
box-shadow: 0 0 1.25rem rgba(var(--#{$prefix}pure-black), .06);
inline-size: $dz-icon-block-size;
inset-block-start: 50%;
inset-inline-start: 50%;
margin-block-start: -$dz-icon-block-size * .5;
margin-inline-start: -$dz-icon-block-size * .5;
}
.dz-success-mark {
background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%235cb85c' d='M2.3 6.73L.6 4.53c-.4-1.04.46-1.4 1.1-.8l1.1 1.4 3.4-3.8c.6-.63 1.6-.27 1.2.7l-4 4.6c-.43.5-.8.4-1.1.1z'/%3E%3C/svg%3E");
}
.dz-error-mark {
background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='%23d9534f' viewBox='-2 -2 7 7'%3E%3Cpath stroke='%23d9534f' d='M0 0l3 3m0-3L0 3'/%3E%3Ccircle r='.5'/%3E%3Ccircle cx='3' r='.5'/%3E%3Ccircle cy='3' r='.5'/%3E%3Ccircle cx='3' cy='3' r='.5'/%3E%3C/svg%3E");
}
.dz-error-message {
position: absolute;
z-index: 40;
display: none;
overflow: auto;
padding: .75rem;
background: rgba(var(--#{$prefix}danger-rgb), .8);
color: var(--#{$prefix}white);
font-weight: $font-weight-medium;
inset: -1px;
text-align: start;
@include border-top-radius($border-radius);
}
/* Error state */
.dz-error {
.dz-error-message {
display: none;
}
.dz-error-mark {
display: block;
}
&:hover {
.dz-error-message {
display: block;
}
.dz-error-mark {
display: none;
}
}
}
/* Success state */
.dz-success .dz-success-mark {
display: block;
}
}
/* ecommerce */
.app-ecommerce {
.dz-message {
margin-block-start: 5rem;
&::before {
inset-block-start: 3rem;
}
}
}
@if $enable-dark-mode {
@include color-mode(dark) {
.dropzone {
--#{$prefix}dz-icon-bg: #373b50;
}
}
}

View File

@@ -0,0 +1,7 @@
import flatpickr from 'flatpickr/dist/flatpickr';
try {
window.flatpickr = flatpickr;
} catch (e) {}
export { flatpickr };

View File

@@ -0,0 +1,610 @@
@import "../../scss/_bootstrap-extended/include";
@import "../../scss/_components/include";
$flatpickr-time-picker-height: 40px !default;
/* set position to open flat picker calendar */
.flatpickr-wrapper{
position: relative;
}
/* Animations */
@mixin keyframes($name) {
@keyframes #{$name} {
@content;
}
@keyframes #{$name} {
@content;
}
@keyframes #{$name} {
@content;
}
}
@include keyframes(fpFadeInDown) {
from {
opacity: 0;
transform: translate3d(0, -20px, 0);
}
to {
opacity: 1;
transform: translate3d(0, 0, 0);
}
}
.flatpickr-calendar {
position: absolute;
overflow: hidden;
box-sizing: border-box;
padding: $picker-padding;
animation: none;
background: $picker-bg;
box-shadow: $picker-box-shadow;
font-size: $font-size-base;
inline-size: $picker-width;
opacity: 0;
text-align: center;
visibility: hidden;
@include border-radius($picker-border-radius);
&.open,
&.inline {
opacity: 1;
visibility: visible;
}
&.open {
z-index: $picker-zindex;
}
&.animate.open {
animation: fpFadeInDown 300ms cubic-bezier(.23, 1, .32, 1);
}
&:not(.inline, .open) {
display: none;
}
&.inline {
position: relative;
inset-block-start: 2px;
}
/* below style required important to override default flatpickr element styles */
&.hasWeeks {
inline-size: $picker-width + $picker-cell-size !important;
}
&.hasTime .flatpickr-weeks {
border-block-end: 0;
border-end-end-radius: 0;
border-end-start-radius: 0;
margin-block-start: 1.125rem;
}
/* if hasTime with calendar */
&.hasTime {
padding-block-end: 0;
.flatpickr-time {
block-size: $flatpickr-time-picker-height;
}
&:not(.noCalendar) {
border-block-start: $picker-timer-border-width solid $picker-timer-border-color;
}
}
&.noCalendar.hasTime {
padding: 0;
}
/* To update arrows in number input of time picker */
input[type="number"]::-webkit-inner-spin-button,
input[type="number"]::-webkit-outer-spin-button {
margin: 0;
appearance: none;
}
/* flat picker month list */
.flatpickr-month {
position: relative;
overflow: hidden;
background: $picker-bg;
block-size: $picker-cell-size + .0375rem;
line-height: 1;
text-align: center;
user-select: none;
}
.flatpickr-prev-month,
.flatpickr-next-month {
position: absolute;
z-index: 3;
display: flex;
align-items: center;
justify-content: center;
background-color: $picker-arrow-bg;
block-size: $picker-arrow-wrapper-size;
cursor: pointer;
inline-size: $picker-arrow-wrapper-size;
inset-block-start: .75rem;
line-height: $picker-arrow-wrapper-size;
padding-block: 0;
padding-inline: .41rem;
text-decoration: none;
@include border-radius($picker-cell-border-radius);
svg {
fill: $picker-arrow-color;
inline-size: calc($picker-arrow-size + .15rem);
stroke: $picker-arrow-color;
stroke-width: 1;
vertical-align: middle;
}
:dir(rtl) & {
transform: scaleX(-1);
}
}
.flatpickr-prev-month i,
.flatpickr-next-month i {
position: relative;
}
.flatpickr-prev-month {
&.flatpickr-prev-month {
inset-inline-end: 3.6rem;
}
}
.flatpickr-next-month {
&.flatpickr-prev-month {
inset-inline: 0;
}
&.flatpickr-next-month {
inset-inline-end: 1rem;
}
}
.flatpickr-prev-month:hover,
.flatpickr-next-month:hover {
opacity: 1;
}
.flatpickr-prev-month svg path,
.flatpickr-next-month svg path {
fill: inherit;
@include transition(fill .1s);
}
/* flat picker input styles */
.numInputWrapper {
position: relative;
block-size: auto;
input,
span {
display: inline-block;
}
input {
inline-size: 100%;
}
span {
position: absolute;
inset-inline-end: 4px;
opacity: 0;
&:hover {
background: rgb(0 0 0 / 10%);
}
&:active {
background: rgb(0 0 0 / 20%);
}
&::after {
display: block;
block-size: 0;
content: "";
inline-size: 0;
}
&.arrowUp {
inset-block-start: 7px;
}
&.arrowUp::after {
border-block-end: 4px solid rgb(72 72 72 / 60%);
border-inline-end: 4px solid transparent;
border-inline-start: 4px solid transparent;
}
&.arrowDown {
inset-block-end: 7px;
}
&.arrowDown::after {
border-block-start: 4px solid rgb(72 72 72 / 60%);
border-inline-end: 4px solid transparent;
border-inline-start: 4px solid transparent;
}
svg {
block-size: auto;
inline-size: inherit;
}
svg path {
fill: rgb(255 255 255 / 50%);
}
}
&:hover {
background: rgb(0 0 0 / 5%);
}
&:hover span {
opacity: 1;
}
}
/* flat picker current month styles */
.flatpickr-current-month {
position: absolute;
display: flex;
align-items: center;
justify-content: start;
block-size: $picker-arrow-wrapper-size - .375;
color: $picker-header-color;
font-weight: 300;
gap: .25rem;
inline-size: 75%;
inset-inline-start: 3.5%;
line-height: 1;
padding-block: 1rem 0;
padding-inline: 0;
text-align: center;
transform: translate3d(0, 0, 0);
.cur-month{
font-size: $font-size-base;
font-weight: $font-weight-normal;
}
.flatpickr-monthDropdown-months,
input.cur-year {
display: inline-block;
box-sizing: border-box;
border: 0;
@include border-radius(0);
background: transparent;
color: inherit;
font-family: inherit;
font-size: inherit;
font-weight: $font-weight-normal;
line-height: inherit;
outline: none;
padding-block: 0;
vertical-align: middle;
}
.numInputWrapper {
display: inline-block;
inline-size: 6ch;
}
.flatpickr-monthDropdown-months {
position: relative;
appearance: menulist;
background-color: $picker-bg;
block-size: $picker-cell-size;
color: $picker-header-color;
cursor: pointer;
font-size: $font-size-lg;
inline-size: auto;
}
input.cur-year {
margin: 0;
block-size: $picker-cell-size - .5rem;
cursor: default;
&:focus {
outline: 0;
}
}
}
/* flat picker calendar weekdays styles */
.flatpickr-weekdays {
display: flex;
overflow: hidden;
align-items: center;
background: $picker-bg;
block-size: $picker-cell-size;
inline-size: 100%;
margin-block-end: .6875rem;
margin-block-start: .5rem;
max-inline-size: 17.5rem;
text-align: center;
.flatpickr-weekdaycontainer {
display: flex;
inline-size: 100%;
padding-block: calc($picker-cell-padding / 2);
}
span.flatpickr-weekday {
display: block;
flex: 1;
margin: 0;
background: $picker-bg;
color: $picker-header-color;
cursor: default;
font-size: $font-size-sm;
inline-size: $picker-cell-size;
line-height: 1;
text-align: center;
}
}
.dayContainer,
.flatpickr-weeks {
padding-block: 1px 0;
padding-inline: 0;
}
/* flat picker days styles */
.flatpickr-days {
position: relative;
display: flex;
overflow: hidden;
background: $picker-bg;
inline-size: auto;
&:focus {
outline: 0;
}
/* days wrapper/container */
.dayContainer {
display: inline-block;
display: flex;
box-sizing: border-box;
flex-wrap: wrap;
justify-content: space-around;
padding: 0;
inline-size: $picker-cell-size * 7;
max-inline-size: $picker-cell-size * 7;
min-inline-size: $picker-cell-size * 7;
opacity: 1;
outline: 0;
transform: translate3d(0, 0, 0);
}
/* day wise styling */
.flatpickr-day {
display: flex;
box-sizing: border-box;
align-items: center;
justify-content: center;
border: 1px solid transparent;
margin: 0;
background: none;
block-size: $picker-cell-size;
color: $picker-color;
cursor: pointer;
font-weight: $font-weight-normal;
inline-size: 15.2857%;
line-height: $picker-cell-size;
max-inline-size: $picker-cell-size;
text-align: center;
@include border-radius($picker-cell-border-radius);
&.today,
&.today:hover {
background-color: $picker-cell-today-bg;
color: $picker-cell-today-color;
}
&.inRange,
&.prevMonthDay.inRange,
&.nextMonthDay.inRange,
&.today.inRange,
&.prevMonthDay.today.inRange,
&.nextMonthDay.today.inRange,
&:hover,
&.prevMonthDay:hover,
&.nextMonthDay:hover,
&:focus,
&.prevMonthDay:focus,
&.nextMonthDay:focus {
cursor: pointer;
outline: 0;
}
/* hover & focus styles */
&:hover,
&.prevMonthDay:hover,
&.nextMonthDay:hover,
&:focus,
&.prevMonthDay:focus,
&.nextMonthDay:focus{
background-color: $picker-cell-hover-bg;
}
/* range styles */
&.inRange,
&.prevMonthDay.inRange,
&.nextMonthDay.inRange,
&.today.inRange,
&.prevMonthDay.today.inRange,
&.nextMonthDay.today.inRange{
background-color: $picker-range-active-bg;
color: $picker-range-active-color;
}
/* selected styles */
&.selected,
&.selected.inRange,
&.selected:focus,
&.selected:hover,
&.selected.nextMonthDay,
&.selected.prevMonthDay,
&.startRange,
&.startRange.inRange,
&.startRange:focus,
&.startRange:hover,
&.startRange.nextMonthDay,
&.startRange.prevMonthDay,
&.endRange,
&.endRange.inRange,
&.endRange:focus,
&.endRange:hover,
&.endRange.nextMonthDay,
&.endRange.prevMonthDay,
&.week.selected {
background-color: $picker-cell-active-bg;
box-shadow: $picker-cell-active-shadow;
color: $picker-cell-active-color;
}
&.inRange:not(.startRange, .endRange) {
@include border-radius(0);
}
/* disabled styles */
&.disabled,
&.flatpickr-disabled,
&.flatpickr-disabled.today,
&.disabled:hover,
&.flatpickr-disabled:hover,
&.flatpickr-disabled.today:hover {
border-color: transparent;
background: transparent;
cursor: default;
pointer-events: none;
}
&.prevMonthDay,
&.nextMonthDay {
border-color: transparent;
background: transparent;
color: $picker-disabled-color;
cursor: default;
}
&.flatpickr-disabled,
&.disabled{
color: $picker-disabled-color;
}
&.notAllowed,
&.notAllowed.prevMonthDay,
&.notAllowed.nextMonthDay {
border-color: transparent;
background: transparent;
cursor: default;
}
&.selected.startRange,
&.startRange.startRange,
&.endRange.startRange {
@include border-end-radius(0);
}
&.selected.endRange,
&.startRange.endRange,
&.endRange.endRange {
@include border-start-radius(0);
}
}
}
.flatpickr-weekwrapper {
display: inline-block;
margin-block-start: .5rem;
.flatpickr-weekday {
position: relative;
float: none;
inline-size: 100%;
inset-block-start: 1px;
line-height: $picker-cell-size;
}
/* Weekdays style for weeks */
span.flatpickr-day {
display: block;
background: none;
block-size: $picker-cell-size;
inline-size: $picker-cell-size;
max-inline-size: none;
}
}
.flatpickr-innerContainer {
display: flex;
overflow: hidden;
box-sizing: border-box;
.flatpickr-rContainer {
display: inline-block;
box-sizing: border-box;
padding: 0;
}
}
/* flat picker time styles */
.flatpickr-time {
display: flex;
line-height: $flatpickr-time-picker-height;
text-align: center;
.numInputWrapper {
flex: 1;
block-size: $flatpickr-time-picker-height;
float: inline-start;
inline-size: 40%;
}
&.hasSeconds .numInputWrapper {
inline-size: 26%;
}
&.time24hr .numInputWrapper {
inline-size: 49%;
}
input {
position: relative;
box-sizing: border-box;
padding: 0;
border: 0;
@include border-radius(0);
margin: 0;
background: transparent;
block-size: inherit;
box-shadow: none;
cursor: pointer;
font-size: $font-size-base;
line-height: inherit;
text-align: center;
&:focus {
border: 0;
outline: 0;
}
}
.flatpickr-am-pm {
cursor: pointer;
inline-size: 18%;
&:hover {
background: rgb(0 0 0 / 5%);
}
}
}
}

View File

@@ -0,0 +1,22 @@
import { Calendar } from '@fullcalendar/core';
import dayGridPlugin from '@fullcalendar/daygrid';
import interactionPlugin from '@fullcalendar/interaction';
import listPlugin from '@fullcalendar/list';
import timegridPlugin from '@fullcalendar/timegrid';
const calendarPlugins = {
dayGrid: dayGridPlugin,
interaction: interactionPlugin,
list: listPlugin,
timeGrid: timegridPlugin
};
try {
window.Calendar = Calendar;
window.dayGridPlugin = dayGridPlugin;
window.interactionPlugin = interactionPlugin;
window.listPlugin = listPlugin;
window.timegridPlugin = timegridPlugin;
} catch (e) {}
export { Calendar, dayGridPlugin, interactionPlugin, listPlugin, timegridPlugin };

View File

@@ -0,0 +1,386 @@
@import "../../scss/_bootstrap-extended/include";
$fullcalendar-event-padding-y: .25rem !default;
$fullcalendar-event-padding-x: .75rem !default;
$fullcalendar-event-margin-top: .625rem !default;
$fullcalendar-event-font-size: $font-size-base !default;
$fullcalendar-event-font-weight: $font-weight-normal !default;
$fullcalendar-toolbar-btn-padding: $btn-padding-y + .0038 $input-btn-padding-x !default;
$fullcalendar-fc-popover-z-index: 1090 !default;
$fullcalendar-event-border-radius: $border-radius-sm !default;
/* Calendar */
.fc {
--fc-neutral-bg-color: color-mix(in sRGB, var(--#{$prefix}base-color) 6%, var(--#{$prefix}card-bg));
--fc-today-bg-color: color-mix(in sRGB, var(--#{$prefix}base-color) 6%, var(--#{$prefix}card-bg));
--fc-border-color: var(--#{$prefix}border-color);
.private-event {
.fc-event-time,
.fc-event-title {
color: var(--#{$prefix}danger);
}
}
.fc-scrollgrid-section {
block-size: 0;
}
a[data-navlink]:hover {
text-decoration: none;
}
.fc-timegrid-slot {
block-size: 4em;
}
.fc-timeGridWeek-view {
.fc-timegrid-slot-minor {
border-block-start-style: none;
}
}
.fc-timeGridDay-view {
.fc-timegrid-slot-minor {
border-block-start-style: solid;
}
}
.fc-col-header-cell-cushion {
color: var(--#{$prefix}heading-color);
padding-block: 8.7px;
}
.fc-toolbar {
flex-wrap: wrap;
.fc-prev-button,
.fc-next-button {
display: inline-block;
border-color: transparent;
background-color: transparent;
.fc-icon {
color: var(--#{$prefix}heading-color);
}
&:hover,
&:active,
&:focus {
border-color: transparent;
background-color: transparent;
box-shadow: none !important;
}
}
.fc-button {
@include border-radius($border-radius);
font-weight: $font-weight-medium;
&:not(.fc-next-button):not(.fc-prev-button) {
padding: $fullcalendar-toolbar-btn-padding;
border-block-width: 0;
&:active,
&:focus {
box-shadow: none;
}
&:first-child {
border-inline-start: 0;
}
&:last-child {
border-inline-end: 0;
}
}
}
> * > :not(:first-child) {
margin-inline-start: 0;
}
.fc-toolbar-chunk {
display: flex;
align-items: center;
}
.fc-button-group {
.fc-button {
text-transform: capitalize;
}
& + div {
display: flex;
flex-wrap: wrap;
align-items: center;
}
}
.fc--button:empty,
.fc-toolbar-chunk:empty {
display: none;
}
.fc-sidebarToggle-button + div {
margin-inline-start: 0;
}
}
table.fc-scrollgrid {
.fc-col-header {
.fc-col-header-cell {
border-inline-start: none;
}
}
}
.fc-view-harness {
margin-block: 0;
margin-inline: -1.5rem;
min-block-size: 650px;
.fc-daygrid-body {
.fc-daygrid-day {
.fc-daygrid-day-top {
flex-direction: row;
.fc-daygrid-day-number {
padding: .5rem;
}
}
.fc-daygrid-day-bottom .fc-daygrid-more-link {
margin-block-start: .625rem;
}
}
}
.fc-event {
border: 0;
@include border-radius($fullcalendar-event-border-radius);
font-size: $fullcalendar-event-font-size;
font-weight: $fullcalendar-event-font-weight;
padding-block: $fullcalendar-event-padding-y;
padding-inline: $fullcalendar-event-padding-x;
.fc-event-title {
font-weight: $font-weight-medium;
}
}
.fc-daygrid-event-harness {
/*
! week & day events are using this style for all day only, not for other events */
.fc-event {
&.private-event {
border-color: transparent !important;
background-color: transparent !important;
}
}
}
.fc-event .fc-daygrid-event-dot {
display: none;
}
.fc-timegrid-event .fc-event-time {
font-size: .6875rem;
}
.fc-v-event .fc-event-title {
font-size: $fullcalendar-event-font-size;
font-weight: $fullcalendar-event-font-weight;
padding-block-start: .2rem;
}
.fc-timegrid-event .fc-event-main {
padding-block: $fullcalendar-event-padding-y 0;
padding-inline: $fullcalendar-event-padding-x;
}
}
.fc-daygrid-day-events {
.fc-event,
.fc-more-link {
margin-inline: .5rem;
}
@include media-breakpoint-down(md) {
.fc-daygrid-day-bottom {
overflow: hidden;
white-space: nowrap;
}
.fc-more-link {
margin-inline: 0;
}
}
}
/* To fix firefox thead border issue */
.fc-day-today {
background-clip: padding-box;
&:not(.fc-col-header-cell) {
.fc-popover-body {
background-color: var(--#{$prefix}paper-bg);
}
}
}
.fc-divider {
border-color: var(--#{$prefix}border-color);
background: var(--#{$prefix}border-color);
}
.fc-day-disabled {
--fc-neutral-bg-color: color-mix(in sRGB, var(--#{$prefix}base-color) 16%, var(--#{$prefix}card-bg));
}
/* To overwrite white color of event text */
.fc-h-event .fc-event-main,
.fc-v-event .fc-event-main {
color: inherit;
}
.fc-daygrid-block-event .fc-event-time,
.fc-daygrid-dot-event .fc-event-title {
font-weight: $fullcalendar-event-font-weight;
}
.fc-daygrid-body-natural {
.fc-daygrid-day-events {
margin-block: .94rem;
}
}
.fc-daygrid-event-harness + .fc-daygrid-event-harness .fc-daygrid-event {
margin-block-start: $fullcalendar-event-margin-top;
}
.fc-timegrid {
.fc-timegrid-divider {
display: none;
}
.fc-timegrid-event {
@include border-radius(0);
box-shadow: none;
padding-block-start: $fullcalendar-event-padding-x;
@include media-breakpoint-down(md) {
overflow: hidden;
white-space: nowrap;
}
.fc-event-time {
font-size: inherit;
}
}
}
.fc-daygrid-event-harness-abs .fc-event {
margin-block-end: .625rem;
}
.fc-timegrid-slot-label-frame {
text-align: center;
}
.fc-timegrid-axis-cushion,
.fc-timegrid-slot-label-cushion {
font-size: $font-size-sm;
}
.fc-timegrid-axis-cushion {
color: var(--#{$prefix}secondary-color);
padding-block: .5rem;
padding-inline: .4375rem;
text-transform: capitalize;
}
.fc-timegrid-slot-label-cushion {
padding: $fullcalendar-event-padding-x;
color: var(--#{$prefix}heading-color);
text-transform: uppercase;
}
.fc-list-day-cushion,
.fc-list-table td {
padding-inline: 1rem;
}
.fc-list-day-cushion {
padding-block: .5125rem;
}
.fc-popover {
z-index: $fullcalendar-fc-popover-z-index;
border: 0;
background-color: var(--#{$prefix}paper-bg);
.fc-popover-header {
padding: .566rem;
background-color: var(--#{$prefix}body-bg);
}
}
.fc-list {
.fc-list-table {
border-block-end: 1px solid;
th {
border: 0;
background: var(--#{$prefix}body-bg);
color: var(--#{$prefix}heading-color);
}
.fc-list-event {
background-color: transparent !important;
cursor: pointer;
td {
color: var(--#{$prefix}body-color);
}
&:hover {
td {
background-color: color-mix(in sRGB, var(--#{$prefix}base-color) 1.5%, var(--#{$prefix}paper-bg));
}
.fc-list-day {
th {
color: $headings-color;
}
}
tbody > tr:first-child th {
border-block-start: 1px solid $border-color;
}
}
}
tbody > tr:first-child th {
border-block-start: 1px solid var(--#{$prefix}border-color);
}
/* FC day */
.fc-timegrid-axis-cushion.fc-scrollgrid-shrink-cushion {
color: var(--#{$prefix}body-secondary-color);
}
/* FC table list disabled bg */
.fc-day-disabled {
background-color: rgba(var(--#{$prefix}base-color), .16);
}
.fc-day-other {
.fc-daygrid-day-top {
color: var(--#{$prefix}body-secondary-color);
}
}
}
.fc-list-empty {
background-color: var(--#{$prefix}body-bg);
}
}
&.fc-theme-standard {
.fc-list {
border: none;
}
}
.fc-day-other {
.fc-daygrid-day-top {
color: var(--#{$prefix}secondary-color);
opacity: 1;
}
}
}
/* Media Queries */
@include media-breakpoint-down(sm) {
.fc {
.fc-header-toolbar {
.fc-toolbar-chunk + .fc-toolbar-chunk {
margin-block-start: 1rem;
}
}
}
}
/* scss-docs-start calendar-modifiers */
/* Generate contextual modifier classes for colorizing the calendar */
@each $state in map-keys($theme-colors) {
.app-calendar-wrapper {
.bg-label-#{$state} {
.fc-list-event-dot {
--fc-event-border-color: var(--#{$prefix}#{$state});
}
}
.fc-button-#{$state}:not(.fc-prev-button):not(.fc-next-button) {
--fc-button-bg-color: color-mix(in sRGB, var(--#{$prefix}paper-bg) #{$btn-label-tint-amount}, var(--#{$prefix}#{$state}));
--fc-button-border-color: color-mix(in sRGB, var(--#{$prefix}paper-bg) 68%, var(--#{$prefix}#{$state}));
--fc-button-text-color: var(--#{$prefix}#{$state});
--fc-button-active-bg-color: color-mix(in sRGB, var(--#{$prefix}paper-bg) #{$btn-label-active-shade-amount}, var(--#{$prefix}#{$state}));
--fc-button-active-border-color: color-mix(in sRGB, var(--#{$prefix}paper-bg) 68%, var(--#{$prefix}#{$state}));
--fc-button-hover-bg-color: color-mix(in sRGB, var(--#{$prefix}paper-bg) #{$btn-label-active-shade-amount}, var(--#{$prefix}#{$state}));
--fc-button-hover-border-color: color-mix(in sRGB, var(--#{$prefix}paper-bg) 68%, var(--#{$prefix}#{$state}));
&:hover,
&.fc-button-active {
--fc-button-text-color: var(--#{$prefix}#{$state});
}
}
}
}
/* scss-docs-end calendar-modifiers */

View File

@@ -0,0 +1 @@
import 'hammerjs/hammer.js';

View File

@@ -0,0 +1 @@
@import "highlight.js/styles/github.css";

View File

@@ -0,0 +1,7 @@
import hljs from 'highlight.js';
try {
window.hljs = hljs;
} catch (e) {}
export { hljs };

View File

@@ -0,0 +1,2 @@
@import "highlight.js/styles/atom-one-light";
@import "highlight.js/styles/atom-one-dark";

View File

@@ -0,0 +1,5 @@
import i18next from 'i18next';
import i18NextHttpBackend from 'i18next-http-backend';
import languageDetector from 'i18next-browser-languagedetector';
export { i18next, i18NextHttpBackend, languageDetector };

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