Ajout de HelloFresh
This commit is contained in:
4
.editorconfig
Normal file
4
.editorconfig
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
[*.cs]
|
||||||
|
|
||||||
|
# CS8600: Conversion de littéral ayant une valeur null ou d'une éventuelle valeur null en type non-nullable.
|
||||||
|
dotnet_diagnostic.CS8600.severity = silent
|
||||||
185
Controllers/AccountController.cs
Normal file
185
Controllers/AccountController.cs
Normal file
@@ -0,0 +1,185 @@
|
|||||||
|
using System.Security.Claims;
|
||||||
|
using Microsoft.AspNetCore.Authentication;
|
||||||
|
using Microsoft.AspNetCore.Authentication.Cookies;
|
||||||
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
using Microsoft.AspNetCore.Identity;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using administration.Models.Finances;
|
||||||
|
using administration.Models;
|
||||||
|
using User = administration.Models.User;
|
||||||
|
|
||||||
|
public class AccountController : Controller
|
||||||
|
{
|
||||||
|
private readonly LayoutDataContext _db;
|
||||||
|
private readonly IPasswordHasher<User> _hasher;
|
||||||
|
|
||||||
|
public AccountController(LayoutDataContext db, IPasswordHasher<User> hasher)
|
||||||
|
{
|
||||||
|
_db = db;
|
||||||
|
_hasher = hasher;
|
||||||
|
}
|
||||||
|
|
||||||
|
// GET /Account/Login
|
||||||
|
[HttpGet]
|
||||||
|
public IActionResult Login(string? returnUrl = null)
|
||||||
|
{
|
||||||
|
ViewBag.ReturnUrl = returnUrl;
|
||||||
|
return View();
|
||||||
|
}
|
||||||
|
|
||||||
|
// POST /Account/Login
|
||||||
|
[HttpPost, ValidateAntiForgeryToken]
|
||||||
|
public async Task<IActionResult> Login(string username, string password, string? returnUrl = null)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrWhiteSpace(username) || string.IsNullOrWhiteSpace(password))
|
||||||
|
{
|
||||||
|
ModelState.AddModelError("", "Identifiants requis.");
|
||||||
|
return View();
|
||||||
|
}
|
||||||
|
|
||||||
|
var user = await _db.Users.FirstOrDefaultAsync(u => u.Username == username);
|
||||||
|
if (user == null)
|
||||||
|
{
|
||||||
|
ModelState.AddModelError("", "Identifiants invalides.");
|
||||||
|
return View();
|
||||||
|
}
|
||||||
|
|
||||||
|
var verify = _hasher.VerifyHashedPassword(user, user.PasswordHash, password);
|
||||||
|
if (verify == PasswordVerificationResult.Failed)
|
||||||
|
{
|
||||||
|
ModelState.AddModelError("", "Identifiants invalides.");
|
||||||
|
return View();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Claims pour cookie d’auth
|
||||||
|
var claims = new List<Claim>
|
||||||
|
{
|
||||||
|
new Claim(ClaimTypes.NameIdentifier, user.Id.ToString()),
|
||||||
|
new Claim(ClaimTypes.Name, user.Username)
|
||||||
|
};
|
||||||
|
var identity = new ClaimsIdentity(claims, CookieAuthenticationDefaults.AuthenticationScheme);
|
||||||
|
var principal = new ClaimsPrincipal(identity);
|
||||||
|
|
||||||
|
await HttpContext.SignInAsync(CookieAuthenticationDefaults.AuthenticationScheme, principal);
|
||||||
|
|
||||||
|
// Compatibilité avec ton code existant
|
||||||
|
HttpContext.Session.SetInt32("UserId", user.Id);
|
||||||
|
|
||||||
|
if (!string.IsNullOrWhiteSpace(returnUrl) && Url.IsLocalUrl(returnUrl))
|
||||||
|
return Redirect(returnUrl);
|
||||||
|
|
||||||
|
return RedirectToAction("Index", "Home");
|
||||||
|
}
|
||||||
|
|
||||||
|
// POST /Account/Logout
|
||||||
|
[HttpPost, ValidateAntiForgeryToken]
|
||||||
|
public async Task<IActionResult> Logout()
|
||||||
|
{
|
||||||
|
await HttpContext.SignOutAsync();
|
||||||
|
HttpContext.Session.Clear();
|
||||||
|
return RedirectToAction("Login");
|
||||||
|
}
|
||||||
|
|
||||||
|
// GET /Account/ForgotPassword
|
||||||
|
[HttpGet]
|
||||||
|
public IActionResult ForgotPassword() => View();
|
||||||
|
|
||||||
|
// POST /Account/ForgotPassword
|
||||||
|
[HttpPost, ValidateAntiForgeryToken]
|
||||||
|
public async Task<IActionResult> ForgotPassword(string usernameOrEmail)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrWhiteSpace(usernameOrEmail))
|
||||||
|
{
|
||||||
|
ModelState.AddModelError("", "Champ requis.");
|
||||||
|
return View();
|
||||||
|
}
|
||||||
|
|
||||||
|
var user = await _db.Users
|
||||||
|
.FirstOrDefaultAsync(u => u.Username == usernameOrEmail);
|
||||||
|
|
||||||
|
// Par sécurité, on ne révèle pas si l’utilisateur existe
|
||||||
|
if (user != null)
|
||||||
|
{
|
||||||
|
// Génère un token simple (tu peux le hasher si tu veux)
|
||||||
|
var token = Convert.ToBase64String(Guid.NewGuid().ToByteArray())
|
||||||
|
.Replace("+", "-").Replace("/", "_").TrimEnd('=');
|
||||||
|
|
||||||
|
user.ResetToken = token;
|
||||||
|
user.ResetTokenExpiresAt = DateTimeOffset.UtcNow.AddHours(1);
|
||||||
|
await _db.SaveChangesAsync();
|
||||||
|
|
||||||
|
var resetUrl = Url.Action("ResetPassword", "Account", new { token = token }, Request.Scheme);
|
||||||
|
// TODO: envoyer resetUrl par email.
|
||||||
|
// Temporaire : on l’affiche
|
||||||
|
TempData["ResetLink"] = resetUrl;
|
||||||
|
}
|
||||||
|
|
||||||
|
TempData["Info"] = "Si un compte existe, un lien de réinitialisation a été envoyé.";
|
||||||
|
return RedirectToAction("ForgotPassword");
|
||||||
|
}
|
||||||
|
|
||||||
|
// GET /Account/ResetPassword?token=...
|
||||||
|
[HttpGet]
|
||||||
|
public async Task<IActionResult> ResetPassword(string token)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrWhiteSpace(token)) return RedirectToAction("Login");
|
||||||
|
|
||||||
|
var user = await _db.Users.FirstOrDefaultAsync(u =>
|
||||||
|
u.ResetToken == token && u.ResetTokenExpiresAt > DateTimeOffset.UtcNow);
|
||||||
|
|
||||||
|
if (user == null)
|
||||||
|
{
|
||||||
|
TempData["Error"] = "Lien invalide ou expiré.";
|
||||||
|
return RedirectToAction("ForgotPassword");
|
||||||
|
}
|
||||||
|
|
||||||
|
ViewBag.Token = token;
|
||||||
|
return View();
|
||||||
|
}
|
||||||
|
|
||||||
|
// POST /Account/ResetPassword
|
||||||
|
[HttpPost, ValidateAntiForgeryToken]
|
||||||
|
public async Task<IActionResult> ResetPassword(string token, string newPassword, string confirmPassword)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrWhiteSpace(token))
|
||||||
|
{
|
||||||
|
TempData["Error"] = "Token manquant.";
|
||||||
|
return RedirectToAction("ForgotPassword");
|
||||||
|
}
|
||||||
|
if (string.IsNullOrWhiteSpace(newPassword) || newPassword != confirmPassword)
|
||||||
|
{
|
||||||
|
ModelState.AddModelError("", "Les mots de passe ne correspondent pas.");
|
||||||
|
ViewBag.Token = token;
|
||||||
|
return View();
|
||||||
|
}
|
||||||
|
|
||||||
|
var user = await _db.Users.FirstOrDefaultAsync(u =>
|
||||||
|
u.ResetToken == token && u.ResetTokenExpiresAt > DateTimeOffset.UtcNow);
|
||||||
|
|
||||||
|
if (user == null)
|
||||||
|
{
|
||||||
|
TempData["Error"] = "Lien invalide ou expiré.";
|
||||||
|
return RedirectToAction("ForgotPassword");
|
||||||
|
}
|
||||||
|
|
||||||
|
user.PasswordHash = _hasher.HashPassword(user, newPassword);
|
||||||
|
user.ResetToken = null;
|
||||||
|
user.ResetTokenExpiresAt = null;
|
||||||
|
await _db.SaveChangesAsync();
|
||||||
|
|
||||||
|
TempData["Ok"] = "Mot de passe réinitialisé. Connecte-toi.";
|
||||||
|
return RedirectToAction("Login");
|
||||||
|
}
|
||||||
|
|
||||||
|
// (Optionnel) création rapide d’un compte admin si tu n’as rien en BDD
|
||||||
|
[HttpPost, ValidateAntiForgeryToken]
|
||||||
|
public async Task<IActionResult> SeedAdmin(string username = "admin", string password = "ChangeMe!123")
|
||||||
|
{
|
||||||
|
if (await _db.Users.AnyAsync()) return BadRequest("Déjà des utilisateurs en BDD.");
|
||||||
|
var u = new User { Username = username };
|
||||||
|
u.PasswordHash = _hasher.HashPassword(u, password);
|
||||||
|
_db.Users.Add(u);
|
||||||
|
await _db.SaveChangesAsync();
|
||||||
|
return Ok("Admin créé.");
|
||||||
|
}
|
||||||
|
}
|
||||||
16
Controllers/AppController.cs
Normal file
16
Controllers/AppController.cs
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
using Microsoft.AspNetCore.Mvc.Filters;
|
||||||
|
|
||||||
|
public abstract class AppController : Controller
|
||||||
|
{
|
||||||
|
public override void OnActionExecuting(ActionExecutingContext context)
|
||||||
|
{
|
||||||
|
var uid = HttpContext.Session.GetInt32("UserId");
|
||||||
|
var uname = HttpContext.Session.GetString("UserName");
|
||||||
|
|
||||||
|
ViewBag.UserId = uid;
|
||||||
|
ViewBag.UserName = uname;
|
||||||
|
|
||||||
|
base.OnActionExecuting(context);
|
||||||
|
}
|
||||||
|
}
|
||||||
108
Controllers/ConnectionsController.cs
Normal file
108
Controllers/ConnectionsController.cs
Normal file
@@ -0,0 +1,108 @@
|
|||||||
|
using System.Security.Claims;
|
||||||
|
using administration.Models;
|
||||||
|
using Microsoft.AspNetCore.Authentication;
|
||||||
|
using Microsoft.AspNetCore.Authentication.Cookies;
|
||||||
|
using Microsoft.AspNetCore.Authorization;
|
||||||
|
using Microsoft.AspNetCore.Identity;
|
||||||
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
|
||||||
|
namespace administration.Controllers
|
||||||
|
{
|
||||||
|
public class ConnectionsController : Controller
|
||||||
|
{
|
||||||
|
private readonly LayoutDataContext _db;
|
||||||
|
private readonly IPasswordHasher<User> _hasher;
|
||||||
|
|
||||||
|
public ConnectionsController(LayoutDataContext db, IPasswordHasher<User> hasher)
|
||||||
|
{
|
||||||
|
_db = db;
|
||||||
|
_hasher = hasher;
|
||||||
|
}
|
||||||
|
|
||||||
|
// --- PAGE DE LOGIN ---
|
||||||
|
[HttpGet]
|
||||||
|
[AllowAnonymous]
|
||||||
|
public IActionResult Login() => View();
|
||||||
|
|
||||||
|
[HttpPost]
|
||||||
|
[AllowAnonymous]
|
||||||
|
[ValidateAntiForgeryToken]
|
||||||
|
public async Task<IActionResult> Login(string username, string password, string? returnUrl = null)
|
||||||
|
{
|
||||||
|
// 1) Recherche de l'utilisateur
|
||||||
|
var user = _db.Users.FirstOrDefault(u => u.Username == username);
|
||||||
|
if (user == null)
|
||||||
|
{
|
||||||
|
ViewBag.Error = "Nom d’utilisateur ou mot de passe incorrect.";
|
||||||
|
return View();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2) Vérification du mot de passe
|
||||||
|
var verification = _hasher.VerifyHashedPassword(user, user.PasswordHash ?? "", password);
|
||||||
|
if (verification != PasswordVerificationResult.Success &&
|
||||||
|
verification != PasswordVerificationResult.SuccessRehashNeeded)
|
||||||
|
{
|
||||||
|
ViewBag.Error = "Nom d’utilisateur ou mot de passe incorrect.";
|
||||||
|
return View();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3) Si rehash nécessaire → on sauvegarde
|
||||||
|
if (verification == PasswordVerificationResult.SuccessRehashNeeded)
|
||||||
|
{
|
||||||
|
user.PasswordHash = _hasher.HashPassword(user, password);
|
||||||
|
_db.SaveChanges();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 4) Sauvegarde dans la session (si besoin pour ton code existant)
|
||||||
|
HttpContext.Session.SetInt32("UserId", user.Id);
|
||||||
|
HttpContext.Session.SetString("UserName", user.Username);
|
||||||
|
|
||||||
|
// 5) Création du cookie d'authentification
|
||||||
|
var claims = new[]
|
||||||
|
{
|
||||||
|
new Claim(ClaimTypes.NameIdentifier, user.Id.ToString()),
|
||||||
|
new Claim(ClaimTypes.Name, user.Username)
|
||||||
|
};
|
||||||
|
var identity = new ClaimsIdentity(claims, CookieAuthenticationDefaults.AuthenticationScheme);
|
||||||
|
await HttpContext.SignInAsync(
|
||||||
|
CookieAuthenticationDefaults.AuthenticationScheme,
|
||||||
|
new ClaimsPrincipal(identity));
|
||||||
|
|
||||||
|
// 6) Redirection sécurisée
|
||||||
|
if (!string.IsNullOrWhiteSpace(returnUrl) &&
|
||||||
|
Url.IsLocalUrl(returnUrl) &&
|
||||||
|
!returnUrl.Contains("/Connections/Login", StringComparison.OrdinalIgnoreCase))
|
||||||
|
{
|
||||||
|
return LocalRedirect(returnUrl);
|
||||||
|
}
|
||||||
|
|
||||||
|
return RedirectToAction("Index", "Home");
|
||||||
|
}
|
||||||
|
|
||||||
|
// --- DECONNEXION ---
|
||||||
|
[HttpPost]
|
||||||
|
[ValidateAntiForgeryToken]
|
||||||
|
public async Task<IActionResult> Logout()
|
||||||
|
{
|
||||||
|
await HttpContext.SignOutAsync(); // supprime le cookie
|
||||||
|
HttpContext.Session.Clear(); // vide la session
|
||||||
|
return RedirectToAction("Login", "Connections");
|
||||||
|
}
|
||||||
|
|
||||||
|
// --- MISE À JOUR DU MOT DE PASSE ---
|
||||||
|
// ⚠️ On met [Authorize] pour éviter un accès public
|
||||||
|
[HttpPost]
|
||||||
|
[Authorize]
|
||||||
|
public IActionResult SetPassword(string username, string newPassword)
|
||||||
|
{
|
||||||
|
var user = _db.Users.FirstOrDefault(u => u.Username == username);
|
||||||
|
if (user == null)
|
||||||
|
return Content("❌ Utilisateur introuvable");
|
||||||
|
|
||||||
|
user.PasswordHash = _hasher.HashPassword(user, newPassword);
|
||||||
|
_db.SaveChanges();
|
||||||
|
|
||||||
|
return Content("✅ Mot de passe mis à jour avec succès");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,10 +1,10 @@
|
|||||||
|
using administration.Models.Finances;
|
||||||
using administration.Models;
|
|
||||||
using administration.Services;
|
using administration.Services;
|
||||||
|
using Microsoft.AspNetCore.Authorization;
|
||||||
using Microsoft.AspNetCore.Http;
|
using Microsoft.AspNetCore.Http;
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
|
||||||
namespace administration.Controllers
|
namespace administration.Controllers.Finances
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Contrôleur API pour la gestion des dépenses de l'utilisateur.
|
/// Contrôleur API pour la gestion des dépenses de l'utilisateur.
|
||||||
@@ -13,6 +13,7 @@ namespace administration.Controllers
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
[ApiController]
|
[ApiController]
|
||||||
[Route("api/[controller]")]
|
[Route("api/[controller]")]
|
||||||
|
[Authorize]
|
||||||
public class ExpenseController : Controller
|
public class ExpenseController : Controller
|
||||||
{
|
{
|
||||||
private readonly FinancesContext _context;
|
private readonly FinancesContext _context;
|
||||||
@@ -112,6 +113,29 @@ namespace administration.Controllers
|
|||||||
return StatusCode(500, $"Erreur serveur : {ex.Message}, Méthode GetAdditionalRevenues");
|
return StatusCode(500, $"Erreur serveur : {ex.Message}, Méthode GetAdditionalRevenues");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Récupère les dépenses depuis la base de données avec l'id X.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="rows">L'id de la dépense</param>
|
||||||
|
/// <returns>La bonne dépense</returns>
|
||||||
|
[HttpGet("expense_by_id")]
|
||||||
|
public IActionResult GetExpenseByID(int id)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Expense expense = _context.Expenses
|
||||||
|
.Where(r => r.Id == id)
|
||||||
|
.FirstOrDefault();
|
||||||
|
|
||||||
|
return Ok(expense);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
return StatusCode(500, $"Erreur serveur : {ex.Message}, Méthode GetRevenueByID");
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1,17 +1,21 @@
|
|||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
using administration.Models;
|
|
||||||
using administration.Services;
|
using administration.Services;
|
||||||
|
using administration.Models.Finances;
|
||||||
|
using Microsoft.AspNetCore.Authorization;
|
||||||
|
|
||||||
namespace administration.Controllers
|
namespace administration.Controllers.Finances
|
||||||
{
|
{
|
||||||
[ApiController]
|
[Authorize]
|
||||||
[Route("api/[controller]")]
|
public class FinancesController : Controller
|
||||||
public class RevenueController : ControllerBase
|
|
||||||
{
|
{
|
||||||
|
public IActionResult Index()
|
||||||
|
{
|
||||||
|
return View();
|
||||||
|
}
|
||||||
private readonly FinancesContext _context;
|
private readonly FinancesContext _context;
|
||||||
private readonly IUserSessionService _userSession;
|
private readonly IUserSessionService _userSession;
|
||||||
|
|
||||||
public RevenueController(FinancesContext context, IUserSessionService userSession)
|
public FinancesController(FinancesContext context, IUserSessionService userSession)
|
||||||
{
|
{
|
||||||
_context = context;
|
_context = context;
|
||||||
_userSession = userSession;
|
_userSession = userSession;
|
||||||
@@ -122,5 +126,28 @@ namespace administration.Controllers
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Récupère les revenues depuis la base de données avec l'id X.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="rows">L'id du revenue</param>
|
||||||
|
/// <returns>Le bon revenue</returns>
|
||||||
|
[HttpGet("revenues_by_id")]
|
||||||
|
public IActionResult GetRevenueByID(int id)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Revenue revenue = _context.Revenues
|
||||||
|
.Where(r => r.Id == id)
|
||||||
|
.FirstOrDefault();
|
||||||
|
|
||||||
|
return Ok(revenue);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
return StatusCode(500, $"Erreur serveur : {ex.Message}, Méthode GetRevenueByID");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
1109
Controllers/HelloFresh/HelloFreshController.cs
Normal file
1109
Controllers/HelloFresh/HelloFreshController.cs
Normal file
File diff suppressed because it is too large
Load Diff
138
Controllers/HelloFresh/HelloFreshScraperService.cs
Normal file
138
Controllers/HelloFresh/HelloFreshScraperService.cs
Normal file
@@ -0,0 +1,138 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Net.Http;
|
||||||
|
using System.Text.RegularExpressions;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using AngleSharp;
|
||||||
|
using AngleSharp.Dom;
|
||||||
|
using Newtonsoft.Json.Linq;
|
||||||
|
|
||||||
|
namespace HelloFreshScraper.Services
|
||||||
|
{
|
||||||
|
public class Recipe
|
||||||
|
{
|
||||||
|
public string Id { get; set; }
|
||||||
|
public string Name { get; set; }
|
||||||
|
public string Image { get; set; }
|
||||||
|
public string Pdf { get; set; }
|
||||||
|
public string PrepTime { get; set; } // ex: "30-35 min"
|
||||||
|
public string Difficulty { get; set; } // ex: "Intermédiaire"
|
||||||
|
public string Description { get; set; } // ex: "Accompagné de..."
|
||||||
|
public string Label { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class HelloFreshScraperService
|
||||||
|
{
|
||||||
|
private readonly HttpClient _httpClient;
|
||||||
|
private readonly IBrowsingContext _context;
|
||||||
|
|
||||||
|
public HelloFreshScraperService(HttpClient httpClient)
|
||||||
|
{
|
||||||
|
_httpClient = httpClient;
|
||||||
|
var config = Configuration.Default.WithDefaultLoader();
|
||||||
|
_context = BrowsingContext.New(config);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<List<Recipe>> GetRecipesAsync(string locale = "fr-fr", int startPage = 1, int pagesToLoad = 2)
|
||||||
|
{
|
||||||
|
var recipesDict = new Dictionary<string, Recipe>();
|
||||||
|
var config = Configuration.Default.WithDefaultLoader();
|
||||||
|
var context = BrowsingContext.New(config);
|
||||||
|
|
||||||
|
for (int page = startPage; page < startPage + pagesToLoad; page++)
|
||||||
|
{
|
||||||
|
var url = $"https://hfresh.info/{locale}?page={page}";
|
||||||
|
var html = await _httpClient.GetStringAsync(url);
|
||||||
|
|
||||||
|
var document = await context.OpenAsync(req => req.Content(html));
|
||||||
|
var rawData = document.QuerySelector("#app")?.GetAttribute("data-page");
|
||||||
|
|
||||||
|
if (string.IsNullOrWhiteSpace(rawData)) continue;
|
||||||
|
|
||||||
|
var parsed = JObject.Parse(rawData);
|
||||||
|
var recipeArray = parsed.SelectToken("props.recipes.data") as JArray;
|
||||||
|
|
||||||
|
foreach (var item in recipeArray ?? new JArray())
|
||||||
|
{
|
||||||
|
var id = item["id"]?.ToString();
|
||||||
|
var name = item["name"]?.ToString();
|
||||||
|
var pdf = item["pdf"]?.ToString();
|
||||||
|
|
||||||
|
if (string.IsNullOrEmpty(id) || string.IsNullOrEmpty(name) || string.IsNullOrEmpty(pdf))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (recipesDict.ContainsKey(id)) continue; // éviter les doublons
|
||||||
|
|
||||||
|
var nameKey = name.ToLower().Trim();
|
||||||
|
if (recipesDict.Values.Any(r => r.Name.ToLower().Trim() == nameKey)) continue;
|
||||||
|
|
||||||
|
|
||||||
|
var recipe = new Recipe
|
||||||
|
{
|
||||||
|
Id = id,
|
||||||
|
Name = name,
|
||||||
|
Image = item["image"]?.ToString(),
|
||||||
|
Pdf = pdf,
|
||||||
|
Description = item["headline"]?.ToString(),
|
||||||
|
Label = item["label"]?.ToString()
|
||||||
|
};
|
||||||
|
|
||||||
|
recipesDict[id] = recipe;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 👉 Scrape en parallèle les pages de détail
|
||||||
|
var tasks = recipesDict.Values.Select(async recipe =>
|
||||||
|
{
|
||||||
|
var slug = GenerateSlug(recipe.Name);
|
||||||
|
var url = $"https://www.hellofresh.fr/recipes/{slug}-{recipe.Id}";
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var html = await _httpClient.GetStringAsync(url);
|
||||||
|
|
||||||
|
// PrepTime (Regex simple, ex: "35 minutes")
|
||||||
|
var match = Regex.Match(html, @"(\d{1,3})\s*minutes?", RegexOptions.IgnoreCase);
|
||||||
|
if (match.Success)
|
||||||
|
recipe.PrepTime = match.Groups[1].Value;
|
||||||
|
|
||||||
|
// Difficulty
|
||||||
|
var diffMatch = Regex.Match(html, @"<span[^>]*data-translation-id=[""']recipe-detail\.level-number[^>]*>([^<]+)</span>", RegexOptions.IgnoreCase);
|
||||||
|
if (diffMatch.Success)
|
||||||
|
recipe.Difficulty = diffMatch.Groups[1].Value.Trim();
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Console.WriteLine($"❌ Erreur scraping {url} : {ex.Message}");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
await Task.WhenAll(tasks); // 🧠 Attendre que tous les détails soient récupérés
|
||||||
|
|
||||||
|
return recipesDict.Values.ToList();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
private string GenerateSlug(string name)
|
||||||
|
{
|
||||||
|
var slug = name.ToLower()
|
||||||
|
.Replace("é", "e").Replace("è", "e").Replace("ê", "e")
|
||||||
|
.Replace("à", "a").Replace("â", "a").Replace("ù", "u")
|
||||||
|
.Replace("î", "i").Replace("ô", "o").Replace("ç", "c")
|
||||||
|
.Replace("œ", "oe").Replace("&", "et")
|
||||||
|
.Replace("’", "-").Replace("'", "-")
|
||||||
|
.Replace("\"", "").Replace(",", "").Replace(":", "")
|
||||||
|
.Replace("!", "").Replace("?", "").Replace("(", "").Replace(")", "")
|
||||||
|
.Replace(" ", " ").Replace(" ", "-");
|
||||||
|
|
||||||
|
while (slug.Contains("--"))
|
||||||
|
slug = slug.Replace("--", "-");
|
||||||
|
|
||||||
|
return slug.Trim('-');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,46 +1,63 @@
|
|||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using System.Security.Claims;
|
||||||
using administration.Models;
|
using administration.Models;
|
||||||
|
using Microsoft.AspNetCore.Authorization;
|
||||||
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
|
||||||
namespace administration.Controllers;
|
namespace administration.Controllers
|
||||||
|
|
||||||
public class HomeController : Controller
|
|
||||||
{
|
{
|
||||||
private readonly FinancesContext _context;
|
[Authorize] // toute la classe nécessite une connexion
|
||||||
|
public class HomeController : Controller
|
||||||
public HomeController(FinancesContext context)
|
|
||||||
{
|
{
|
||||||
_context = context;
|
private readonly ILogger<HomeController> _logger;
|
||||||
}
|
|
||||||
|
|
||||||
public IActionResult Index()
|
public HomeController(ILogger<HomeController> logger)
|
||||||
{
|
|
||||||
// R<>cup<75>re un utilisateur fictif pour l<>exemple
|
|
||||||
var user = _context.Users.Where(X => X.Id == 2).First(); // <20> remplacer par un filtre r<>el (par ex. Email ou Id)
|
|
||||||
|
|
||||||
if (user != null)
|
|
||||||
{
|
{
|
||||||
// Stocker dans la session
|
_logger = logger;
|
||||||
HttpContext.Session.SetInt32("UserId", user.Id);
|
|
||||||
HttpContext.Session.SetString("UserName", user.Name);
|
|
||||||
}
|
}
|
||||||
return View();
|
|
||||||
}
|
|
||||||
|
|
||||||
public IActionResult Profile()
|
public IActionResult Index()
|
||||||
{
|
{
|
||||||
int? userId = HttpContext.Session.GetInt32("UserId");
|
EnsureSessionFromClaims();
|
||||||
string userName = HttpContext.Session.GetString("UserName");
|
return View();
|
||||||
|
}
|
||||||
|
|
||||||
ViewBag.UserId = userId;
|
public IActionResult Profile()
|
||||||
ViewBag.UserName = userName;
|
{
|
||||||
|
EnsureSessionFromClaims();
|
||||||
|
|
||||||
return View();
|
ViewBag.UserId = HttpContext.Session.GetInt32("UserId");
|
||||||
}
|
ViewBag.UserName = HttpContext.Session.GetString("UserName");
|
||||||
|
|
||||||
[ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)]
|
return View();
|
||||||
public IActionResult Error()
|
}
|
||||||
{
|
|
||||||
return View(new ErrorViewModel { RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier });
|
[ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)]
|
||||||
|
public IActionResult Error()
|
||||||
|
{
|
||||||
|
return View(new ErrorViewModel { RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier });
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Si la session est vide, recharge UserId et UserName depuis les claims
|
||||||
|
/// </summary>
|
||||||
|
private void EnsureSessionFromClaims()
|
||||||
|
{
|
||||||
|
if (!HttpContext.Session.Keys.Contains("UserId") || !HttpContext.Session.Keys.Contains("UserName"))
|
||||||
|
{
|
||||||
|
var userIdClaim = User.FindFirstValue(ClaimTypes.NameIdentifier);
|
||||||
|
var userNameClaim = User.FindFirstValue(ClaimTypes.Name);
|
||||||
|
|
||||||
|
if (!string.IsNullOrEmpty(userIdClaim) && int.TryParse(userIdClaim, out int userId))
|
||||||
|
{
|
||||||
|
HttpContext.Session.SetInt32("UserId", userId);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!string.IsNullOrEmpty(userNameClaim))
|
||||||
|
{
|
||||||
|
HttpContext.Session.SetString("UserName", userNameClaim);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
31
Controllers/OllamaController.cs
Normal file
31
Controllers/OllamaController.cs
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
using IngredientsAI.Services;
|
||||||
|
|
||||||
|
namespace IngredientsAI.Controllers
|
||||||
|
{
|
||||||
|
[ApiController]
|
||||||
|
[Route("api/[controller]")]
|
||||||
|
public class OllamaController : ControllerBase
|
||||||
|
{
|
||||||
|
private readonly OllamaService _ollama;
|
||||||
|
|
||||||
|
public OllamaController(OllamaService ollama)
|
||||||
|
{
|
||||||
|
_ollama = ollama;
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpGet("models")]
|
||||||
|
public async Task<IActionResult> GetModels()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var models = await _ollama.GetModelsAsync();
|
||||||
|
return Ok(new { items = models });
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
return BadRequest(new { error = ex.Message });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
43
Controllers/OllamaService.cs
Normal file
43
Controllers/OllamaService.cs
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
using System.Net.Http;
|
||||||
|
using System.Net.Http.Json;
|
||||||
|
using System.Text.Json;
|
||||||
|
|
||||||
|
namespace IngredientsAI.Services
|
||||||
|
{
|
||||||
|
public class OllamaService
|
||||||
|
{
|
||||||
|
private readonly HttpClient _http;
|
||||||
|
private readonly IConfiguration _config;
|
||||||
|
|
||||||
|
public OllamaService(IConfiguration config)
|
||||||
|
{
|
||||||
|
_config = config;
|
||||||
|
var handler = new HttpClientHandler
|
||||||
|
{
|
||||||
|
// Ignore SSL errors (utile pour ton VPS si certificat pas reconnu en local)
|
||||||
|
ServerCertificateCustomValidationCallback = HttpClientHandler.DangerousAcceptAnyServerCertificateValidator
|
||||||
|
};
|
||||||
|
|
||||||
|
_http = new HttpClient(handler)
|
||||||
|
{
|
||||||
|
BaseAddress = new Uri(_config["Ollama:Url"] ?? "https://ollama.byakurepo.online")
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// Exemple : récupère la liste des modèles disponibles
|
||||||
|
public async Task<IEnumerable<string>> GetModelsAsync()
|
||||||
|
{
|
||||||
|
var res = await _http.GetAsync("/api/tags");
|
||||||
|
res.EnsureSuccessStatusCode();
|
||||||
|
|
||||||
|
var json = await res.Content.ReadAsStringAsync();
|
||||||
|
using var doc = JsonDocument.Parse(json);
|
||||||
|
|
||||||
|
return doc.RootElement
|
||||||
|
.GetProperty("models")
|
||||||
|
.EnumerateArray()
|
||||||
|
.Select(m => m.GetProperty("name").GetString() ?? string.Empty)
|
||||||
|
.ToList();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,62 +0,0 @@
|
|||||||
using Microsoft.AspNetCore.Mvc;
|
|
||||||
using Microsoft.AspNetCore.Mvc.ViewEngines;
|
|
||||||
using Microsoft.AspNetCore.Mvc.Rendering;
|
|
||||||
using Microsoft.AspNetCore.Mvc.ViewFeatures;
|
|
||||||
using Microsoft.AspNetCore.Mvc.ModelBinding;
|
|
||||||
using System.IO;
|
|
||||||
|
|
||||||
namespace administration.Controllers
|
|
||||||
{
|
|
||||||
public class PagesController : Controller
|
|
||||||
{
|
|
||||||
private readonly ICompositeViewEngine _viewEngine;
|
|
||||||
private readonly ITempDataProvider _tempDataProvider;
|
|
||||||
|
|
||||||
public PagesController(ICompositeViewEngine viewEngine, ITempDataProvider tempDataProvider)
|
|
||||||
{
|
|
||||||
_viewEngine = viewEngine;
|
|
||||||
_tempDataProvider = tempDataProvider;
|
|
||||||
}
|
|
||||||
|
|
||||||
[HttpGet("/pages/{folder}/{page}")]
|
|
||||||
public async Task<IActionResult> Render(string folder, string page)
|
|
||||||
{
|
|
||||||
var allowedFolders = new[] { "Charts", "Components", "Connections", "Home", "Tables", "Utilities" };
|
|
||||||
|
|
||||||
var realFolder = allowedFolders.FirstOrDefault(f => string.Equals(f, folder, StringComparison.OrdinalIgnoreCase));
|
|
||||||
if (realFolder == null)
|
|
||||||
return Content("Ce dossier n'est pas autorisé.", "text/plain; charset=utf-8");
|
|
||||||
|
|
||||||
// Trouver la vraie casse du fichier sur disque
|
|
||||||
var folderPath = Path.Combine(Directory.GetCurrentDirectory(), "Views", realFolder);
|
|
||||||
var cshtmlFile = Directory.GetFiles(folderPath, "*.cshtml")
|
|
||||||
.FirstOrDefault(f => string.Equals(Path.GetFileNameWithoutExtension(f), page, StringComparison.OrdinalIgnoreCase));
|
|
||||||
|
|
||||||
if (cshtmlFile == null)
|
|
||||||
return NotFound($"La vue ~/Views/{realFolder}/{page}.cshtml n'existe pas physiquement.");
|
|
||||||
|
|
||||||
var razorViewPath = $"~/Views/{realFolder}/{Path.GetFileName(cshtmlFile)}";
|
|
||||||
var result = _viewEngine.GetView(null, razorViewPath, true);
|
|
||||||
|
|
||||||
if (!result.Success)
|
|
||||||
return NotFound($"Vue Razor non trouvée : {razorViewPath}");
|
|
||||||
|
|
||||||
|
|
||||||
var viewData = new ViewDataDictionary(new EmptyModelMetadataProvider(), new ModelStateDictionary());
|
|
||||||
var tempData = new TempDataDictionary(HttpContext, _tempDataProvider);
|
|
||||||
|
|
||||||
using var sw = new StringWriter();
|
|
||||||
var context = new ViewContext(
|
|
||||||
ControllerContext,
|
|
||||||
result.View,
|
|
||||||
viewData,
|
|
||||||
tempData,
|
|
||||||
sw,
|
|
||||||
new HtmlHelperOptions()
|
|
||||||
);
|
|
||||||
|
|
||||||
await result.View.RenderAsync(context);
|
|
||||||
return Content(sw.ToString(), "text/html");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
504
Controllers/SearchController.cs
Normal file
504
Controllers/SearchController.cs
Normal file
@@ -0,0 +1,504 @@
|
|||||||
|
//// Controllers/SearchController.cs
|
||||||
|
//using Microsoft.AspNetCore.Mvc;
|
||||||
|
//using Microsoft.Extensions.Logging;
|
||||||
|
//using System.Net.Http.Headers;
|
||||||
|
//using System.Text;
|
||||||
|
//using System.Text.Json;
|
||||||
|
//using System.Text.Json.Serialization;
|
||||||
|
//using System.Text.RegularExpressions;
|
||||||
|
|
||||||
|
//namespace Administration.Controllers
|
||||||
|
//{
|
||||||
|
// [ApiController]
|
||||||
|
// [Route("api/ai")]
|
||||||
|
// public class SearchController : ControllerBase
|
||||||
|
// {
|
||||||
|
// private readonly IHttpClientFactory _httpFactory;
|
||||||
|
// private readonly IConfiguration _cfg;
|
||||||
|
// private readonly ILogger<SearchController> _log;
|
||||||
|
|
||||||
|
// public SearchController(IHttpClientFactory httpFactory, IConfiguration cfg, ILogger<SearchController> log)
|
||||||
|
// {
|
||||||
|
// _httpFactory = httpFactory;
|
||||||
|
// _cfg = cfg;
|
||||||
|
// _log = log;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// // =========================
|
||||||
|
// // DTOs
|
||||||
|
// // =========================
|
||||||
|
// public sealed class AiSelectRequest
|
||||||
|
// {
|
||||||
|
// public string Query { get; set; } = "";
|
||||||
|
// public List<string> Allowed { get; set; } = new();
|
||||||
|
// public bool Debug { get; set; } = false;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// public sealed class AiSelectResponse
|
||||||
|
// {
|
||||||
|
// [JsonPropertyName("names")]
|
||||||
|
// public List<string> Names { get; set; } = new();
|
||||||
|
|
||||||
|
// [JsonPropertyName("debug")]
|
||||||
|
// public object? Debug { get; set; }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// // =========================
|
||||||
|
// // POST /api/ai/select
|
||||||
|
// // =========================
|
||||||
|
// [HttpPost("select")]
|
||||||
|
// public async Task<IActionResult> Select([FromBody] AiSelectRequest body)
|
||||||
|
// {
|
||||||
|
// if (body is null) return BadRequest(new { error = "Body requis." });
|
||||||
|
// if (string.IsNullOrWhiteSpace(body.Query)) return BadRequest(new { error = "Query requis." });
|
||||||
|
// if (body.Allowed is null || body.Allowed.Count == 0)
|
||||||
|
// {
|
||||||
|
// _log.LogWarning("AI Select: Allowed vide pour query '{Query}'", body.Query);
|
||||||
|
// return Ok(new AiSelectResponse { Names = new() });
|
||||||
|
// }
|
||||||
|
|
||||||
|
// // Normalisation unique
|
||||||
|
// var allowed = body.Allowed
|
||||||
|
// .Where(a => !string.IsNullOrWhiteSpace(a))
|
||||||
|
// .Select(a => a.Trim())
|
||||||
|
// .Distinct(StringComparer.OrdinalIgnoreCase)
|
||||||
|
// .ToList();
|
||||||
|
|
||||||
|
// // --- 1) Raccourcis instantanés : catégories & synonymes riches
|
||||||
|
// var catHits = TryCategoryExpand(body.Query, allowed);
|
||||||
|
// if (catHits.Count > 0)
|
||||||
|
// return Ok(new AiSelectResponse { Names = SortByAllowedOrder(catHits, allowed) });
|
||||||
|
|
||||||
|
// // --- 2) Match "classique" tolérant (FR/EN, accents, pluriels)
|
||||||
|
// var classicHits = ClassicMatch(body.Query, allowed);
|
||||||
|
// if (classicHits.Count > 0)
|
||||||
|
// return Ok(new AiSelectResponse { Names = SortByAllowedOrder(classicHits, allowed) });
|
||||||
|
|
||||||
|
// // --- 3) Heuristique "prompt" -> on tente l'IA (court)
|
||||||
|
// var ollamaUrl = _cfg["Ollama:Url"] ?? "http://ollama:11434";
|
||||||
|
// var model = _cfg["Ollama:Model"] ?? "qwen2.5:1.5b-instruct";
|
||||||
|
|
||||||
|
// // prompt ultra directif pour forcer un tableau JSON plat
|
||||||
|
// var prompt =
|
||||||
|
// $"Liste autorisée: [{string.Join(",", allowed.Select(a => $"\"{a}\""))}].\n" +
|
||||||
|
// $"Requête: \"{body.Query}\".\n" +
|
||||||
|
// "Réponds UNIQUEMENT par un tableau JSON plat des éléments EXACTEMENT issus de la liste autorisée. " +
|
||||||
|
// "Exemple: [\"Tomate\",\"Oignon\"]. Interdit: objets {name:...}, clés ingredients:, texte hors JSON.";
|
||||||
|
|
||||||
|
// var client = _httpFactory.CreateClient();
|
||||||
|
// client.Timeout = Timeout.InfiniteTimeSpan; // on contrôle avec CTS
|
||||||
|
|
||||||
|
// var payload = new
|
||||||
|
// {
|
||||||
|
// model,
|
||||||
|
// prompt,
|
||||||
|
// stream = false,
|
||||||
|
// format = "json",
|
||||||
|
// keep_alive = "10m",
|
||||||
|
// options = new
|
||||||
|
// {
|
||||||
|
// temperature = 0.0,
|
||||||
|
// num_ctx = 64,
|
||||||
|
// num_predict = 64
|
||||||
|
// }
|
||||||
|
// };
|
||||||
|
|
||||||
|
// var req = new HttpRequestMessage(HttpMethod.Post, $"{ollamaUrl.TrimEnd('/')}/api/generate");
|
||||||
|
// req.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
|
||||||
|
// req.Content = new StringContent(JsonSerializer.Serialize(payload), Encoding.UTF8, "application/json");
|
||||||
|
|
||||||
|
// _log.LogInformation("AI Select ▶ Query='{Query}', AllowedCount={AllowedCount}, Model={Model}, Url={Url}",
|
||||||
|
// body.Query, allowed.Count, model, ollamaUrl);
|
||||||
|
// if (body.Debug)
|
||||||
|
// {
|
||||||
|
// _log.LogDebug("AI Select ▶ Prompt envoyé:\n{Prompt}", payload.prompt);
|
||||||
|
// }
|
||||||
|
|
||||||
|
// // Si la requête ressemble à une phrase libre -> 4s, sinon 2s
|
||||||
|
// bool prompty = body.Query.Length >= 18
|
||||||
|
// || Regex.IsMatch(body.Query, @"\b(avec|sans|pour|idée|idées|recette|faire|préparer|quoi|envie)\b", RegexOptions.IgnoreCase);
|
||||||
|
// using var cts = new CancellationTokenSource(TimeSpan.FromSeconds(prompty ? 4 : 2));
|
||||||
|
|
||||||
|
// try
|
||||||
|
// {
|
||||||
|
// using var resp = await client.SendAsync(req, HttpCompletionOption.ResponseHeadersRead, cts.Token);
|
||||||
|
// var raw = await resp.Content.ReadAsStringAsync();
|
||||||
|
|
||||||
|
// _log.LogInformation("AI Select ◀ HTTP {Status} ({Reason})", (int)resp.StatusCode, resp.ReasonPhrase);
|
||||||
|
// _log.LogDebug("AI Select ◀ RAW:\n{Raw}", raw);
|
||||||
|
|
||||||
|
// if (!resp.IsSuccessStatusCode)
|
||||||
|
// {
|
||||||
|
// _log.LogWarning("AI Select: statut non OK, on renvoie l’erreur au client.");
|
||||||
|
// return StatusCode((int)resp.StatusCode, new
|
||||||
|
// {
|
||||||
|
// error = "IA error",
|
||||||
|
// raw,
|
||||||
|
// url = $"{ollamaUrl.TrimEnd('/')}/api/generate"
|
||||||
|
// });
|
||||||
|
// }
|
||||||
|
|
||||||
|
// // Extraire "response" puis convertir en liste de chaînes
|
||||||
|
// using var doc = JsonDocument.Parse(raw);
|
||||||
|
// var responseText = doc.RootElement.TryGetProperty("response", out var rEl)
|
||||||
|
// ? (rEl.GetString() ?? "")
|
||||||
|
// : "";
|
||||||
|
|
||||||
|
// var iaNames = ExtractNames(responseText);
|
||||||
|
// var mapped = MapToAllowed(iaNames, allowed);
|
||||||
|
|
||||||
|
// return Ok(new AiSelectResponse
|
||||||
|
// {
|
||||||
|
// Names = SortByAllowedOrder(mapped, allowed),
|
||||||
|
// Debug = body.Debug ? new { sent = payload, url = $"{ollamaUrl.TrimEnd('/')}/api/generate", raw } : null
|
||||||
|
// });
|
||||||
|
// }
|
||||||
|
// catch (TaskCanceledException)
|
||||||
|
// {
|
||||||
|
// _log.LogWarning("AI Select: timeout côté Ollama ({Url})", ollamaUrl);
|
||||||
|
// return StatusCode(504, new { error = "Timeout IA" });
|
||||||
|
// }
|
||||||
|
// catch (Exception ex)
|
||||||
|
// {
|
||||||
|
// _log.LogError(ex, "AI Select: exception pendant l’appel Ollama.");
|
||||||
|
// return StatusCode(500, new { error = ex.Message });
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// // =========================
|
||||||
|
// // Helpers — Normalisation
|
||||||
|
// // =========================
|
||||||
|
// static string RemoveDiacritics(string s)
|
||||||
|
// {
|
||||||
|
// if (string.IsNullOrEmpty(s)) return "";
|
||||||
|
// var formD = s.Normalize(NormalizationForm.FormD);
|
||||||
|
// var sb = new StringBuilder(formD.Length);
|
||||||
|
// foreach (var ch in formD)
|
||||||
|
// {
|
||||||
|
// var uc = System.Globalization.CharUnicodeInfo.GetUnicodeCategory(ch);
|
||||||
|
// if (uc != System.Globalization.UnicodeCategory.NonSpacingMark)
|
||||||
|
// sb.Append(ch);
|
||||||
|
// }
|
||||||
|
// return sb.ToString().Normalize(NormalizationForm.FormC);
|
||||||
|
// }
|
||||||
|
|
||||||
|
// static string Key(string? s)
|
||||||
|
// {
|
||||||
|
// s ??= "";
|
||||||
|
// var noAcc = RemoveDiacritics(s).ToLowerInvariant();
|
||||||
|
// // retire ponctuation + normalise espaces
|
||||||
|
// noAcc = Regex.Replace(noAcc, @"[^\p{L}\p{Nd}\s]", " ");
|
||||||
|
// noAcc = Regex.Replace(noAcc, @"\s+", " ").Trim();
|
||||||
|
// // singulier approximatif (enlève 's' final si pertinent)
|
||||||
|
// if (noAcc.EndsWith("s") && noAcc.Length > 3) noAcc = noAcc[..^1];
|
||||||
|
// return noAcc;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// static List<string> SortByAllowedOrder(IEnumerable<string> items, List<string> allowed)
|
||||||
|
// {
|
||||||
|
// var set = new HashSet<string>(items, StringComparer.OrdinalIgnoreCase);
|
||||||
|
// var ordered = new List<string>();
|
||||||
|
// foreach (var a in allowed)
|
||||||
|
// if (set.Contains(a)) ordered.Add(a);
|
||||||
|
// return ordered;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// // =========================
|
||||||
|
// // Helpers — Matching local
|
||||||
|
// // =========================
|
||||||
|
|
||||||
|
// // Synonymes simples EN -> FR (complète librement)
|
||||||
|
// static readonly Dictionary<string, string[]> EN_FR_SYNONYMS = new(StringComparer.OrdinalIgnoreCase)
|
||||||
|
// {
|
||||||
|
// ["meat"] = new[] { "viande", "viandes", "boeuf", "bœuf", "porc", "poulet", "agneau", "veau", "saucisse", "jambon" },
|
||||||
|
// ["fish"] = new[] { "poisson", "saumon", "thon", "cabillaud", "lieu", "filet de lieu", "colin", "merlu" },
|
||||||
|
// ["spicy"] = new[] { "piquant", "épicé", "piment", "harissa", "sriracha", "curry", "paprika", "poivre", "gingembre" },
|
||||||
|
// ["fresh"] = new[] { "frais", "fraîche", "fraîches", "réfrigéré", "perissable", "périssable" },
|
||||||
|
// ["dairy"] = new[] { "laitier", "laitiers", "lait", "beurre", "fromage", "crème", "yaourt" },
|
||||||
|
// ["herbs"] = new[] { "herbes", "persil", "ciboulette", "basilic", "menthe", "aneth", "romarin", "thym" },
|
||||||
|
// ["sauce"] = new[] { "sauce", "sauces", "condiment", "condiments", "mayonnaise", "ketchup", "moutarde", "soja", "sauce soja", "BBQ" },
|
||||||
|
// ["veggie"] = new[] { "légume", "légumes", "tomate", "oignon", "carotte", "brocoli", "courgette", "poivron", "ail", "salade" },
|
||||||
|
// ["protein"] = new[] { "protéine", "protéines", "oeuf", "œuf", "tofu", "tempeh", "pois chiches", "lentilles", "haricots", "poulet", "fromage" },
|
||||||
|
// };
|
||||||
|
|
||||||
|
// static List<string> ClassicMatch(string query, List<string> allowed)
|
||||||
|
// {
|
||||||
|
// var nq = Key(query);
|
||||||
|
// var tokens = nq.Split(' ', StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries);
|
||||||
|
|
||||||
|
// // EN->FR élargit
|
||||||
|
// var expanded = new HashSet<string>(tokens);
|
||||||
|
// foreach (var t in tokens)
|
||||||
|
// if (EN_FR_SYNONYMS.TryGetValue(t, out var frs))
|
||||||
|
// foreach (var fr in frs) expanded.Add(Key(fr));
|
||||||
|
|
||||||
|
// var hits = new List<string>();
|
||||||
|
// foreach (var a in allowed)
|
||||||
|
// {
|
||||||
|
// if (AnyTokenMatches(a, expanded))
|
||||||
|
// hits.Add(a);
|
||||||
|
// }
|
||||||
|
|
||||||
|
// return hits.Distinct(StringComparer.OrdinalIgnoreCase).ToList();
|
||||||
|
// }
|
||||||
|
|
||||||
|
|
||||||
|
// // =========================
|
||||||
|
// // Catégories & règles
|
||||||
|
// // =========================
|
||||||
|
// sealed class CategoryRule
|
||||||
|
// {
|
||||||
|
// public string Name { get; init; } = "";
|
||||||
|
// public string[] Triggers { get; init; } = Array.Empty<string>();
|
||||||
|
// public string[] Must { get; init; } = Array.Empty<string>();
|
||||||
|
// public string[] Any { get; init; } = Array.Empty<string>();
|
||||||
|
// public string[] Not { get; init; } = Array.Empty<string>();
|
||||||
|
// }
|
||||||
|
|
||||||
|
// static readonly List<CategoryRule> CATEGORY_RULES = new()
|
||||||
|
// {
|
||||||
|
// new CategoryRule {
|
||||||
|
// Name = "legumes",
|
||||||
|
// Triggers = new[]{"legume","légume","légumes","vegetable","veggie","crudité"},
|
||||||
|
// Any = new[]{
|
||||||
|
// "oignon","carotte","pomme de terre","brocoli","courgette",
|
||||||
|
// "poivron","tomate","ail","salade","champignon","haricot vert","épinard"
|
||||||
|
// },
|
||||||
|
// Not = new[]{
|
||||||
|
// // viande/charcuterie
|
||||||
|
// "saucisse","porc","poulet","boeuf","bœuf","agneau","veau","jambon","lardon","charcuterie","filet",
|
||||||
|
// // poisson/mer
|
||||||
|
// "poisson","saumon","thon","lieu","cabillaud","merlu","colin","crevette","moule",
|
||||||
|
// // laitier/fromage/œuf
|
||||||
|
// "fromage","crème","lait","yaourt","œuf","oeuf","beurre"
|
||||||
|
// }
|
||||||
|
// },
|
||||||
|
// new CategoryRule {
|
||||||
|
// Name = "fruits",
|
||||||
|
// Triggers = new[]{"fruit","fruits","dessert","sucré"},
|
||||||
|
// Any = new[]{"pomme","banane","orange","citron","citron vert","fraise","poire","raisin","tomate"}
|
||||||
|
// },
|
||||||
|
// new CategoryRule {
|
||||||
|
// Name = "epices",
|
||||||
|
// Triggers = new[]{"epice","épice","epices","épices","spice","spicy","assaisonnement"},
|
||||||
|
// Any = new[]{"cumin","paprika","curcuma","vadouvan","curry","poivre","piment","gingembre","muscade","thym"}
|
||||||
|
// },
|
||||||
|
// new CategoryRule {
|
||||||
|
// Name = "herbes",
|
||||||
|
// Triggers = new[]{"herbe","herbes","aromatique","aromatiques"},
|
||||||
|
// Any = new[]{"persil","ciboulette","basilic","menthe","aneth","romarin","thym","coriandre"}
|
||||||
|
// },
|
||||||
|
// new CategoryRule {
|
||||||
|
// Name = "laitiers",
|
||||||
|
// Triggers = new[]{"laitier","laitiers","dairy","fromager","crémier"},
|
||||||
|
// Any = new[]{"lait","beurre","fromage","crème","yaourt","crème aigre","mozzarella","parmesan","lait de coco"}
|
||||||
|
// },
|
||||||
|
// new CategoryRule {
|
||||||
|
// Name = "viandes",
|
||||||
|
// Triggers = new[]{"viande","viandes","carné","meat","steak","charcuterie"},
|
||||||
|
// Any = new[]{"boeuf","bœuf","porc","poulet","dinde","agneau","veau","saucisse","jambon","lardons","filet de porc"}
|
||||||
|
// },
|
||||||
|
// new CategoryRule {
|
||||||
|
// Name = "poissons",
|
||||||
|
// Triggers = new[]{"poisson","poissons","seafood","poissonnerie","poissonnier"},
|
||||||
|
// Any = new[]{"saumon","thon","lieu","filet de lieu","cabillaud","merlu","colin","crevette","moule"}
|
||||||
|
// },
|
||||||
|
// new CategoryRule {
|
||||||
|
// Name = "proteines",
|
||||||
|
// Triggers = new[]{"protéine","protéines","protein","proteins"},
|
||||||
|
// Any = new[]{"oeuf","œuf","tofu","tempeh","pois chiches","lentilles","haricots","saucisse","jambon","poulet","filet de porc","fromage"}
|
||||||
|
// },
|
||||||
|
// new CategoryRule {
|
||||||
|
// Name = "frais",
|
||||||
|
// Triggers = new[]{"frais","fraiche","fraîche","fraîches","réfrigéré","frigo","perissable","périssable"},
|
||||||
|
// Any = new[]{"salade","tomate","concombre","yaourt","fromage","beurre","crème","herbes","viande","poisson"}
|
||||||
|
// },
|
||||||
|
// new CategoryRule {
|
||||||
|
// Name = "piquant",
|
||||||
|
// Triggers = new[]{"piquant","pimenté","fort","épicé","spicy","hot"},
|
||||||
|
// Any = new[]{"piment","harissa","sriracha","tabasco","curry","paprika","gingembre","poivre","pâte de curry","pâte de curry vert"}
|
||||||
|
// },
|
||||||
|
// new CategoryRule {
|
||||||
|
// Name = "sauces",
|
||||||
|
// Triggers = new[]{"sauce","sauces","condiment","condiments","topping"},
|
||||||
|
// Any = new[]{"mayonnaise","ketchup","moutarde","soja","sauce soja","worcestershire","BBQ","harissa","sriracha","pâte de curry","pâte de curry vert","lait de coco","crème"}
|
||||||
|
// },
|
||||||
|
// new CategoryRule {
|
||||||
|
// Name = "condiments",
|
||||||
|
// Triggers = new[]{"condiment","condiments","pickles","vinaigre","cornichon"},
|
||||||
|
// Any = new[]{"moutarde","vinaigre","huile","cornichon","câpres","poivre","sel"}
|
||||||
|
// },
|
||||||
|
// new CategoryRule {
|
||||||
|
// Name = "cereales",
|
||||||
|
// Triggers = new[]{"céréale","céréales","grains","cereal"},
|
||||||
|
// Any = new[]{"riz","quinoa","semoule","boulgour","avoine","farine"}
|
||||||
|
// },
|
||||||
|
// new CategoryRule {
|
||||||
|
// Name = "pates",
|
||||||
|
// Triggers = new[]{"pate","pâtes","nouilles","pasta","spaghetti"},
|
||||||
|
// Any = new[]{"pâtes","nouilles","nouilles de riz","spaghetti","penne","farfalle"}
|
||||||
|
// },
|
||||||
|
// new CategoryRule {
|
||||||
|
// Name = "sandwich",
|
||||||
|
// Triggers = new[]{"sandwich","sandwichs","sandwiches","wrap","tacos","kebab","burger"},
|
||||||
|
// Any = new[]{"pain","salade","tomate","oignon","fromage","jambon","saucisse","poulet","sauce","cornichon"}
|
||||||
|
// },
|
||||||
|
// new CategoryRule {
|
||||||
|
// Name = "sucre",
|
||||||
|
// Triggers = new[]{"sucre","sucré","dessert","patisserie","pâtisserie","gâteau"},
|
||||||
|
// Any = new[]{"sucre","chocolat","vanille","beurre","farine","lait","œuf","oeuf","pomme","banane","crème"}
|
||||||
|
// },
|
||||||
|
// };
|
||||||
|
|
||||||
|
// static List<string> TryCategoryExpand(string query, List<string> allowed)
|
||||||
|
// {
|
||||||
|
// var nq = Key(query);
|
||||||
|
// var hits = new List<string>();
|
||||||
|
|
||||||
|
// foreach (var rule in CATEGORY_RULES)
|
||||||
|
// {
|
||||||
|
// if (!rule.Triggers.Any(t => nq.Contains(Key(t)))) continue;
|
||||||
|
|
||||||
|
// var allowedHits = allowed.Where(a =>
|
||||||
|
// {
|
||||||
|
// // normalisé dans les helpers
|
||||||
|
// bool anyOk = rule.Any.Length == 0 || AnyTokenMatches(a, rule.Any);
|
||||||
|
// bool mustOk = rule.Must.Length == 0 || AllTokensMatch(a, rule.Must);
|
||||||
|
// bool notOk = rule.Not.Length > 0 && AnyTokenMatches(a, rule.Not);
|
||||||
|
// return anyOk && mustOk && !notOk;
|
||||||
|
// });
|
||||||
|
|
||||||
|
// hits.AddRange(allowedHits);
|
||||||
|
// }
|
||||||
|
|
||||||
|
// return hits.Distinct(StringComparer.OrdinalIgnoreCase).ToList();
|
||||||
|
// }
|
||||||
|
|
||||||
|
// // =========================
|
||||||
|
// // Helpers — Parsing IA
|
||||||
|
// // =========================
|
||||||
|
// static List<string> ExtractNames(string responseText)
|
||||||
|
// {
|
||||||
|
// // 1) tableau JSON brut -> ["...","..."]
|
||||||
|
// try
|
||||||
|
// {
|
||||||
|
// var arr = JsonSerializer.Deserialize<string[]>(responseText);
|
||||||
|
// if (arr is not null && arr.Length > 0)
|
||||||
|
// return arr.Where(s => !string.IsNullOrWhiteSpace(s)).ToList();
|
||||||
|
// }
|
||||||
|
// catch { /* not an array */ }
|
||||||
|
|
||||||
|
// // 2) objet { "ingredients": [...] } ou { "ingrédients": [...] }
|
||||||
|
// try
|
||||||
|
// {
|
||||||
|
// using var inner = JsonDocument.Parse(responseText);
|
||||||
|
// if (inner.RootElement.TryGetProperty("ingredients", out var arr1) && arr1.ValueKind == JsonValueKind.Array)
|
||||||
|
// return arr1.EnumerateArray().Select(e => e.GetString() ?? "").Where(s => !string.IsNullOrWhiteSpace(s)).ToList();
|
||||||
|
|
||||||
|
// if (inner.RootElement.TryGetProperty("ingrédients", out var arr2) && arr2.ValueKind == JsonValueKind.Array)
|
||||||
|
// return arr2.EnumerateArray().Select(e => e.GetString() ?? "").Where(s => !string.IsNullOrWhiteSpace(s)).ToList();
|
||||||
|
// }
|
||||||
|
// catch { /* not an object */ }
|
||||||
|
|
||||||
|
// // 3) JSON encodé dans une string (rare mais vu chez Qwen)
|
||||||
|
// var mObj = Regex.Match(responseText, @"\{[\s\S]*\}");
|
||||||
|
// if (mObj.Success)
|
||||||
|
// {
|
||||||
|
// try
|
||||||
|
// {
|
||||||
|
// using var objDoc = JsonDocument.Parse(mObj.Value);
|
||||||
|
// if (objDoc.RootElement.TryGetProperty("ingredients", out var arr1) && arr1.ValueKind == JsonValueKind.Array)
|
||||||
|
// return arr1.EnumerateArray().Select(e => e.GetString() ?? "").Where(s => !string.IsNullOrWhiteSpace(s)).ToList();
|
||||||
|
|
||||||
|
// if (objDoc.RootElement.TryGetProperty("ingrédients", out var arr2) && arr2.ValueKind == JsonValueKind.Array)
|
||||||
|
// return arr2.EnumerateArray().Select(e => e.GetString() ?? "").Where(s => !string.IsNullOrWhiteSpace(s)).ToList();
|
||||||
|
// }
|
||||||
|
// catch { /* ignore */ }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// // 4) fallback : extrait le premier [...] plausible
|
||||||
|
// var mArr = Regex.Match(responseText, @"\[[\s\S]*?\]");
|
||||||
|
// if (mArr.Success)
|
||||||
|
// {
|
||||||
|
// try
|
||||||
|
// {
|
||||||
|
// var arr = JsonSerializer.Deserialize<string[]>(mArr.Value);
|
||||||
|
// if (arr is not null && arr.Length > 0)
|
||||||
|
// return arr.Where(s => !string.IsNullOrWhiteSpace(s)).ToList();
|
||||||
|
// }
|
||||||
|
// catch { /* ignore */ }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// return new List<string>();
|
||||||
|
// }
|
||||||
|
|
||||||
|
// static List<string> MapToAllowed(IEnumerable<string> names, List<string> allowed)
|
||||||
|
// {
|
||||||
|
// var mapAllowed = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
|
||||||
|
// foreach (var a in allowed)
|
||||||
|
// {
|
||||||
|
// var k = Key(a);
|
||||||
|
// if (!mapAllowed.ContainsKey(k))
|
||||||
|
// mapAllowed[k] = a;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// var result = new List<string>();
|
||||||
|
// var seen = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
|
||||||
|
|
||||||
|
// foreach (var n in names)
|
||||||
|
// {
|
||||||
|
// var k = Key(n);
|
||||||
|
// if (mapAllowed.TryGetValue(k, out var official))
|
||||||
|
// {
|
||||||
|
// if (seen.Add(official))
|
||||||
|
// result.Add(official);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// return result;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// // --- Helpers de matching précis ---
|
||||||
|
// static bool ContainsPhraseOrWord(string haystack, string token)
|
||||||
|
// {
|
||||||
|
// // les deux sont déjà normalisés via Key() avant appel
|
||||||
|
// if (string.IsNullOrWhiteSpace(token)) return false;
|
||||||
|
|
||||||
|
// if (token.Contains(' '))
|
||||||
|
// {
|
||||||
|
// // multi-mots : on garde le contains sur la phrase normalisée
|
||||||
|
// return haystack.Contains(token);
|
||||||
|
// }
|
||||||
|
|
||||||
|
// // 1 mot : on exige un match sur "mot entier"
|
||||||
|
// // ex: "oignon" ne doit pas faire matcher "saucisse de porc ... aux oignons caramélisés"
|
||||||
|
// var words = haystack.Split(' ', StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries);
|
||||||
|
// foreach (var w in words)
|
||||||
|
// if (w.Equals(token, StringComparison.Ordinal)) return true;
|
||||||
|
|
||||||
|
// return false;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// static bool AnyTokenMatches(string haystack, IEnumerable<string> tokens)
|
||||||
|
// {
|
||||||
|
// var h = Key(haystack);
|
||||||
|
// foreach (var t in tokens)
|
||||||
|
// {
|
||||||
|
// var tok = Key(t);
|
||||||
|
// if (ContainsPhraseOrWord(h, tok)) return true;
|
||||||
|
// }
|
||||||
|
// return false;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// static bool AllTokensMatch(string haystack, IEnumerable<string> tokens)
|
||||||
|
// {
|
||||||
|
// var h = Key(haystack);
|
||||||
|
// foreach (var t in tokens)
|
||||||
|
// {
|
||||||
|
// var tok = Key(t);
|
||||||
|
// if (!ContainsPhraseOrWord(h, tok)) return false;
|
||||||
|
// }
|
||||||
|
// return true;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// }
|
||||||
|
//}
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
|
||||||
namespace administration.Models;
|
namespace administration.Models.Finances;
|
||||||
|
|
||||||
public partial class AdditionalSource
|
public partial class AdditionalSource
|
||||||
{
|
{
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
|
||||||
namespace administration.Models;
|
namespace administration.Models.Finances;
|
||||||
|
|
||||||
public partial class Expense
|
public partial class Expense
|
||||||
{
|
{
|
||||||
@@ -2,7 +2,7 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
|
||||||
namespace administration.Models;
|
namespace administration.Models.Finances;
|
||||||
|
|
||||||
public partial class FinancesContext : DbContext
|
public partial class FinancesContext : DbContext
|
||||||
{
|
{
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
|
||||||
namespace administration.Models;
|
namespace administration.Models.Finances;
|
||||||
|
|
||||||
public partial class Logo
|
public partial class Logo
|
||||||
{
|
{
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
|
||||||
namespace administration.Models;
|
namespace administration.Models.Finances;
|
||||||
|
|
||||||
public partial class Revenue
|
public partial class Revenue
|
||||||
{
|
{
|
||||||
17
Models/Finances/User.cs
Normal file
17
Models/Finances/User.cs
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace administration.Models.Finances;
|
||||||
|
|
||||||
|
public partial class User
|
||||||
|
{
|
||||||
|
public int Id { get; set; }
|
||||||
|
|
||||||
|
public string Name { get; set; } = null!;
|
||||||
|
|
||||||
|
public virtual ICollection<AdditionalSource> AdditionalSources { get; set; } = new List<AdditionalSource>();
|
||||||
|
|
||||||
|
public virtual ICollection<Expense> Expenses { get; set; } = new List<Expense>();
|
||||||
|
|
||||||
|
public virtual ICollection<Revenue> Revenues { get; set; } = new List<Revenue>();
|
||||||
|
}
|
||||||
9
Models/HelloFresh/DTO/IngredientItemDto.cs
Normal file
9
Models/HelloFresh/DTO/IngredientItemDto.cs
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
namespace administration.Models.HelloFresh.DTO;
|
||||||
|
|
||||||
|
public class IngredientItemDto
|
||||||
|
{
|
||||||
|
public string Name { get; set; } = "";
|
||||||
|
public string? Quantity { get; set; }
|
||||||
|
public string? Image { get; set; }
|
||||||
|
public bool Owned { get; set; }
|
||||||
|
}
|
||||||
16
Models/HelloFresh/DTO/SmartSearchResponse.cs
Normal file
16
Models/HelloFresh/DTO/SmartSearchResponse.cs
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
using administration.Models.HelloFresh.DTO;
|
||||||
|
|
||||||
|
namespace administration.Models.DTO
|
||||||
|
{
|
||||||
|
public class SmartSearchResponse
|
||||||
|
{
|
||||||
|
public List<IngredientItemDto> Items { get; set; } = new();
|
||||||
|
public SmartSearchDebug Debug { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class SmartSearchDebug
|
||||||
|
{
|
||||||
|
public object Sent { get; set; }
|
||||||
|
public string Llm { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
92
Models/HelloFresh/HelloFreshContext.cs
Normal file
92
Models/HelloFresh/HelloFreshContext.cs
Normal file
@@ -0,0 +1,92 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
|
||||||
|
namespace administration.Models.HelloFresh;
|
||||||
|
|
||||||
|
public partial class HelloFreshContext : DbContext
|
||||||
|
{
|
||||||
|
public HelloFreshContext()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public HelloFreshContext(DbContextOptions<HelloFreshContext> options)
|
||||||
|
: base(options)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual DbSet<HistoriqueRecette> HistoriqueRecettes { get; set; }
|
||||||
|
|
||||||
|
public virtual DbSet<Ingredient> Ingredients { get; set; }
|
||||||
|
|
||||||
|
public virtual DbSet<Recette> Recettes { get; set; }
|
||||||
|
|
||||||
|
public virtual DbSet<SavingRecette> SavingRecettes { get; set; }
|
||||||
|
|
||||||
|
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
|
||||||
|
#warning To protect potentially sensitive information in your connection string, you should move it out of source code. You can avoid scaffolding the connection string by using the Name= syntax to read it from configuration - see https://go.microsoft.com/fwlink/?linkid=2131148. For more guidance on storing connection strings, see https://go.microsoft.com/fwlink/?LinkId=723263.
|
||||||
|
=> optionsBuilder.UseSqlServer("Server=217.154.116.43;Database=HelloFresh;User Id=sa;Password=Mf33ksTRLrPKSqQ4cTXitgiSN6BPBt89;TrustServerCertificate=True;");
|
||||||
|
|
||||||
|
protected override void OnModelCreating(ModelBuilder modelBuilder)
|
||||||
|
{
|
||||||
|
modelBuilder.Entity<HistoriqueRecette>(entity =>
|
||||||
|
{
|
||||||
|
entity.Property(e => e.Id).HasColumnName("id");
|
||||||
|
// Map DateOnly -> date SQL
|
||||||
|
entity.Property(e => e.DateHistorique)
|
||||||
|
.HasConversion(
|
||||||
|
v => v.ToDateTime(TimeOnly.MinValue), // vers SQL
|
||||||
|
v => DateOnly.FromDateTime(v) // depuis SQL
|
||||||
|
)
|
||||||
|
.HasColumnType("date");
|
||||||
|
entity.Property(e => e.RecetteId).HasColumnName("recetteId");
|
||||||
|
entity.Property(e => e.UserId).HasColumnName("userId");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity<Ingredient>(entity =>
|
||||||
|
{
|
||||||
|
entity.Property(e => e.Id).HasColumnName("id");
|
||||||
|
entity.Property(e => e.NameOwnedIngredients).HasColumnName("nameOwnedIngredients");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity<Recette>(entity =>
|
||||||
|
{
|
||||||
|
entity.HasNoKey();
|
||||||
|
|
||||||
|
entity.Property(e => e.Description).HasColumnName("description");
|
||||||
|
entity.Property(e => e.Difficulte)
|
||||||
|
.HasMaxLength(50)
|
||||||
|
.HasColumnName("difficulte");
|
||||||
|
entity.Property(e => e.Id).HasColumnName("id");
|
||||||
|
entity.Property(e => e.Image).HasColumnName("image");
|
||||||
|
entity.Property(e => e.Ingredients).HasColumnName("ingredients");
|
||||||
|
entity.Property(e => e.IngredientsToHad).HasColumnName("ingredientsToHad");
|
||||||
|
entity.Property(e => e.Kcal)
|
||||||
|
.HasMaxLength(10)
|
||||||
|
.IsFixedLength()
|
||||||
|
.HasColumnName("kcal");
|
||||||
|
entity.Property(e => e.Name).HasColumnName("name");
|
||||||
|
entity.Property(e => e.Pdf).HasColumnName("pdf");
|
||||||
|
entity.Property(e => e.Preference).HasColumnName("preference");
|
||||||
|
entity.Property(e => e.Proteines)
|
||||||
|
.HasMaxLength(10)
|
||||||
|
.IsFixedLength()
|
||||||
|
.HasColumnName("proteines");
|
||||||
|
entity.Property(e => e.Slug).HasColumnName("slug");
|
||||||
|
entity.Property(e => e.SupplementText).HasColumnName("supplementText");
|
||||||
|
entity.Property(e => e.Tags).HasColumnName("tags");
|
||||||
|
entity.Property(e => e.TempsDePreparation).HasColumnName("tempsDePreparation");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity<SavingRecette>(entity =>
|
||||||
|
{
|
||||||
|
entity.Property(e => e.Id).HasColumnName("id");
|
||||||
|
entity.Property(e => e.IdSavingRecette).HasColumnName("idSavingRecette");
|
||||||
|
entity.Property(e => e.UserId).HasColumnName("userId");
|
||||||
|
});
|
||||||
|
|
||||||
|
OnModelCreatingPartial(modelBuilder);
|
||||||
|
}
|
||||||
|
|
||||||
|
partial void OnModelCreatingPartial(ModelBuilder modelBuilder);
|
||||||
|
}
|
||||||
15
Models/HelloFresh/HistoriqueRecette.cs
Normal file
15
Models/HelloFresh/HistoriqueRecette.cs
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace administration.Models.HelloFresh;
|
||||||
|
|
||||||
|
public partial class HistoriqueRecette
|
||||||
|
{
|
||||||
|
public int Id { get; set; }
|
||||||
|
|
||||||
|
public string RecetteId { get; set; } = ""; // <-- string pour matcher Recette.Id
|
||||||
|
|
||||||
|
public int UserId { get; set; }
|
||||||
|
|
||||||
|
public DateOnly DateHistorique { get; set; }
|
||||||
|
}
|
||||||
11
Models/HelloFresh/Ingredient.cs
Normal file
11
Models/HelloFresh/Ingredient.cs
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace administration.Models.HelloFresh;
|
||||||
|
|
||||||
|
public partial class Ingredient
|
||||||
|
{
|
||||||
|
public int Id { get; set; }
|
||||||
|
|
||||||
|
public string NameOwnedIngredients { get; set; } = null!;
|
||||||
|
}
|
||||||
37
Models/HelloFresh/Recette.cs
Normal file
37
Models/HelloFresh/Recette.cs
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace administration.Models.HelloFresh;
|
||||||
|
|
||||||
|
public partial class Recette
|
||||||
|
{
|
||||||
|
public string Id { get; set; } = null!;
|
||||||
|
|
||||||
|
public string? Name { get; set; }
|
||||||
|
|
||||||
|
public string? SupplementText { get; set; }
|
||||||
|
|
||||||
|
public string? Description { get; set; }
|
||||||
|
|
||||||
|
public string? Tags { get; set; }
|
||||||
|
|
||||||
|
public string? Ingredients { get; set; }
|
||||||
|
|
||||||
|
public int? Preference { get; set; }
|
||||||
|
|
||||||
|
public string? Image { get; set; }
|
||||||
|
|
||||||
|
public string? Difficulte { get; set; }
|
||||||
|
|
||||||
|
public int? TempsDePreparation { get; set; }
|
||||||
|
|
||||||
|
public string? Kcal { get; set; }
|
||||||
|
|
||||||
|
public string? Proteines { get; set; }
|
||||||
|
|
||||||
|
public string? Slug { get; set; }
|
||||||
|
|
||||||
|
public string? Pdf { get; set; }
|
||||||
|
|
||||||
|
public string? IngredientsToHad { get; set; }
|
||||||
|
}
|
||||||
13
Models/HelloFresh/SavingRecette.cs
Normal file
13
Models/HelloFresh/SavingRecette.cs
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace administration.Models.HelloFresh;
|
||||||
|
|
||||||
|
public partial class SavingRecette
|
||||||
|
{
|
||||||
|
public int Id { get; set; }
|
||||||
|
|
||||||
|
public string IdSavingRecette { get; set; } = null!;
|
||||||
|
|
||||||
|
public int UserId { get; set; }
|
||||||
|
}
|
||||||
42
Models/LayoutDataContext.cs
Normal file
42
Models/LayoutDataContext.cs
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
|
||||||
|
namespace administration.Models;
|
||||||
|
|
||||||
|
public partial class LayoutDataContext : DbContext
|
||||||
|
{
|
||||||
|
public LayoutDataContext()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public LayoutDataContext(DbContextOptions<LayoutDataContext> options)
|
||||||
|
: base(options)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual DbSet<User> Users { get; set; }
|
||||||
|
|
||||||
|
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
|
||||||
|
#warning To protect potentially sensitive information in your connection string, you should move it out of source code. You can avoid scaffolding the connection string by using the Name= syntax to read it from configuration - see https://go.microsoft.com/fwlink/?linkid=2131148. For more guidance on storing connection strings, see https://go.microsoft.com/fwlink/?LinkId=723263.
|
||||||
|
=> optionsBuilder.UseSqlServer("Server=217.154.116.43,1433;Database=LayoutData;User Id=sa;Password=Mf33ksTRLrPKSqQ4cTXitgiSN6BPBt89;TrustServerCertificate=True;");
|
||||||
|
|
||||||
|
protected override void OnModelCreating(ModelBuilder modelBuilder)
|
||||||
|
{
|
||||||
|
modelBuilder.Entity<User>(entity =>
|
||||||
|
{
|
||||||
|
entity.HasKey(e => e.Id).HasName("PK__Users__3214EC0774A20142");
|
||||||
|
|
||||||
|
entity.HasIndex(e => e.Username, "UX_Users_Username").IsUnique();
|
||||||
|
|
||||||
|
entity.Property(e => e.CreatedAt).HasDefaultValueSql("(sysdatetimeoffset())");
|
||||||
|
entity.Property(e => e.PasswordHash).HasMaxLength(512);
|
||||||
|
entity.Property(e => e.ResetToken).HasMaxLength(256);
|
||||||
|
entity.Property(e => e.Username).HasMaxLength(100);
|
||||||
|
});
|
||||||
|
|
||||||
|
OnModelCreatingPartial(modelBuilder);
|
||||||
|
}
|
||||||
|
|
||||||
|
partial void OnModelCreatingPartial(ModelBuilder modelBuilder);
|
||||||
|
}
|
||||||
@@ -7,11 +7,13 @@ public partial class User
|
|||||||
{
|
{
|
||||||
public int Id { get; set; }
|
public int Id { get; set; }
|
||||||
|
|
||||||
public string Name { get; set; } = null!;
|
public string Username { get; set; } = null!;
|
||||||
|
|
||||||
public virtual ICollection<AdditionalSource> AdditionalSources { get; set; } = new List<AdditionalSource>();
|
public string PasswordHash { get; set; } = null!;
|
||||||
|
|
||||||
public virtual ICollection<Expense> Expenses { get; set; } = new List<Expense>();
|
public string? ResetToken { get; set; }
|
||||||
|
|
||||||
public virtual ICollection<Revenue> Revenues { get; set; } = new List<Revenue>();
|
public DateTimeOffset? ResetTokenExpiresAt { get; set; }
|
||||||
|
|
||||||
|
public DateTimeOffset CreatedAt { get; set; }
|
||||||
}
|
}
|
||||||
|
|||||||
87
Program.cs
87
Program.cs
@@ -1,8 +1,13 @@
|
|||||||
using administration.Models;
|
using administration.Models;
|
||||||
|
using administration.Models.Finances;
|
||||||
|
using administration.Models.HelloFresh;
|
||||||
using administration.Services;
|
using administration.Services;
|
||||||
using Microsoft.AspNetCore.Authentication;
|
using IngredientsAI.Services;
|
||||||
using Microsoft.AspNetCore.Authorization;
|
using Microsoft.AspNetCore.Authentication.Cookies;
|
||||||
|
using Microsoft.AspNetCore.Identity;
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using System.Text.Json;
|
||||||
|
using User = administration.Models.User;
|
||||||
|
|
||||||
namespace administration
|
namespace administration
|
||||||
{
|
{
|
||||||
@@ -10,51 +15,65 @@ namespace administration
|
|||||||
{
|
{
|
||||||
public static void Main(string[] args)
|
public static void Main(string[] args)
|
||||||
{
|
{
|
||||||
// Charger les variables d'environnement depuis .env
|
|
||||||
DotNetEnv.Env.Load();
|
DotNetEnv.Env.Load();
|
||||||
|
|
||||||
var builder = WebApplication.CreateBuilder(args);
|
var builder = WebApplication.CreateBuilder(args);
|
||||||
|
|
||||||
// ==============================================
|
// ==============================================
|
||||||
// 1️⃣ Configurer la base de données
|
// 1️⃣ Base de données
|
||||||
// ==============================================
|
// ==============================================
|
||||||
var dbConnection = Environment.GetEnvironmentVariable("ADMIN_DB_CONNECTION");
|
var dbConnection = Environment.GetEnvironmentVariable("ADMIN_DB_CONNECTION");
|
||||||
if (string.IsNullOrEmpty(dbConnection))
|
if (string.IsNullOrEmpty(dbConnection))
|
||||||
throw new Exception("❌ ADMIN_DB_CONNECTION est introuvable dans les variables d'environnement.");
|
throw new Exception("❌ ADMIN_DB_CONNECTION est introuvable.");
|
||||||
|
|
||||||
builder.Services.AddDbContext<FinancesContext>(options =>
|
builder.Services.AddDbContext<FinancesContext>(options =>
|
||||||
options.UseSqlServer(dbConnection, sqlOptions => sqlOptions.EnableRetryOnFailure())
|
options.UseSqlServer(dbConnection, sqlOptions => sqlOptions.EnableRetryOnFailure()));
|
||||||
);
|
|
||||||
|
builder.Services.AddDbContext<HelloFreshContext>(options =>
|
||||||
|
options.UseSqlServer(builder.Configuration.GetConnectionString("HelloFreshConnection")));
|
||||||
|
|
||||||
|
builder.Services.AddDbContext<LayoutDataContext>(options =>
|
||||||
|
options.UseSqlServer(builder.Configuration.GetConnectionString("DefaultConnection")));
|
||||||
|
|
||||||
AppSettings.Initialize(builder.Configuration);
|
AppSettings.Initialize(builder.Configuration);
|
||||||
|
builder.Services.AddSingleton<OllamaService>();
|
||||||
|
|
||||||
// ==============================================
|
// ==============================================
|
||||||
// 2️⃣ Ajouter la session
|
// 2️⃣ Session
|
||||||
// ==============================================
|
// ==============================================
|
||||||
builder.Services.AddSession(options =>
|
builder.Services.AddSession(options =>
|
||||||
{
|
{
|
||||||
options.IdleTimeout = TimeSpan.FromMinutes(300); // Expiration session
|
options.IdleTimeout = TimeSpan.FromHours(8);
|
||||||
options.Cookie.HttpOnly = true;
|
options.Cookie.HttpOnly = true;
|
||||||
options.Cookie.IsEssential = true;
|
options.Cookie.IsEssential = true;
|
||||||
});
|
});
|
||||||
|
|
||||||
// ==============================================
|
// ==============================================
|
||||||
// 3️⃣ Ajouter l’authentification Basic
|
// 3️⃣ Authentification par cookie
|
||||||
// ==============================================
|
// ==============================================
|
||||||
builder.Services.AddAuthentication("BasicAuthentication")
|
builder.Services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
|
||||||
.AddScheme<AuthenticationSchemeOptions, BasicAuthenticationHandler>("BasicAuthentication", null);
|
.AddCookie(options =>
|
||||||
|
{
|
||||||
|
options.LoginPath = "/Connections/Login";
|
||||||
|
options.AccessDeniedPath = "/Connections/Login";
|
||||||
|
options.SlidingExpiration = true;
|
||||||
|
options.ExpireTimeSpan = TimeSpan.FromDays(14);
|
||||||
|
});
|
||||||
|
|
||||||
builder.Services.AddAuthorization();
|
builder.Services.AddAuthorization();
|
||||||
|
builder.Services.AddControllers().AddJsonOptions(o =>
|
||||||
|
{
|
||||||
|
o.JsonSerializerOptions.PropertyNamingPolicy = JsonNamingPolicy.CamelCase;
|
||||||
|
});
|
||||||
|
|
||||||
// ==============================================
|
// ==============================================
|
||||||
// 4️⃣ Ajouter MVC + dépendances
|
// 4️⃣ MVC + services
|
||||||
// ==============================================
|
// ==============================================
|
||||||
builder.Services.AddControllersWithViews();
|
builder.Services.AddControllersWithViews();
|
||||||
builder.Services.AddHttpContextAccessor();
|
builder.Services.AddHttpContextAccessor();
|
||||||
builder.Services.AddScoped<IUserSessionService, UserSessionService>();
|
builder.Services.AddScoped<IPasswordHasher<User>, PasswordHasher<User>>();
|
||||||
|
|
||||||
// ==============================================
|
// ==============================================
|
||||||
// 5️⃣ CORS pour le frontend
|
// 5️⃣ CORS
|
||||||
// ==============================================
|
// ==============================================
|
||||||
builder.Services.AddCors(options =>
|
builder.Services.AddCors(options =>
|
||||||
{
|
{
|
||||||
@@ -66,14 +85,31 @@ namespace administration
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
// ==============================================
|
|
||||||
// 6️⃣ Construire l'application
|
|
||||||
// ==============================================
|
|
||||||
var app = builder.Build();
|
|
||||||
|
|
||||||
|
builder.Services.AddHttpClient(); // déjà présent chez toi
|
||||||
|
|
||||||
|
builder.Services.AddHttpClient("ollama", (sp, client) =>
|
||||||
|
{
|
||||||
|
var cfg = sp.GetRequiredService<IConfiguration>();
|
||||||
|
var baseUrl = cfg["Ollama:Url"] ?? "http://ollama:11434";
|
||||||
|
client.BaseAddress = new Uri(baseUrl);
|
||||||
|
client.Timeout = TimeSpan.FromSeconds(25);
|
||||||
|
})
|
||||||
|
#if DEBUG
|
||||||
|
.ConfigurePrimaryHttpMessageHandler(() => new HttpClientHandler
|
||||||
|
{
|
||||||
|
ServerCertificateCustomValidationCallback = HttpClientHandler.DangerousAcceptAnyServerCertificateValidator
|
||||||
|
});
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// ...
|
||||||
|
// ...
|
||||||
|
builder.Logging.AddFilter("administration.Services.BasicAuthenticationHandler", LogLevel.Warning);
|
||||||
|
|
||||||
|
var app = builder.Build();
|
||||||
// ==============================================
|
// ==============================================
|
||||||
// 7️⃣ Middleware Pipeline
|
// 6️⃣ Pipeline
|
||||||
// ==============================================
|
|
||||||
if (!app.Environment.IsDevelopment())
|
if (!app.Environment.IsDevelopment())
|
||||||
{
|
{
|
||||||
app.UseExceptionHandler("/Home/Error");
|
app.UseExceptionHandler("/Home/Error");
|
||||||
@@ -85,14 +121,11 @@ namespace administration
|
|||||||
|
|
||||||
app.UseRouting();
|
app.UseRouting();
|
||||||
app.UseCors("AllowFrontend");
|
app.UseCors("AllowFrontend");
|
||||||
app.UseSession();
|
|
||||||
|
|
||||||
app.UseAuthentication();
|
app.UseSession(); // ✅ toujours avant auth
|
||||||
|
app.UseAuthentication(); // ✅ s'applique à tout le site
|
||||||
app.UseAuthorization();
|
app.UseAuthorization();
|
||||||
|
|
||||||
// ==============================================
|
|
||||||
// 8️⃣ Routes
|
|
||||||
// ==============================================
|
|
||||||
app.MapControllerRoute(
|
app.MapControllerRoute(
|
||||||
name: "default",
|
name: "default",
|
||||||
pattern: "{controller=Home}/{action=Index}/{id?}");
|
pattern: "{controller=Home}/{action=Index}/{id?}");
|
||||||
|
|||||||
@@ -18,8 +18,7 @@ namespace administration.Services
|
|||||||
|
|
||||||
protected override Task<AuthenticateResult> HandleAuthenticateAsync()
|
protected override Task<AuthenticateResult> HandleAuthenticateAsync()
|
||||||
{
|
{
|
||||||
if (!Request.Headers.ContainsKey("Authorization"))
|
if (!Request.Headers.ContainsKey("Authorization")) return Task.FromResult(AuthenticateResult.NoResult());
|
||||||
return Task.FromResult(AuthenticateResult.Fail("Missing Authorization Header"));
|
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,492 +0,0 @@
|
|||||||
<!DOCTYPE html>
|
|
||||||
<html lang="en">
|
|
||||||
|
|
||||||
<head>
|
|
||||||
|
|
||||||
<meta charset="utf-8">
|
|
||||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
|
||||||
<meta name="description" content="">
|
|
||||||
<meta name="author" content="">
|
|
||||||
|
|
||||||
<title>SB Admin 2 - Charts</title>
|
|
||||||
|
|
||||||
<!-- Custom fonts for this template-->
|
|
||||||
<link href="vendor/fontawesome-free/css/all.min.css" rel="stylesheet" type="text/css">
|
|
||||||
<link
|
|
||||||
href="https://fonts.googleapis.com/css?family=Nunito:200,200i,300,300i,400,400i,600,600i,700,700i,800,800i,900,900i"
|
|
||||||
rel="stylesheet">
|
|
||||||
|
|
||||||
<!-- Custom styles for this template-->
|
|
||||||
<link href="css/sb-admin-2.min.css" rel="stylesheet">
|
|
||||||
|
|
||||||
</head>
|
|
||||||
|
|
||||||
<body id="page-top">
|
|
||||||
|
|
||||||
<!-- Page Wrapper -->
|
|
||||||
<div id="wrapper">
|
|
||||||
|
|
||||||
<!-- Sidebar -->
|
|
||||||
<ul class="navbar-nav bg-gradient-primary sidebar sidebar-dark accordion" id="accordionSidebar">
|
|
||||||
|
|
||||||
<!-- Sidebar - Brand -->
|
|
||||||
<a class="sidebar-brand d-flex align-items-center justify-content-center" href="index.html">
|
|
||||||
<div class="sidebar-brand-icon rotate-n-15">
|
|
||||||
<i class="fas fa-laugh-wink"></i>
|
|
||||||
</div>
|
|
||||||
<div class="sidebar-brand-text mx-3">SB Admin <sup>2</sup></div>
|
|
||||||
</a>
|
|
||||||
|
|
||||||
<!-- Divider -->
|
|
||||||
<hr class="sidebar-divider my-0">
|
|
||||||
|
|
||||||
<!-- Nav Item - Dashboard -->
|
|
||||||
<li class="nav-item">
|
|
||||||
<a class="nav-link" href="index.html">
|
|
||||||
<i class="fas fa-fw fa-tachometer-alt"></i>
|
|
||||||
<span>Dashboard</span></a>
|
|
||||||
</li>
|
|
||||||
|
|
||||||
<!-- Divider -->
|
|
||||||
<hr class="sidebar-divider">
|
|
||||||
|
|
||||||
<!-- Heading -->
|
|
||||||
<div class="sidebar-heading">
|
|
||||||
Interface
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Nav Item - Pages Collapse Menu -->
|
|
||||||
<li class="nav-item">
|
|
||||||
<a class="nav-link collapsed" href="#" data-toggle="collapse" data-target="#collapseTwo"
|
|
||||||
aria-expanded="true" aria-controls="collapseTwo">
|
|
||||||
<i class="fas fa-fw fa-cog"></i>
|
|
||||||
<span>Components</span>
|
|
||||||
</a>
|
|
||||||
<div id="collapseTwo" class="collapse" aria-labelledby="headingTwo" data-parent="#accordionSidebar">
|
|
||||||
<div class="bg-white py-2 collapse-inner rounded">
|
|
||||||
<h6 class="collapse-header">Custom Components:</h6>
|
|
||||||
<a class="collapse-item" href="buttons.html">Buttons</a>
|
|
||||||
<a class="collapse-item" href="cards.html">Cards</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</li>
|
|
||||||
|
|
||||||
<!-- Nav Item - Utilities Collapse Menu -->
|
|
||||||
<li class="nav-item">
|
|
||||||
<a class="nav-link collapsed" href="#" data-toggle="collapse" data-target="#collapseUtilities"
|
|
||||||
aria-expanded="true" aria-controls="collapseUtilities">
|
|
||||||
<i class="fas fa-fw fa-wrench"></i>
|
|
||||||
<span>Utilities</span>
|
|
||||||
</a>
|
|
||||||
<div id="collapseUtilities" class="collapse" aria-labelledby="headingUtilities"
|
|
||||||
data-parent="#accordionSidebar">
|
|
||||||
<div class="bg-white py-2 collapse-inner rounded">
|
|
||||||
<h6 class="collapse-header">Custom Utilities:</h6>
|
|
||||||
<a class="collapse-item" href="utilities-color.html">Colors</a>
|
|
||||||
<a class="collapse-item" href="utilities-border.html">Borders</a>
|
|
||||||
<a class="collapse-item" href="utilities-animation.html">Animations</a>
|
|
||||||
<a class="collapse-item" href="utilities-other.html">Other</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</li>
|
|
||||||
|
|
||||||
<!-- Divider -->
|
|
||||||
<hr class="sidebar-divider">
|
|
||||||
|
|
||||||
<!-- Heading -->
|
|
||||||
<div class="sidebar-heading">
|
|
||||||
Addons
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Nav Item - Pages Collapse Menu -->
|
|
||||||
<li class="nav-item">
|
|
||||||
<a class="nav-link collapsed" href="#" data-toggle="collapse" data-target="#collapsePages"
|
|
||||||
aria-expanded="true" aria-controls="collapsePages">
|
|
||||||
<i class="fas fa-fw fa-folder"></i>
|
|
||||||
<span>Pages</span>
|
|
||||||
</a>
|
|
||||||
<div id="collapsePages" class="collapse" aria-labelledby="headingPages" data-parent="#accordionSidebar">
|
|
||||||
<div class="bg-white py-2 collapse-inner rounded">
|
|
||||||
<h6 class="collapse-header">Login Screens:</h6>
|
|
||||||
<a class="collapse-item" href="login.html">Login</a>
|
|
||||||
<a class="collapse-item" href="register.html">Register</a>
|
|
||||||
<a class="collapse-item" href="forgot-password.html">Forgot Password</a>
|
|
||||||
<div class="collapse-divider"></div>
|
|
||||||
<h6 class="collapse-header">Other Pages:</h6>
|
|
||||||
<a class="collapse-item" href="404.html">404 Page</a>
|
|
||||||
<a class="collapse-item" href="blank.html">Blank Page</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</li>
|
|
||||||
|
|
||||||
<!-- Nav Item - Charts -->
|
|
||||||
<li class="nav-item active">
|
|
||||||
<a class="nav-link" href="charts.html">
|
|
||||||
<i class="fas fa-fw fa-chart-area"></i>
|
|
||||||
<span>Charts</span></a>
|
|
||||||
</li>
|
|
||||||
|
|
||||||
<!-- Nav Item - Tables -->
|
|
||||||
<li class="nav-item">
|
|
||||||
<a class="nav-link" href="tables.html">
|
|
||||||
<i class="fas fa-fw fa-table"></i>
|
|
||||||
<span>Tables</span></a>
|
|
||||||
</li>
|
|
||||||
|
|
||||||
<!-- Divider -->
|
|
||||||
<hr class="sidebar-divider d-none d-md-block">
|
|
||||||
|
|
||||||
<!-- Sidebar Toggler (Sidebar) -->
|
|
||||||
<div class="text-center d-none d-md-inline">
|
|
||||||
<button class="rounded-circle border-0" id="sidebarToggle"></button>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</ul>
|
|
||||||
<!-- End of Sidebar -->
|
|
||||||
|
|
||||||
<!-- Content Wrapper -->
|
|
||||||
<div id="content-wrapper" class="d-flex flex-column">
|
|
||||||
|
|
||||||
<!-- Main Content -->
|
|
||||||
<div id="content">
|
|
||||||
|
|
||||||
<!-- Topbar -->
|
|
||||||
<nav class="navbar navbar-expand navbar-light bg-white topbar mb-4 static-top shadow">
|
|
||||||
|
|
||||||
<!-- Sidebar Toggle (Topbar) -->
|
|
||||||
<button id="sidebarToggleTop" class="btn btn-link d-md-none rounded-circle mr-3">
|
|
||||||
<i class="fa fa-bars"></i>
|
|
||||||
</button>
|
|
||||||
|
|
||||||
<!-- Topbar Search -->
|
|
||||||
<form
|
|
||||||
class="d-none d-sm-inline-block form-inline mr-auto ml-md-3 my-2 my-md-0 mw-100 navbar-search">
|
|
||||||
<div class="input-group">
|
|
||||||
<input type="text" class="form-control bg-light border-0 small" placeholder="Search for..."
|
|
||||||
aria-label="Search" aria-describedby="basic-addon2">
|
|
||||||
<div class="input-group-append">
|
|
||||||
<button class="btn btn-primary" type="button">
|
|
||||||
<i class="fas fa-search fa-sm"></i>
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
|
|
||||||
<!-- Topbar Navbar -->
|
|
||||||
<ul class="navbar-nav ml-auto">
|
|
||||||
|
|
||||||
<!-- Nav Item - Search Dropdown (Visible Only XS) -->
|
|
||||||
<li class="nav-item dropdown no-arrow d-sm-none">
|
|
||||||
<a class="nav-link dropdown-toggle" href="#" id="searchDropdown" role="button"
|
|
||||||
data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
|
|
||||||
<i class="fas fa-search fa-fw"></i>
|
|
||||||
</a>
|
|
||||||
<!-- Dropdown - Messages -->
|
|
||||||
<div class="dropdown-menu dropdown-menu-right p-3 shadow animated--grow-in"
|
|
||||||
aria-labelledby="searchDropdown">
|
|
||||||
<form class="form-inline mr-auto w-100 navbar-search">
|
|
||||||
<div class="input-group">
|
|
||||||
<input type="text" class="form-control bg-light border-0 small"
|
|
||||||
placeholder="Search for..." aria-label="Search"
|
|
||||||
aria-describedby="basic-addon2">
|
|
||||||
<div class="input-group-append">
|
|
||||||
<button class="btn btn-primary" type="button">
|
|
||||||
<i class="fas fa-search fa-sm"></i>
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
</li>
|
|
||||||
|
|
||||||
<!-- Nav Item - Alerts -->
|
|
||||||
<li class="nav-item dropdown no-arrow mx-1">
|
|
||||||
<a class="nav-link dropdown-toggle" href="#" id="alertsDropdown" role="button"
|
|
||||||
data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
|
|
||||||
<i class="fas fa-bell fa-fw"></i>
|
|
||||||
<!-- Counter - Alerts -->
|
|
||||||
<span class="badge badge-danger badge-counter">3+</span>
|
|
||||||
</a>
|
|
||||||
<!-- Dropdown - Alerts -->
|
|
||||||
<div class="dropdown-list dropdown-menu dropdown-menu-right shadow animated--grow-in"
|
|
||||||
aria-labelledby="alertsDropdown">
|
|
||||||
<h6 class="dropdown-header">
|
|
||||||
Alerts Center
|
|
||||||
</h6>
|
|
||||||
<a class="dropdown-item d-flex align-items-center" href="#">
|
|
||||||
<div class="mr-3">
|
|
||||||
<div class="icon-circle bg-primary">
|
|
||||||
<i class="fas fa-file-alt text-white"></i>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<div class="small text-gray-500">December 12, 2019</div>
|
|
||||||
<span class="font-weight-bold">A new monthly report is ready to download!</span>
|
|
||||||
</div>
|
|
||||||
</a>
|
|
||||||
<a class="dropdown-item d-flex align-items-center" href="#">
|
|
||||||
<div class="mr-3">
|
|
||||||
<div class="icon-circle bg-success">
|
|
||||||
<i class="fas fa-donate text-white"></i>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<div class="small text-gray-500">December 7, 2019</div>
|
|
||||||
$290.29 has been deposited into your account!
|
|
||||||
</div>
|
|
||||||
</a>
|
|
||||||
<a class="dropdown-item d-flex align-items-center" href="#">
|
|
||||||
<div class="mr-3">
|
|
||||||
<div class="icon-circle bg-warning">
|
|
||||||
<i class="fas fa-exclamation-triangle text-white"></i>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<div class="small text-gray-500">December 2, 2019</div>
|
|
||||||
Spending Alert: We've noticed unusually high spending for your account.
|
|
||||||
</div>
|
|
||||||
</a>
|
|
||||||
<a class="dropdown-item text-center small text-gray-500" href="#">Show All Alerts</a>
|
|
||||||
</div>
|
|
||||||
</li>
|
|
||||||
|
|
||||||
<!-- Nav Item - Messages -->
|
|
||||||
<li class="nav-item dropdown no-arrow mx-1">
|
|
||||||
<a class="nav-link dropdown-toggle" href="#" id="messagesDropdown" role="button"
|
|
||||||
data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
|
|
||||||
<i class="fas fa-envelope fa-fw"></i>
|
|
||||||
<!-- Counter - Messages -->
|
|
||||||
<span class="badge badge-danger badge-counter">7</span>
|
|
||||||
</a>
|
|
||||||
<!-- Dropdown - Messages -->
|
|
||||||
<div class="dropdown-list dropdown-menu dropdown-menu-right shadow animated--grow-in"
|
|
||||||
aria-labelledby="messagesDropdown">
|
|
||||||
<h6 class="dropdown-header">
|
|
||||||
Message Center
|
|
||||||
</h6>
|
|
||||||
<a class="dropdown-item d-flex align-items-center" href="#">
|
|
||||||
<div class="dropdown-list-image mr-3">
|
|
||||||
<img class="rounded-circle" src="img/undraw_profile_1.svg"
|
|
||||||
alt="...">
|
|
||||||
<div class="status-indicator bg-success"></div>
|
|
||||||
</div>
|
|
||||||
<div class="font-weight-bold">
|
|
||||||
<div class="text-truncate">Hi there! I am wondering if you can help me with a
|
|
||||||
problem I've been having.</div>
|
|
||||||
<div class="small text-gray-500">Emily Fowler · 58m</div>
|
|
||||||
</div>
|
|
||||||
</a>
|
|
||||||
<a class="dropdown-item d-flex align-items-center" href="#">
|
|
||||||
<div class="dropdown-list-image mr-3">
|
|
||||||
<img class="rounded-circle" src="img/undraw_profile_2.svg"
|
|
||||||
alt="...">
|
|
||||||
<div class="status-indicator"></div>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<div class="text-truncate">I have the photos that you ordered last month, how
|
|
||||||
would you like them sent to you?</div>
|
|
||||||
<div class="small text-gray-500">Jae Chun · 1d</div>
|
|
||||||
</div>
|
|
||||||
</a>
|
|
||||||
<a class="dropdown-item d-flex align-items-center" href="#">
|
|
||||||
<div class="dropdown-list-image mr-3">
|
|
||||||
<img class="rounded-circle" src="img/undraw_profile_3.svg"
|
|
||||||
alt="...">
|
|
||||||
<div class="status-indicator bg-warning"></div>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<div class="text-truncate">Last month's report looks great, I am very happy with
|
|
||||||
the progress so far, keep up the good work!</div>
|
|
||||||
<div class="small text-gray-500">Morgan Alvarez · 2d</div>
|
|
||||||
</div>
|
|
||||||
</a>
|
|
||||||
<a class="dropdown-item d-flex align-items-center" href="#">
|
|
||||||
<div class="dropdown-list-image mr-3">
|
|
||||||
<img class="rounded-circle" src="https://source.unsplash.com/Mv9hjnEUHR4/60x60"
|
|
||||||
alt="...">
|
|
||||||
<div class="status-indicator bg-success"></div>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<div class="text-truncate">Am I a good boy? The reason I ask is because someone
|
|
||||||
told me that people say this to all dogs, even if they aren't good...</div>
|
|
||||||
<div class="small text-gray-500">Chicken the Dog · 2w</div>
|
|
||||||
</div>
|
|
||||||
</a>
|
|
||||||
<a class="dropdown-item text-center small text-gray-500" href="#">Read More Messages</a>
|
|
||||||
</div>
|
|
||||||
</li>
|
|
||||||
|
|
||||||
<div class="topbar-divider d-none d-sm-block"></div>
|
|
||||||
|
|
||||||
<!-- Nav Item - User Information -->
|
|
||||||
<li class="nav-item dropdown no-arrow">
|
|
||||||
<a class="nav-link dropdown-toggle" href="#" id="userDropdown" role="button"
|
|
||||||
data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
|
|
||||||
<span class="mr-2 d-none d-lg-inline text-gray-600 small">Douglas McGee</span>
|
|
||||||
<img class="img-profile rounded-circle"
|
|
||||||
src="img/undraw_profile.svg">
|
|
||||||
</a>
|
|
||||||
<!-- Dropdown - User Information -->
|
|
||||||
<div class="dropdown-menu dropdown-menu-right shadow animated--grow-in"
|
|
||||||
aria-labelledby="userDropdown">
|
|
||||||
<a class="dropdown-item" href="#">
|
|
||||||
<i class="fas fa-user fa-sm fa-fw mr-2 text-gray-400"></i>
|
|
||||||
Profile
|
|
||||||
</a>
|
|
||||||
<a class="dropdown-item" href="#">
|
|
||||||
<i class="fas fa-cogs fa-sm fa-fw mr-2 text-gray-400"></i>
|
|
||||||
Settings
|
|
||||||
</a>
|
|
||||||
<a class="dropdown-item" href="#">
|
|
||||||
<i class="fas fa-list fa-sm fa-fw mr-2 text-gray-400"></i>
|
|
||||||
Activity Log
|
|
||||||
</a>
|
|
||||||
<div class="dropdown-divider"></div>
|
|
||||||
<a class="dropdown-item" href="#" data-toggle="modal" data-target="#logoutModal">
|
|
||||||
<i class="fas fa-sign-out-alt fa-sm fa-fw mr-2 text-gray-400"></i>
|
|
||||||
Logout
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
</li>
|
|
||||||
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
</nav>
|
|
||||||
<!-- End of Topbar -->
|
|
||||||
|
|
||||||
<!-- Begin Page Content -->
|
|
||||||
<div class="container-fluid">
|
|
||||||
|
|
||||||
<!-- Page Heading -->
|
|
||||||
<h1 class="h3 mb-2 text-gray-800">Charts</h1>
|
|
||||||
<p class="mb-4">Chart.js is a third party plugin that is used to generate the charts in this theme.
|
|
||||||
The charts below have been customized - for further customization options, please visit the <a
|
|
||||||
target="_blank" href="https://www.chartjs.org/docs/latest/">official Chart.js
|
|
||||||
documentation</a>.</p>
|
|
||||||
|
|
||||||
<!-- Content Row -->
|
|
||||||
<div class="row">
|
|
||||||
|
|
||||||
<div class="col-xl-8 col-lg-7">
|
|
||||||
|
|
||||||
<!-- Area Chart -->
|
|
||||||
<div class="card shadow mb-4">
|
|
||||||
<div class="card-header py-3">
|
|
||||||
<h6 class="m-0 font-weight-bold text-primary">Area Chart</h6>
|
|
||||||
</div>
|
|
||||||
<div class="card-body">
|
|
||||||
<div class="chart-area">
|
|
||||||
<canvas id="myAreaChart"></canvas>
|
|
||||||
</div>
|
|
||||||
<hr>
|
|
||||||
Styling for the area chart can be found in the
|
|
||||||
<code>/js/demo/chart-area-demo.js</code> file.
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Bar Chart -->
|
|
||||||
<div class="card shadow mb-4">
|
|
||||||
<div class="card-header py-3">
|
|
||||||
<h6 class="m-0 font-weight-bold text-primary">Bar Chart</h6>
|
|
||||||
</div>
|
|
||||||
<div class="card-body">
|
|
||||||
<div class="chart-bar">
|
|
||||||
<canvas id="myBarChart"></canvas>
|
|
||||||
</div>
|
|
||||||
<hr>
|
|
||||||
Styling for the bar chart can be found in the
|
|
||||||
<code>/js/demo/chart-bar-demo.js</code> file.
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Donut Chart -->
|
|
||||||
<div class="col-xl-4 col-lg-5">
|
|
||||||
<div class="card shadow mb-4">
|
|
||||||
<!-- Card Header - Dropdown -->
|
|
||||||
<div class="card-header py-3">
|
|
||||||
<h6 class="m-0 font-weight-bold text-primary">Donut Chart</h6>
|
|
||||||
</div>
|
|
||||||
<!-- Card Body -->
|
|
||||||
<div class="card-body">
|
|
||||||
<div class="chart-pie pt-4">
|
|
||||||
<canvas id="myPieChart"></canvas>
|
|
||||||
</div>
|
|
||||||
<hr>
|
|
||||||
Styling for the donut chart can be found in the
|
|
||||||
<code>/js/demo/chart-pie-demo.js</code> file.
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
<!-- /.container-fluid -->
|
|
||||||
|
|
||||||
</div>
|
|
||||||
<!-- End of Main Content -->
|
|
||||||
|
|
||||||
<!-- Footer -->
|
|
||||||
<footer class="sticky-footer bg-white">
|
|
||||||
<div class="container my-auto">
|
|
||||||
<div class="copyright text-center my-auto">
|
|
||||||
<span>Copyright © Your Website 2020</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</footer>
|
|
||||||
<!-- End of Footer -->
|
|
||||||
|
|
||||||
</div>
|
|
||||||
<!-- End of Content Wrapper -->
|
|
||||||
|
|
||||||
</div>
|
|
||||||
<!-- End of Page Wrapper -->
|
|
||||||
|
|
||||||
<!-- Scroll to Top Button-->
|
|
||||||
<a class="scroll-to-top rounded" href="#page-top">
|
|
||||||
<i class="fas fa-angle-up"></i>
|
|
||||||
</a>
|
|
||||||
|
|
||||||
<!-- Logout Modal-->
|
|
||||||
<div class="modal fade" id="logoutModal" tabindex="-1" role="dialog" aria-labelledby="exampleModalLabel"
|
|
||||||
aria-hidden="true">
|
|
||||||
<div class="modal-dialog" role="document">
|
|
||||||
<div class="modal-content">
|
|
||||||
<div class="modal-header">
|
|
||||||
<h5 class="modal-title" id="exampleModalLabel">Ready to Leave?</h5>
|
|
||||||
<button class="close" type="button" data-dismiss="modal" aria-label="Close">
|
|
||||||
<span aria-hidden="true">×</span>
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
<div class="modal-body">Select "Logout" below if you are ready to end your current session.</div>
|
|
||||||
<div class="modal-footer">
|
|
||||||
<button class="btn btn-secondary" type="button" data-dismiss="modal">Cancel</button>
|
|
||||||
<a class="btn btn-primary" href="login.html">Logout</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Bootstrap core JavaScript-->
|
|
||||||
<script src="vendor/jquery/jquery.min.js"></script>
|
|
||||||
<script src="vendor/bootstrap/js/bootstrap.bundle.min.js"></script>
|
|
||||||
|
|
||||||
<!-- Core plugin JavaScript-->
|
|
||||||
<script src="vendor/jquery-easing/jquery.easing.min.js"></script>
|
|
||||||
|
|
||||||
<!-- Custom scripts for all pages-->
|
|
||||||
<script src="js/sb-admin-2.min.js"></script>
|
|
||||||
|
|
||||||
<!-- Page level plugins -->
|
|
||||||
<script src="vendor/chart.js/Chart.min.js"></script>
|
|
||||||
|
|
||||||
<!-- Page level custom scripts -->
|
|
||||||
<script src="js/demo/chart-area-demo.js"></script>
|
|
||||||
<script src="js/demo/chart-pie-demo.js"></script>
|
|
||||||
<script src="js/demo/chart-bar-demo.js"></script>
|
|
||||||
|
|
||||||
</body>
|
|
||||||
|
|
||||||
</html>
|
|
||||||
@@ -1,599 +0,0 @@
|
|||||||
<!DOCTYPE html>
|
|
||||||
<html lang="en">
|
|
||||||
|
|
||||||
<head>
|
|
||||||
|
|
||||||
<meta charset="utf-8">
|
|
||||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
|
||||||
<meta name="description" content="">
|
|
||||||
<meta name="author" content="">
|
|
||||||
|
|
||||||
<title>SB Admin 2 - Buttons</title>
|
|
||||||
|
|
||||||
<!-- Custom fonts for this template-->
|
|
||||||
<link href="vendor/fontawesome-free/css/all.min.css" rel="stylesheet" type="text/css">
|
|
||||||
<link
|
|
||||||
href="https://fonts.googleapis.com/css?family=Nunito:200,200i,300,300i,400,400i,600,600i,700,700i,800,800i,900,900i"
|
|
||||||
rel="stylesheet">
|
|
||||||
|
|
||||||
<!-- Custom styles for this template-->
|
|
||||||
<link href="css/sb-admin-2.min.css" rel="stylesheet">
|
|
||||||
|
|
||||||
</head>
|
|
||||||
|
|
||||||
<body id="page-top">
|
|
||||||
|
|
||||||
<!-- Page Wrapper -->
|
|
||||||
<div id="wrapper">
|
|
||||||
|
|
||||||
<!-- Sidebar -->
|
|
||||||
<ul class="navbar-nav bg-gradient-primary sidebar sidebar-dark accordion" id="accordionSidebar">
|
|
||||||
|
|
||||||
<!-- Sidebar - Brand -->
|
|
||||||
<a class="sidebar-brand d-flex align-items-center justify-content-center" href="index.html">
|
|
||||||
<div class="sidebar-brand-icon rotate-n-15">
|
|
||||||
<i class="fas fa-laugh-wink"></i>
|
|
||||||
</div>
|
|
||||||
<div class="sidebar-brand-text mx-3">SB Admin <sup>2</sup></div>
|
|
||||||
</a>
|
|
||||||
|
|
||||||
<!-- Divider -->
|
|
||||||
<hr class="sidebar-divider my-0">
|
|
||||||
|
|
||||||
<!-- Nav Item - Dashboard -->
|
|
||||||
<li class="nav-item">
|
|
||||||
<a class="nav-link" href="index.html">
|
|
||||||
<i class="fas fa-fw fa-tachometer-alt"></i>
|
|
||||||
<span>Dashboard</span></a>
|
|
||||||
</li>
|
|
||||||
|
|
||||||
<!-- Divider -->
|
|
||||||
<hr class="sidebar-divider">
|
|
||||||
|
|
||||||
<!-- Heading -->
|
|
||||||
<div class="sidebar-heading">
|
|
||||||
Interface
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Nav Item - Pages Collapse Menu -->
|
|
||||||
<li class="nav-item active">
|
|
||||||
<a class="nav-link" href="#" data-toggle="collapse" data-target="#collapseTwo" aria-expanded="true"
|
|
||||||
aria-controls="collapseTwo">
|
|
||||||
<i class="fas fa-fw fa-cog"></i>
|
|
||||||
<span>Components</span>
|
|
||||||
</a>
|
|
||||||
<div id="collapseTwo" class="collapse show" aria-labelledby="headingTwo"
|
|
||||||
data-parent="#accordionSidebar">
|
|
||||||
<div class="bg-white py-2 collapse-inner rounded">
|
|
||||||
<h6 class="collapse-header">Custom Components:</h6>
|
|
||||||
<a class="collapse-item active" href="buttons.html">Buttons</a>
|
|
||||||
<a class="collapse-item" href="cards.html">Cards</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</li>
|
|
||||||
|
|
||||||
<!-- Nav Item - Utilities Collapse Menu -->
|
|
||||||
<li class="nav-item">
|
|
||||||
<a class="nav-link collapsed" href="#" data-toggle="collapse" data-target="#collapseUtilities"
|
|
||||||
aria-expanded="true" aria-controls="collapseUtilities">
|
|
||||||
<i class="fas fa-fw fa-wrench"></i>
|
|
||||||
<span>Utilities</span>
|
|
||||||
</a>
|
|
||||||
<div id="collapseUtilities" class="collapse" aria-labelledby="headingUtilities"
|
|
||||||
data-parent="#accordionSidebar">
|
|
||||||
<div class="bg-white py-2 collapse-inner rounded">
|
|
||||||
<h6 class="collapse-header">Custom Utilities:</h6>
|
|
||||||
<a class="collapse-item" href="utilities-color.html">Colors</a>
|
|
||||||
<a class="collapse-item" href="utilities-border.html">Borders</a>
|
|
||||||
<a class="collapse-item" href="utilities-animation.html">Animations</a>
|
|
||||||
<a class="collapse-item" href="utilities-other.html">Other</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</li>
|
|
||||||
|
|
||||||
<!-- Divider -->
|
|
||||||
<hr class="sidebar-divider">
|
|
||||||
|
|
||||||
<!-- Heading -->
|
|
||||||
<div class="sidebar-heading">
|
|
||||||
Addons
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Nav Item - Pages Collapse Menu -->
|
|
||||||
<li class="nav-item">
|
|
||||||
<a class="nav-link collapsed" href="#" data-toggle="collapse" data-target="#collapsePages"
|
|
||||||
aria-expanded="true" aria-controls="collapsePages">
|
|
||||||
<i class="fas fa-fw fa-folder"></i>
|
|
||||||
<span>Pages</span>
|
|
||||||
</a>
|
|
||||||
<div id="collapsePages" class="collapse" aria-labelledby="headingPages" data-parent="#accordionSidebar">
|
|
||||||
<div class="bg-white py-2 collapse-inner rounded">
|
|
||||||
<h6 class="collapse-header">Login Screens:</h6>
|
|
||||||
<a class="collapse-item" href="login.html">Login</a>
|
|
||||||
<a class="collapse-item" href="register.html">Register</a>
|
|
||||||
<a class="collapse-item" href="forgot-password.html">Forgot Password</a>
|
|
||||||
<div class="collapse-divider"></div>
|
|
||||||
<h6 class="collapse-header">Other Pages:</h6>
|
|
||||||
<a class="collapse-item" href="404.html">404 Page</a>
|
|
||||||
<a class="collapse-item" href="blank.html">Blank Page</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</li>
|
|
||||||
|
|
||||||
<!-- Nav Item - Charts -->
|
|
||||||
<li class="nav-item">
|
|
||||||
<a class="nav-link" href="charts.html">
|
|
||||||
<i class="fas fa-fw fa-chart-area"></i>
|
|
||||||
<span>Charts</span></a>
|
|
||||||
</li>
|
|
||||||
|
|
||||||
<!-- Nav Item - Tables -->
|
|
||||||
<li class="nav-item">
|
|
||||||
<a class="nav-link" href="tables.html">
|
|
||||||
<i class="fas fa-fw fa-table"></i>
|
|
||||||
<span>Tables</span></a>
|
|
||||||
</li>
|
|
||||||
|
|
||||||
<!-- Divider -->
|
|
||||||
<hr class="sidebar-divider d-none d-md-block">
|
|
||||||
|
|
||||||
<!-- Sidebar Toggler (Sidebar) -->
|
|
||||||
<div class="text-center d-none d-md-inline">
|
|
||||||
<button class="rounded-circle border-0" id="sidebarToggle"></button>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</ul>
|
|
||||||
<!-- End of Sidebar -->
|
|
||||||
|
|
||||||
<!-- Content Wrapper -->
|
|
||||||
<div id="content-wrapper" class="d-flex flex-column">
|
|
||||||
|
|
||||||
<!-- Main Content -->
|
|
||||||
<div id="content">
|
|
||||||
|
|
||||||
<!-- Topbar -->
|
|
||||||
<nav class="navbar navbar-expand navbar-light bg-white topbar mb-4 static-top shadow">
|
|
||||||
|
|
||||||
<!-- Sidebar Toggle (Topbar) -->
|
|
||||||
<button id="sidebarToggleTop" class="btn btn-link d-md-none rounded-circle mr-3">
|
|
||||||
<i class="fa fa-bars"></i>
|
|
||||||
</button>
|
|
||||||
|
|
||||||
<!-- Topbar Search -->
|
|
||||||
<form
|
|
||||||
class="d-none d-sm-inline-block form-inline mr-auto ml-md-3 my-2 my-md-0 mw-100 navbar-search">
|
|
||||||
<div class="input-group">
|
|
||||||
<input type="text" class="form-control bg-light border-0 small" placeholder="Search for..."
|
|
||||||
aria-label="Search" aria-describedby="basic-addon2">
|
|
||||||
<div class="input-group-append">
|
|
||||||
<button class="btn btn-primary" type="button">
|
|
||||||
<i class="fas fa-search fa-sm"></i>
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
|
|
||||||
<!-- Topbar Navbar -->
|
|
||||||
<ul class="navbar-nav ml-auto">
|
|
||||||
|
|
||||||
<!-- Nav Item - Search Dropdown (Visible Only XS) -->
|
|
||||||
<li class="nav-item dropdown no-arrow d-sm-none">
|
|
||||||
<a class="nav-link dropdown-toggle" href="#" id="searchDropdown" role="button"
|
|
||||||
data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
|
|
||||||
<i class="fas fa-search fa-fw"></i>
|
|
||||||
</a>
|
|
||||||
<!-- Dropdown - Messages -->
|
|
||||||
<div class="dropdown-menu dropdown-menu-right p-3 shadow animated--grow-in"
|
|
||||||
aria-labelledby="searchDropdown">
|
|
||||||
<form class="form-inline mr-auto w-100 navbar-search">
|
|
||||||
<div class="input-group">
|
|
||||||
<input type="text" class="form-control bg-light border-0 small"
|
|
||||||
placeholder="Search for..." aria-label="Search"
|
|
||||||
aria-describedby="basic-addon2">
|
|
||||||
<div class="input-group-append">
|
|
||||||
<button class="btn btn-primary" type="button">
|
|
||||||
<i class="fas fa-search fa-sm"></i>
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
</li>
|
|
||||||
|
|
||||||
<!-- Nav Item - Alerts -->
|
|
||||||
<li class="nav-item dropdown no-arrow mx-1">
|
|
||||||
<a class="nav-link dropdown-toggle" href="#" id="alertsDropdown" role="button"
|
|
||||||
data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
|
|
||||||
<i class="fas fa-bell fa-fw"></i>
|
|
||||||
<!-- Counter - Alerts -->
|
|
||||||
<span class="badge badge-danger badge-counter">3+</span>
|
|
||||||
</a>
|
|
||||||
<!-- Dropdown - Alerts -->
|
|
||||||
<div class="dropdown-list dropdown-menu dropdown-menu-right shadow animated--grow-in"
|
|
||||||
aria-labelledby="alertsDropdown">
|
|
||||||
<h6 class="dropdown-header">
|
|
||||||
Alerts Center
|
|
||||||
</h6>
|
|
||||||
<a class="dropdown-item d-flex align-items-center" href="#">
|
|
||||||
<div class="mr-3">
|
|
||||||
<div class="icon-circle bg-primary">
|
|
||||||
<i class="fas fa-file-alt text-white"></i>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<div class="small text-gray-500">December 12, 2019</div>
|
|
||||||
<span class="font-weight-bold">A new monthly report is ready to download!</span>
|
|
||||||
</div>
|
|
||||||
</a>
|
|
||||||
<a class="dropdown-item d-flex align-items-center" href="#">
|
|
||||||
<div class="mr-3">
|
|
||||||
<div class="icon-circle bg-success">
|
|
||||||
<i class="fas fa-donate text-white"></i>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<div class="small text-gray-500">December 7, 2019</div>
|
|
||||||
$290.29 has been deposited into your account!
|
|
||||||
</div>
|
|
||||||
</a>
|
|
||||||
<a class="dropdown-item d-flex align-items-center" href="#">
|
|
||||||
<div class="mr-3">
|
|
||||||
<div class="icon-circle bg-warning">
|
|
||||||
<i class="fas fa-exclamation-triangle text-white"></i>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<div class="small text-gray-500">December 2, 2019</div>
|
|
||||||
Spending Alert: We've noticed unusually high spending for your account.
|
|
||||||
</div>
|
|
||||||
</a>
|
|
||||||
<a class="dropdown-item text-center small text-gray-500" href="#">Show All Alerts</a>
|
|
||||||
</div>
|
|
||||||
</li>
|
|
||||||
|
|
||||||
<!-- Nav Item - Messages -->
|
|
||||||
<li class="nav-item dropdown no-arrow mx-1">
|
|
||||||
<a class="nav-link dropdown-toggle" href="#" id="messagesDropdown" role="button"
|
|
||||||
data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
|
|
||||||
<i class="fas fa-envelope fa-fw"></i>
|
|
||||||
<!-- Counter - Messages -->
|
|
||||||
<span class="badge badge-danger badge-counter">7</span>
|
|
||||||
</a>
|
|
||||||
<!-- Dropdown - Messages -->
|
|
||||||
<div class="dropdown-list dropdown-menu dropdown-menu-right shadow animated--grow-in"
|
|
||||||
aria-labelledby="messagesDropdown">
|
|
||||||
<h6 class="dropdown-header">
|
|
||||||
Message Center
|
|
||||||
</h6>
|
|
||||||
<a class="dropdown-item d-flex align-items-center" href="#">
|
|
||||||
<div class="dropdown-list-image mr-3">
|
|
||||||
<img class="rounded-circle" src="img/undraw_profile_1.svg"
|
|
||||||
alt="...">
|
|
||||||
<div class="status-indicator bg-success"></div>
|
|
||||||
</div>
|
|
||||||
<div class="font-weight-bold">
|
|
||||||
<div class="text-truncate">Hi there! I am wondering if you can help me with a
|
|
||||||
problem I've been having.</div>
|
|
||||||
<div class="small text-gray-500">Emily Fowler · 58m</div>
|
|
||||||
</div>
|
|
||||||
</a>
|
|
||||||
<a class="dropdown-item d-flex align-items-center" href="#">
|
|
||||||
<div class="dropdown-list-image mr-3">
|
|
||||||
<img class="rounded-circle" src="img/undraw_profile_2.svg"
|
|
||||||
alt="...">
|
|
||||||
<div class="status-indicator"></div>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<div class="text-truncate">I have the photos that you ordered last month, how
|
|
||||||
would you like them sent to you?</div>
|
|
||||||
<div class="small text-gray-500">Jae Chun · 1d</div>
|
|
||||||
</div>
|
|
||||||
</a>
|
|
||||||
<a class="dropdown-item d-flex align-items-center" href="#">
|
|
||||||
<div class="dropdown-list-image mr-3">
|
|
||||||
<img class="rounded-circle" src="img/undraw_profile_3.svg"
|
|
||||||
alt="...">
|
|
||||||
<div class="status-indicator bg-warning"></div>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<div class="text-truncate">Last month's report looks great, I am very happy with
|
|
||||||
the progress so far, keep up the good work!</div>
|
|
||||||
<div class="small text-gray-500">Morgan Alvarez · 2d</div>
|
|
||||||
</div>
|
|
||||||
</a>
|
|
||||||
<a class="dropdown-item d-flex align-items-center" href="#">
|
|
||||||
<div class="dropdown-list-image mr-3">
|
|
||||||
<img class="rounded-circle" src="https://source.unsplash.com/Mv9hjnEUHR4/60x60"
|
|
||||||
alt="...">
|
|
||||||
<div class="status-indicator bg-success"></div>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<div class="text-truncate">Am I a good boy? The reason I ask is because someone
|
|
||||||
told me that people say this to all dogs, even if they aren't good...</div>
|
|
||||||
<div class="small text-gray-500">Chicken the Dog · 2w</div>
|
|
||||||
</div>
|
|
||||||
</a>
|
|
||||||
<a class="dropdown-item text-center small text-gray-500" href="#">Read More Messages</a>
|
|
||||||
</div>
|
|
||||||
</li>
|
|
||||||
|
|
||||||
<div class="topbar-divider d-none d-sm-block"></div>
|
|
||||||
|
|
||||||
<!-- Nav Item - User Information -->
|
|
||||||
<li class="nav-item dropdown no-arrow">
|
|
||||||
<a class="nav-link dropdown-toggle" href="#" id="userDropdown" role="button"
|
|
||||||
data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
|
|
||||||
<span class="mr-2 d-none d-lg-inline text-gray-600 small">Douglas McGee</span>
|
|
||||||
<img class="img-profile rounded-circle"
|
|
||||||
src="img/undraw_profile.svg">
|
|
||||||
</a>
|
|
||||||
<!-- Dropdown - User Information -->
|
|
||||||
<div class="dropdown-menu dropdown-menu-right shadow animated--grow-in"
|
|
||||||
aria-labelledby="userDropdown">
|
|
||||||
<a class="dropdown-item" href="#">
|
|
||||||
<i class="fas fa-user fa-sm fa-fw mr-2 text-gray-400"></i>
|
|
||||||
Profile
|
|
||||||
</a>
|
|
||||||
<a class="dropdown-item" href="#">
|
|
||||||
<i class="fas fa-cogs fa-sm fa-fw mr-2 text-gray-400"></i>
|
|
||||||
Settings
|
|
||||||
</a>
|
|
||||||
<a class="dropdown-item" href="#">
|
|
||||||
<i class="fas fa-list fa-sm fa-fw mr-2 text-gray-400"></i>
|
|
||||||
Activity Log
|
|
||||||
</a>
|
|
||||||
<div class="dropdown-divider"></div>
|
|
||||||
<a class="dropdown-item" href="#" data-toggle="modal" data-target="#logoutModal">
|
|
||||||
<i class="fas fa-sign-out-alt fa-sm fa-fw mr-2 text-gray-400"></i>
|
|
||||||
Logout
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
</li>
|
|
||||||
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
</nav>
|
|
||||||
<!-- End of Topbar -->
|
|
||||||
|
|
||||||
<!-- Begin Page Content -->
|
|
||||||
<div class="container-fluid">
|
|
||||||
|
|
||||||
<!-- Page Heading -->
|
|
||||||
<h1 class="h3 mb-4 text-gray-800">Buttons</h1>
|
|
||||||
|
|
||||||
<div class="row">
|
|
||||||
|
|
||||||
<div class="col-lg-6">
|
|
||||||
|
|
||||||
<!-- Circle Buttons -->
|
|
||||||
<div class="card shadow mb-4">
|
|
||||||
<div class="card-header py-3">
|
|
||||||
<h6 class="m-0 font-weight-bold text-primary">Circle Buttons</h6>
|
|
||||||
</div>
|
|
||||||
<div class="card-body">
|
|
||||||
<p>Use Font Awesome Icons (included with this theme package) along with the circle
|
|
||||||
buttons as shown in the examples below!</p>
|
|
||||||
<!-- Circle Buttons (Default) -->
|
|
||||||
<div class="mb-2">
|
|
||||||
<code>.btn-circle</code>
|
|
||||||
</div>
|
|
||||||
<a href="#" class="btn btn-primary btn-circle">
|
|
||||||
<i class="fab fa-facebook-f"></i>
|
|
||||||
</a>
|
|
||||||
<a href="#" class="btn btn-success btn-circle">
|
|
||||||
<i class="fas fa-check"></i>
|
|
||||||
</a>
|
|
||||||
<a href="#" class="btn btn-info btn-circle">
|
|
||||||
<i class="fas fa-info-circle"></i>
|
|
||||||
</a>
|
|
||||||
<a href="#" class="btn btn-warning btn-circle">
|
|
||||||
<i class="fas fa-exclamation-triangle"></i>
|
|
||||||
</a>
|
|
||||||
<a href="#" class="btn btn-danger btn-circle">
|
|
||||||
<i class="fas fa-trash"></i>
|
|
||||||
</a>
|
|
||||||
<!-- Circle Buttons (Small) -->
|
|
||||||
<div class="mt-4 mb-2">
|
|
||||||
<code>.btn-circle .btn-sm</code>
|
|
||||||
</div>
|
|
||||||
<a href="#" class="btn btn-primary btn-circle btn-sm">
|
|
||||||
<i class="fab fa-facebook-f"></i>
|
|
||||||
</a>
|
|
||||||
<a href="#" class="btn btn-success btn-circle btn-sm">
|
|
||||||
<i class="fas fa-check"></i>
|
|
||||||
</a>
|
|
||||||
<a href="#" class="btn btn-info btn-circle btn-sm">
|
|
||||||
<i class="fas fa-info-circle"></i>
|
|
||||||
</a>
|
|
||||||
<a href="#" class="btn btn-warning btn-circle btn-sm">
|
|
||||||
<i class="fas fa-exclamation-triangle"></i>
|
|
||||||
</a>
|
|
||||||
<a href="#" class="btn btn-danger btn-circle btn-sm">
|
|
||||||
<i class="fas fa-trash"></i>
|
|
||||||
</a>
|
|
||||||
<!-- Circle Buttons (Large) -->
|
|
||||||
<div class="mt-4 mb-2">
|
|
||||||
<code>.btn-circle .btn-lg</code>
|
|
||||||
</div>
|
|
||||||
<a href="#" class="btn btn-primary btn-circle btn-lg">
|
|
||||||
<i class="fab fa-facebook-f"></i>
|
|
||||||
</a>
|
|
||||||
<a href="#" class="btn btn-success btn-circle btn-lg">
|
|
||||||
<i class="fas fa-check"></i>
|
|
||||||
</a>
|
|
||||||
<a href="#" class="btn btn-info btn-circle btn-lg">
|
|
||||||
<i class="fas fa-info-circle"></i>
|
|
||||||
</a>
|
|
||||||
<a href="#" class="btn btn-warning btn-circle btn-lg">
|
|
||||||
<i class="fas fa-exclamation-triangle"></i>
|
|
||||||
</a>
|
|
||||||
<a href="#" class="btn btn-danger btn-circle btn-lg">
|
|
||||||
<i class="fas fa-trash"></i>
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Brand Buttons -->
|
|
||||||
<div class="card shadow mb-4">
|
|
||||||
<div class="card-header py-3">
|
|
||||||
<h6 class="m-0 font-weight-bold text-primary">Brand Buttons</h6>
|
|
||||||
</div>
|
|
||||||
<div class="card-body">
|
|
||||||
<p>Google and Facebook buttons are available featuring each company's respective
|
|
||||||
brand color. They are used on the user login and registration pages.</p>
|
|
||||||
<p>You can create more custom buttons by adding a new color variable in the
|
|
||||||
<code>_variables.scss</code> file and then using the Bootstrap button variant
|
|
||||||
mixin to create a new style, as demonstrated in the <code>_buttons.scss</code>
|
|
||||||
file.</p>
|
|
||||||
<a href="#" class="btn btn-google btn-block"><i class="fab fa-google fa-fw"></i>
|
|
||||||
.btn-google</a>
|
|
||||||
<a href="#" class="btn btn-facebook btn-block"><i
|
|
||||||
class="fab fa-facebook-f fa-fw"></i> .btn-facebook</a>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="col-lg-6">
|
|
||||||
|
|
||||||
<div class="card shadow mb-4">
|
|
||||||
<div class="card-header py-3">
|
|
||||||
<h6 class="m-0 font-weight-bold text-primary">Split Buttons with Icon</h6>
|
|
||||||
</div>
|
|
||||||
<div class="card-body">
|
|
||||||
<p>Works with any button colors, just use the <code>.btn-icon-split</code> class and
|
|
||||||
the markup in the examples below. The examples below also use the
|
|
||||||
<code>.text-white-50</code> helper class on the icons for additional styling,
|
|
||||||
but it is not required.</p>
|
|
||||||
<a href="#" class="btn btn-primary btn-icon-split">
|
|
||||||
<span class="icon text-white-50">
|
|
||||||
<i class="fas fa-flag"></i>
|
|
||||||
</span>
|
|
||||||
<span class="text">Split Button Primary</span>
|
|
||||||
</a>
|
|
||||||
<div class="my-2"></div>
|
|
||||||
<a href="#" class="btn btn-success btn-icon-split">
|
|
||||||
<span class="icon text-white-50">
|
|
||||||
<i class="fas fa-check"></i>
|
|
||||||
</span>
|
|
||||||
<span class="text">Split Button Success</span>
|
|
||||||
</a>
|
|
||||||
<div class="my-2"></div>
|
|
||||||
<a href="#" class="btn btn-info btn-icon-split">
|
|
||||||
<span class="icon text-white-50">
|
|
||||||
<i class="fas fa-info-circle"></i>
|
|
||||||
</span>
|
|
||||||
<span class="text">Split Button Info</span>
|
|
||||||
</a>
|
|
||||||
<div class="my-2"></div>
|
|
||||||
<a href="#" class="btn btn-warning btn-icon-split">
|
|
||||||
<span class="icon text-white-50">
|
|
||||||
<i class="fas fa-exclamation-triangle"></i>
|
|
||||||
</span>
|
|
||||||
<span class="text">Split Button Warning</span>
|
|
||||||
</a>
|
|
||||||
<div class="my-2"></div>
|
|
||||||
<a href="#" class="btn btn-danger btn-icon-split">
|
|
||||||
<span class="icon text-white-50">
|
|
||||||
<i class="fas fa-trash"></i>
|
|
||||||
</span>
|
|
||||||
<span class="text">Split Button Danger</span>
|
|
||||||
</a>
|
|
||||||
<div class="my-2"></div>
|
|
||||||
<a href="#" class="btn btn-secondary btn-icon-split">
|
|
||||||
<span class="icon text-white-50">
|
|
||||||
<i class="fas fa-arrow-right"></i>
|
|
||||||
</span>
|
|
||||||
<span class="text">Split Button Secondary</span>
|
|
||||||
</a>
|
|
||||||
<div class="my-2"></div>
|
|
||||||
<a href="#" class="btn btn-light btn-icon-split">
|
|
||||||
<span class="icon text-gray-600">
|
|
||||||
<i class="fas fa-arrow-right"></i>
|
|
||||||
</span>
|
|
||||||
<span class="text">Split Button Light</span>
|
|
||||||
</a>
|
|
||||||
<div class="mb-4"></div>
|
|
||||||
<p>Also works with small and large button classes!</p>
|
|
||||||
<a href="#" class="btn btn-primary btn-icon-split btn-sm">
|
|
||||||
<span class="icon text-white-50">
|
|
||||||
<i class="fas fa-flag"></i>
|
|
||||||
</span>
|
|
||||||
<span class="text">Split Button Small</span>
|
|
||||||
</a>
|
|
||||||
<div class="my-2"></div>
|
|
||||||
<a href="#" class="btn btn-primary btn-icon-split btn-lg">
|
|
||||||
<span class="icon text-white-50">
|
|
||||||
<i class="fas fa-flag"></i>
|
|
||||||
</span>
|
|
||||||
<span class="text">Split Button Large</span>
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
<!-- /.container-fluid -->
|
|
||||||
|
|
||||||
</div>
|
|
||||||
<!-- End of Main Content -->
|
|
||||||
|
|
||||||
<!-- Footer -->
|
|
||||||
<footer class="sticky-footer bg-white">
|
|
||||||
<div class="container my-auto">
|
|
||||||
<div class="copyright text-center my-auto">
|
|
||||||
<span>Copyright © Your Website 2020</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</footer>
|
|
||||||
<!-- End of Footer -->
|
|
||||||
|
|
||||||
</div>
|
|
||||||
<!-- End of Content Wrapper -->
|
|
||||||
|
|
||||||
</div>
|
|
||||||
<!-- End of Page Wrapper -->
|
|
||||||
|
|
||||||
<!-- Scroll to Top Button-->
|
|
||||||
<a class="scroll-to-top rounded" href="#page-top">
|
|
||||||
<i class="fas fa-angle-up"></i>
|
|
||||||
</a>
|
|
||||||
|
|
||||||
<!-- Logout Modal-->
|
|
||||||
<div class="modal fade" id="logoutModal" tabindex="-1" role="dialog" aria-labelledby="exampleModalLabel"
|
|
||||||
aria-hidden="true">
|
|
||||||
<div class="modal-dialog" role="document">
|
|
||||||
<div class="modal-content">
|
|
||||||
<div class="modal-header">
|
|
||||||
<h5 class="modal-title" id="exampleModalLabel">Ready to Leave?</h5>
|
|
||||||
<button class="close" type="button" data-dismiss="modal" aria-label="Close">
|
|
||||||
<span aria-hidden="true">×</span>
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
<div class="modal-body">Select "Logout" below if you are ready to end your current session.</div>
|
|
||||||
<div class="modal-footer">
|
|
||||||
<button class="btn btn-secondary" type="button" data-dismiss="modal">Cancel</button>
|
|
||||||
<a class="btn btn-primary" href="login.html">Logout</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Bootstrap core JavaScript-->
|
|
||||||
<script src="vendor/jquery/jquery.min.js"></script>
|
|
||||||
<script src="vendor/bootstrap/js/bootstrap.bundle.min.js"></script>
|
|
||||||
|
|
||||||
<!-- Core plugin JavaScript-->
|
|
||||||
<script src="vendor/jquery-easing/jquery.easing.min.js"></script>
|
|
||||||
|
|
||||||
<!-- Custom scripts for all pages-->
|
|
||||||
<script src="js/sb-admin-2.min.js"></script>
|
|
||||||
|
|
||||||
</body>
|
|
||||||
|
|
||||||
</html>
|
|
||||||
@@ -1,593 +0,0 @@
|
|||||||
<!DOCTYPE html>
|
|
||||||
<html lang="en">
|
|
||||||
|
|
||||||
<head>
|
|
||||||
|
|
||||||
<meta charset="utf-8">
|
|
||||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
|
||||||
<meta name="description" content="">
|
|
||||||
<meta name="author" content="">
|
|
||||||
|
|
||||||
<title>SB Admin 2 - Cards</title>
|
|
||||||
|
|
||||||
<!-- Custom fonts for this template-->
|
|
||||||
<link href="vendor/fontawesome-free/css/all.min.css" rel="stylesheet" type="text/css">
|
|
||||||
<link
|
|
||||||
href="https://fonts.googleapis.com/css?family=Nunito:200,200i,300,300i,400,400i,600,600i,700,700i,800,800i,900,900i"
|
|
||||||
rel="stylesheet">
|
|
||||||
|
|
||||||
<!-- Custom styles for this template-->
|
|
||||||
<link href="css/sb-admin-2.min.css" rel="stylesheet">
|
|
||||||
|
|
||||||
</head>
|
|
||||||
|
|
||||||
<body id="page-top">
|
|
||||||
|
|
||||||
<!-- Page Wrapper -->
|
|
||||||
<div id="wrapper">
|
|
||||||
|
|
||||||
<!-- Sidebar -->
|
|
||||||
<ul class="navbar-nav bg-gradient-primary sidebar sidebar-dark accordion" id="accordionSidebar">
|
|
||||||
|
|
||||||
<!-- Sidebar - Brand -->
|
|
||||||
<a class="sidebar-brand d-flex align-items-center justify-content-center" href="index.html">
|
|
||||||
<div class="sidebar-brand-icon rotate-n-15">
|
|
||||||
<i class="fas fa-laugh-wink"></i>
|
|
||||||
</div>
|
|
||||||
<div class="sidebar-brand-text mx-3">SB Admin <sup>2</sup></div>
|
|
||||||
</a>
|
|
||||||
|
|
||||||
<!-- Divider -->
|
|
||||||
<hr class="sidebar-divider my-0">
|
|
||||||
|
|
||||||
<!-- Nav Item - Dashboard -->
|
|
||||||
<li class="nav-item">
|
|
||||||
<a class="nav-link" href="index.html">
|
|
||||||
<i class="fas fa-fw fa-tachometer-alt"></i>
|
|
||||||
<span>Dashboard</span></a>
|
|
||||||
</li>
|
|
||||||
|
|
||||||
<!-- Divider -->
|
|
||||||
<hr class="sidebar-divider">
|
|
||||||
|
|
||||||
<!-- Heading -->
|
|
||||||
<div class="sidebar-heading">
|
|
||||||
Interface
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Nav Item - Pages Collapse Menu -->
|
|
||||||
<li class="nav-item active">
|
|
||||||
<a class="nav-link" href="#" data-toggle="collapse" data-target="#collapseTwo" aria-expanded="true"
|
|
||||||
aria-controls="collapseTwo">
|
|
||||||
<i class="fas fa-fw fa-cog"></i>
|
|
||||||
<span>Components</span>
|
|
||||||
</a>
|
|
||||||
<div id="collapseTwo" class="collapse show" aria-labelledby="headingTwo"
|
|
||||||
data-parent="#accordionSidebar">
|
|
||||||
<div class="bg-white py-2 collapse-inner rounded">
|
|
||||||
<h6 class="collapse-header">Custom Components:</h6>
|
|
||||||
<a class="collapse-item" href="buttons.html">Buttons</a>
|
|
||||||
<a class="collapse-item active" href="cards.html">Cards</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</li>
|
|
||||||
|
|
||||||
<!-- Nav Item - Utilities Collapse Menu -->
|
|
||||||
<li class="nav-item">
|
|
||||||
<a class="nav-link collapsed" href="#" data-toggle="collapse" data-target="#collapseUtilities"
|
|
||||||
aria-expanded="true" aria-controls="collapseUtilities">
|
|
||||||
<i class="fas fa-fw fa-wrench"></i>
|
|
||||||
<span>Utilities</span>
|
|
||||||
</a>
|
|
||||||
<div id="collapseUtilities" class="collapse" aria-labelledby="headingUtilities"
|
|
||||||
data-parent="#accordionSidebar">
|
|
||||||
<div class="bg-white py-2 collapse-inner rounded">
|
|
||||||
<h6 class="collapse-header">Custom Utilities:</h6>
|
|
||||||
<a class="collapse-item" href="utilities-color.html">Colors</a>
|
|
||||||
<a class="collapse-item" href="utilities-border.html">Borders</a>
|
|
||||||
<a class="collapse-item" href="utilities-animation.html">Animations</a>
|
|
||||||
<a class="collapse-item" href="utilities-other.html">Other</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</li>
|
|
||||||
|
|
||||||
<!-- Divider -->
|
|
||||||
<hr class="sidebar-divider">
|
|
||||||
|
|
||||||
<!-- Heading -->
|
|
||||||
<div class="sidebar-heading">
|
|
||||||
Addons
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Nav Item - Pages Collapse Menu -->
|
|
||||||
<li class="nav-item">
|
|
||||||
<a class="nav-link collapsed" href="#" data-toggle="collapse" data-target="#collapsePages"
|
|
||||||
aria-expanded="true" aria-controls="collapsePages">
|
|
||||||
<i class="fas fa-fw fa-folder"></i>
|
|
||||||
<span>Pages</span>
|
|
||||||
</a>
|
|
||||||
<div id="collapsePages" class="collapse" aria-labelledby="headingPages" data-parent="#accordionSidebar">
|
|
||||||
<div class="bg-white py-2 collapse-inner rounded">
|
|
||||||
<h6 class="collapse-header">Login Screens:</h6>
|
|
||||||
<a class="collapse-item" href="login.html">Login</a>
|
|
||||||
<a class="collapse-item" href="register.html">Register</a>
|
|
||||||
<a class="collapse-item" href="forgot-password.html">Forgot Password</a>
|
|
||||||
<div class="collapse-divider"></div>
|
|
||||||
<h6 class="collapse-header">Other Pages:</h6>
|
|
||||||
<a class="collapse-item" href="404.html">404 Page</a>
|
|
||||||
<a class="collapse-item" href="blank.html">Blank Page</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</li>
|
|
||||||
|
|
||||||
<!-- Nav Item - Charts -->
|
|
||||||
<li class="nav-item">
|
|
||||||
<a class="nav-link" href="charts.html">
|
|
||||||
<i class="fas fa-fw fa-chart-area"></i>
|
|
||||||
<span>Charts</span></a>
|
|
||||||
</li>
|
|
||||||
|
|
||||||
<!-- Nav Item - Tables -->
|
|
||||||
<li class="nav-item">
|
|
||||||
<a class="nav-link" href="tables.html">
|
|
||||||
<i class="fas fa-fw fa-table"></i>
|
|
||||||
<span>Tables</span></a>
|
|
||||||
</li>
|
|
||||||
|
|
||||||
<!-- Divider -->
|
|
||||||
<hr class="sidebar-divider d-none d-md-block">
|
|
||||||
|
|
||||||
<!-- Sidebar Toggler (Sidebar) -->
|
|
||||||
<div class="text-center d-none d-md-inline">
|
|
||||||
<button class="rounded-circle border-0" id="sidebarToggle"></button>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</ul>
|
|
||||||
<!-- End of Sidebar -->
|
|
||||||
|
|
||||||
<!-- Content Wrapper -->
|
|
||||||
<div id="content-wrapper" class="d-flex flex-column">
|
|
||||||
|
|
||||||
<!-- Main Content -->
|
|
||||||
<div id="content">
|
|
||||||
|
|
||||||
<!-- Topbar -->
|
|
||||||
<nav class="navbar navbar-expand navbar-light bg-white topbar mb-4 static-top shadow">
|
|
||||||
|
|
||||||
<!-- Sidebar Toggle (Topbar) -->
|
|
||||||
<button id="sidebarToggleTop" class="btn btn-link d-md-none rounded-circle mr-3">
|
|
||||||
<i class="fa fa-bars"></i>
|
|
||||||
</button>
|
|
||||||
|
|
||||||
<!-- Topbar Search -->
|
|
||||||
<form
|
|
||||||
class="d-none d-sm-inline-block form-inline mr-auto ml-md-3 my-2 my-md-0 mw-100 navbar-search">
|
|
||||||
<div class="input-group">
|
|
||||||
<input type="text" class="form-control bg-light border-0 small" placeholder="Search for..."
|
|
||||||
aria-label="Search" aria-describedby="basic-addon2">
|
|
||||||
<div class="input-group-append">
|
|
||||||
<button class="btn btn-primary" type="button">
|
|
||||||
<i class="fas fa-search fa-sm"></i>
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
|
|
||||||
<!-- Topbar Navbar -->
|
|
||||||
<ul class="navbar-nav ml-auto">
|
|
||||||
|
|
||||||
<!-- Nav Item - Search Dropdown (Visible Only XS) -->
|
|
||||||
<li class="nav-item dropdown no-arrow d-sm-none">
|
|
||||||
<a class="nav-link dropdown-toggle" href="#" id="searchDropdown" role="button"
|
|
||||||
data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
|
|
||||||
<i class="fas fa-search fa-fw"></i>
|
|
||||||
</a>
|
|
||||||
<!-- Dropdown - Messages -->
|
|
||||||
<div class="dropdown-menu dropdown-menu-right p-3 shadow animated--grow-in"
|
|
||||||
aria-labelledby="searchDropdown">
|
|
||||||
<form class="form-inline mr-auto w-100 navbar-search">
|
|
||||||
<div class="input-group">
|
|
||||||
<input type="text" class="form-control bg-light border-0 small"
|
|
||||||
placeholder="Search for..." aria-label="Search"
|
|
||||||
aria-describedby="basic-addon2">
|
|
||||||
<div class="input-group-append">
|
|
||||||
<button class="btn btn-primary" type="button">
|
|
||||||
<i class="fas fa-search fa-sm"></i>
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
</li>
|
|
||||||
|
|
||||||
<!-- Nav Item - Alerts -->
|
|
||||||
<li class="nav-item dropdown no-arrow mx-1">
|
|
||||||
<a class="nav-link dropdown-toggle" href="#" id="alertsDropdown" role="button"
|
|
||||||
data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
|
|
||||||
<i class="fas fa-bell fa-fw"></i>
|
|
||||||
<!-- Counter - Alerts -->
|
|
||||||
<span class="badge badge-danger badge-counter">3+</span>
|
|
||||||
</a>
|
|
||||||
<!-- Dropdown - Alerts -->
|
|
||||||
<div class="dropdown-list dropdown-menu dropdown-menu-right shadow animated--grow-in"
|
|
||||||
aria-labelledby="alertsDropdown">
|
|
||||||
<h6 class="dropdown-header">
|
|
||||||
Alerts Center
|
|
||||||
</h6>
|
|
||||||
<a class="dropdown-item d-flex align-items-center" href="#">
|
|
||||||
<div class="mr-3">
|
|
||||||
<div class="icon-circle bg-primary">
|
|
||||||
<i class="fas fa-file-alt text-white"></i>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<div class="small text-gray-500">December 12, 2019</div>
|
|
||||||
<span class="font-weight-bold">A new monthly report is ready to download!</span>
|
|
||||||
</div>
|
|
||||||
</a>
|
|
||||||
<a class="dropdown-item d-flex align-items-center" href="#">
|
|
||||||
<div class="mr-3">
|
|
||||||
<div class="icon-circle bg-success">
|
|
||||||
<i class="fas fa-donate text-white"></i>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<div class="small text-gray-500">December 7, 2019</div>
|
|
||||||
$290.29 has been deposited into your account!
|
|
||||||
</div>
|
|
||||||
</a>
|
|
||||||
<a class="dropdown-item d-flex align-items-center" href="#">
|
|
||||||
<div class="mr-3">
|
|
||||||
<div class="icon-circle bg-warning">
|
|
||||||
<i class="fas fa-exclamation-triangle text-white"></i>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<div class="small text-gray-500">December 2, 2019</div>
|
|
||||||
Spending Alert: We've noticed unusually high spending for your account.
|
|
||||||
</div>
|
|
||||||
</a>
|
|
||||||
<a class="dropdown-item text-center small text-gray-500" href="#">Show All Alerts</a>
|
|
||||||
</div>
|
|
||||||
</li>
|
|
||||||
|
|
||||||
<!-- Nav Item - Messages -->
|
|
||||||
<li class="nav-item dropdown no-arrow mx-1">
|
|
||||||
<a class="nav-link dropdown-toggle" href="#" id="messagesDropdown" role="button"
|
|
||||||
data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
|
|
||||||
<i class="fas fa-envelope fa-fw"></i>
|
|
||||||
<!-- Counter - Messages -->
|
|
||||||
<span class="badge badge-danger badge-counter">7</span>
|
|
||||||
</a>
|
|
||||||
<!-- Dropdown - Messages -->
|
|
||||||
<div class="dropdown-list dropdown-menu dropdown-menu-right shadow animated--grow-in"
|
|
||||||
aria-labelledby="messagesDropdown">
|
|
||||||
<h6 class="dropdown-header">
|
|
||||||
Message Center
|
|
||||||
</h6>
|
|
||||||
<a class="dropdown-item d-flex align-items-center" href="#">
|
|
||||||
<div class="dropdown-list-image mr-3">
|
|
||||||
<img class="rounded-circle" src="img/undraw_profile_1.svg"
|
|
||||||
alt="...">
|
|
||||||
<div class="status-indicator bg-success"></div>
|
|
||||||
</div>
|
|
||||||
<div class="font-weight-bold">
|
|
||||||
<div class="text-truncate">Hi there! I am wondering if you can help me with a
|
|
||||||
problem I've been having.</div>
|
|
||||||
<div class="small text-gray-500">Emily Fowler · 58m</div>
|
|
||||||
</div>
|
|
||||||
</a>
|
|
||||||
<a class="dropdown-item d-flex align-items-center" href="#">
|
|
||||||
<div class="dropdown-list-image mr-3">
|
|
||||||
<img class="rounded-circle" src="img/undraw_profile_2.svg"
|
|
||||||
alt="...">
|
|
||||||
<div class="status-indicator"></div>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<div class="text-truncate">I have the photos that you ordered last month, how
|
|
||||||
would you like them sent to you?</div>
|
|
||||||
<div class="small text-gray-500">Jae Chun · 1d</div>
|
|
||||||
</div>
|
|
||||||
</a>
|
|
||||||
<a class="dropdown-item d-flex align-items-center" href="#">
|
|
||||||
<div class="dropdown-list-image mr-3">
|
|
||||||
<img class="rounded-circle" src="img/undraw_profile_3.svg"
|
|
||||||
alt="...">
|
|
||||||
<div class="status-indicator bg-warning"></div>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<div class="text-truncate">Last month's report looks great, I am very happy with
|
|
||||||
the progress so far, keep up the good work!</div>
|
|
||||||
<div class="small text-gray-500">Morgan Alvarez · 2d</div>
|
|
||||||
</div>
|
|
||||||
</a>
|
|
||||||
<a class="dropdown-item d-flex align-items-center" href="#">
|
|
||||||
<div class="dropdown-list-image mr-3">
|
|
||||||
<img class="rounded-circle" src="https://source.unsplash.com/Mv9hjnEUHR4/60x60"
|
|
||||||
alt="...">
|
|
||||||
<div class="status-indicator bg-success"></div>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<div class="text-truncate">Am I a good boy? The reason I ask is because someone
|
|
||||||
told me that people say this to all dogs, even if they aren't good...</div>
|
|
||||||
<div class="small text-gray-500">Chicken the Dog · 2w</div>
|
|
||||||
</div>
|
|
||||||
</a>
|
|
||||||
<a class="dropdown-item text-center small text-gray-500" href="#">Read More Messages</a>
|
|
||||||
</div>
|
|
||||||
</li>
|
|
||||||
|
|
||||||
<div class="topbar-divider d-none d-sm-block"></div>
|
|
||||||
|
|
||||||
<!-- Nav Item - User Information -->
|
|
||||||
<li class="nav-item dropdown no-arrow">
|
|
||||||
<a class="nav-link dropdown-toggle" href="#" id="userDropdown" role="button"
|
|
||||||
data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
|
|
||||||
<span class="mr-2 d-none d-lg-inline text-gray-600 small">Douglas McGee</span>
|
|
||||||
<img class="img-profile rounded-circle"
|
|
||||||
src="img/undraw_profile.svg">
|
|
||||||
</a>
|
|
||||||
<!-- Dropdown - User Information -->
|
|
||||||
<div class="dropdown-menu dropdown-menu-right shadow animated--grow-in"
|
|
||||||
aria-labelledby="userDropdown">
|
|
||||||
<a class="dropdown-item" href="#">
|
|
||||||
<i class="fas fa-user fa-sm fa-fw mr-2 text-gray-400"></i>
|
|
||||||
Profile
|
|
||||||
</a>
|
|
||||||
<a class="dropdown-item" href="#">
|
|
||||||
<i class="fas fa-cogs fa-sm fa-fw mr-2 text-gray-400"></i>
|
|
||||||
Settings
|
|
||||||
</a>
|
|
||||||
<a class="dropdown-item" href="#">
|
|
||||||
<i class="fas fa-list fa-sm fa-fw mr-2 text-gray-400"></i>
|
|
||||||
Activity Log
|
|
||||||
</a>
|
|
||||||
<div class="dropdown-divider"></div>
|
|
||||||
<a class="dropdown-item" href="#" data-toggle="modal" data-target="#logoutModal">
|
|
||||||
<i class="fas fa-sign-out-alt fa-sm fa-fw mr-2 text-gray-400"></i>
|
|
||||||
Logout
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
</li>
|
|
||||||
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
</nav>
|
|
||||||
<!-- End of Topbar -->
|
|
||||||
|
|
||||||
<!-- Begin Page Content -->
|
|
||||||
<div class="container-fluid">
|
|
||||||
|
|
||||||
<!-- Page Heading -->
|
|
||||||
<div class="d-sm-flex align-items-center justify-content-between mb-4">
|
|
||||||
<h1 class="h3 mb-0 text-gray-800">Cards</h1>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="row">
|
|
||||||
|
|
||||||
<!-- Earnings (Monthly) Card Example -->
|
|
||||||
<div class="col-xl-3 col-md-6 mb-4">
|
|
||||||
<div class="card border-left-primary shadow h-100 py-2">
|
|
||||||
<div class="card-body">
|
|
||||||
<div class="row no-gutters align-items-center">
|
|
||||||
<div class="col mr-2">
|
|
||||||
<div class="text-xs font-weight-bold text-primary text-uppercase mb-1">
|
|
||||||
Earnings (Monthly)</div>
|
|
||||||
<div class="h5 mb-0 font-weight-bold text-gray-800">$40,000</div>
|
|
||||||
</div>
|
|
||||||
<div class="col-auto">
|
|
||||||
<i class="fas fa-calendar fa-2x text-gray-300"></i>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Earnings (Annual) Card Example -->
|
|
||||||
<div class="col-xl-3 col-md-6 mb-4">
|
|
||||||
<div class="card border-left-success shadow h-100 py-2">
|
|
||||||
<div class="card-body">
|
|
||||||
<div class="row no-gutters align-items-center">
|
|
||||||
<div class="col mr-2">
|
|
||||||
<div class="text-xs font-weight-bold text-success text-uppercase mb-1">
|
|
||||||
Earnings (Annual)</div>
|
|
||||||
<div class="h5 mb-0 font-weight-bold text-gray-800">$215,000</div>
|
|
||||||
</div>
|
|
||||||
<div class="col-auto">
|
|
||||||
<i class="fas fa-dollar-sign fa-2x text-gray-300"></i>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Tasks Card Example -->
|
|
||||||
<div class="col-xl-3 col-md-6 mb-4">
|
|
||||||
<div class="card border-left-info shadow h-100 py-2">
|
|
||||||
<div class="card-body">
|
|
||||||
<div class="row no-gutters align-items-center">
|
|
||||||
<div class="col mr-2">
|
|
||||||
<div class="text-xs font-weight-bold text-info text-uppercase mb-1">Tasks
|
|
||||||
</div>
|
|
||||||
<div class="row no-gutters align-items-center">
|
|
||||||
<div class="col-auto">
|
|
||||||
<div class="h5 mb-0 mr-3 font-weight-bold text-gray-800">50%</div>
|
|
||||||
</div>
|
|
||||||
<div class="col">
|
|
||||||
<div class="progress progress-sm mr-2">
|
|
||||||
<div class="progress-bar bg-info" role="progressbar"
|
|
||||||
style="width: 50%" aria-valuenow="50" aria-valuemin="0"
|
|
||||||
aria-valuemax="100"></div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="col-auto">
|
|
||||||
<i class="fas fa-clipboard-list fa-2x text-gray-300"></i>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Pending Requests Card Example -->
|
|
||||||
<div class="col-xl-3 col-md-6 mb-4">
|
|
||||||
<div class="card border-left-warning shadow h-100 py-2">
|
|
||||||
<div class="card-body">
|
|
||||||
<div class="row no-gutters align-items-center">
|
|
||||||
<div class="col mr-2">
|
|
||||||
<div class="text-xs font-weight-bold text-warning text-uppercase mb-1">
|
|
||||||
Pending Requests</div>
|
|
||||||
<div class="h5 mb-0 font-weight-bold text-gray-800">18</div>
|
|
||||||
</div>
|
|
||||||
<div class="col-auto">
|
|
||||||
<i class="fas fa-comments fa-2x text-gray-300"></i>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="row">
|
|
||||||
|
|
||||||
<div class="col-lg-6">
|
|
||||||
|
|
||||||
<!-- Default Card Example -->
|
|
||||||
<div class="card mb-4">
|
|
||||||
<div class="card-header">
|
|
||||||
Default Card Example
|
|
||||||
</div>
|
|
||||||
<div class="card-body">
|
|
||||||
This card uses Bootstrap's default styling with no utility classes added. Global
|
|
||||||
styles are the only things modifying the look and feel of this default card example.
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Basic Card Example -->
|
|
||||||
<div class="card shadow mb-4">
|
|
||||||
<div class="card-header py-3">
|
|
||||||
<h6 class="m-0 font-weight-bold text-primary">Basic Card Example</h6>
|
|
||||||
</div>
|
|
||||||
<div class="card-body">
|
|
||||||
The styling for this basic card example is created by using default Bootstrap
|
|
||||||
utility classes. By using utility classes, the style of the card component can be
|
|
||||||
easily modified with no need for any custom CSS!
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="col-lg-6">
|
|
||||||
|
|
||||||
<!-- Dropdown Card Example -->
|
|
||||||
<div class="card shadow mb-4">
|
|
||||||
<!-- Card Header - Dropdown -->
|
|
||||||
<div
|
|
||||||
class="card-header py-3 d-flex flex-row align-items-center justify-content-between">
|
|
||||||
<h6 class="m-0 font-weight-bold text-primary">Dropdown Card Example</h6>
|
|
||||||
<div class="dropdown no-arrow">
|
|
||||||
<a class="dropdown-toggle" href="#" role="button" id="dropdownMenuLink"
|
|
||||||
data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
|
|
||||||
<i class="fas fa-ellipsis-v fa-sm fa-fw text-gray-400"></i>
|
|
||||||
</a>
|
|
||||||
<div class="dropdown-menu dropdown-menu-right shadow animated--fade-in"
|
|
||||||
aria-labelledby="dropdownMenuLink">
|
|
||||||
<div class="dropdown-header">Dropdown Header:</div>
|
|
||||||
<a class="dropdown-item" href="#">Action</a>
|
|
||||||
<a class="dropdown-item" href="#">Another action</a>
|
|
||||||
<div class="dropdown-divider"></div>
|
|
||||||
<a class="dropdown-item" href="#">Something else here</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<!-- Card Body -->
|
|
||||||
<div class="card-body">
|
|
||||||
Dropdown menus can be placed in the card header in order to extend the functionality
|
|
||||||
of a basic card. In this dropdown card example, the Font Awesome vertical ellipsis
|
|
||||||
icon in the card header can be clicked on in order to toggle a dropdown menu.
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Collapsable Card Example -->
|
|
||||||
<div class="card shadow mb-4">
|
|
||||||
<!-- Card Header - Accordion -->
|
|
||||||
<a href="#collapseCardExample" class="d-block card-header py-3" data-toggle="collapse"
|
|
||||||
role="button" aria-expanded="true" aria-controls="collapseCardExample">
|
|
||||||
<h6 class="m-0 font-weight-bold text-primary">Collapsable Card Example</h6>
|
|
||||||
</a>
|
|
||||||
<!-- Card Content - Collapse -->
|
|
||||||
<div class="collapse show" id="collapseCardExample">
|
|
||||||
<div class="card-body">
|
|
||||||
This is a collapsable card example using Bootstrap's built in collapse
|
|
||||||
functionality. <strong>Click on the card header</strong> to see the card body
|
|
||||||
collapse and expand!
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
<!-- /.container-fluid -->
|
|
||||||
|
|
||||||
</div>
|
|
||||||
<!-- End of Main Content -->
|
|
||||||
|
|
||||||
<!-- Footer -->
|
|
||||||
<footer class="sticky-footer bg-white">
|
|
||||||
<div class="container my-auto">
|
|
||||||
<div class="copyright text-center my-auto">
|
|
||||||
<span>Copyright © Your Website 2020</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</footer>
|
|
||||||
<!-- End of Footer -->
|
|
||||||
|
|
||||||
</div>
|
|
||||||
<!-- End of Content Wrapper -->
|
|
||||||
|
|
||||||
</div>
|
|
||||||
<!-- End of Page Wrapper -->
|
|
||||||
|
|
||||||
<!-- Scroll to Top Button-->
|
|
||||||
<a class="scroll-to-top rounded" href="#page-top">
|
|
||||||
<i class="fas fa-angle-up"></i>
|
|
||||||
</a>
|
|
||||||
|
|
||||||
<!-- Logout Modal-->
|
|
||||||
<div class="modal fade" id="logoutModal" tabindex="-1" role="dialog" aria-labelledby="exampleModalLabel"
|
|
||||||
aria-hidden="true">
|
|
||||||
<div class="modal-dialog" role="document">
|
|
||||||
<div class="modal-content">
|
|
||||||
<div class="modal-header">
|
|
||||||
<h5 class="modal-title" id="exampleModalLabel">Ready to Leave?</h5>
|
|
||||||
<button class="close" type="button" data-dismiss="modal" aria-label="Close">
|
|
||||||
<span aria-hidden="true">×</span>
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
<div class="modal-body">Select "Logout" below if you are ready to end your current session.</div>
|
|
||||||
<div class="modal-footer">
|
|
||||||
<button class="btn btn-secondary" type="button" data-dismiss="modal">Cancel</button>
|
|
||||||
<a class="btn btn-primary" href="login.html">Logout</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Bootstrap core JavaScript-->
|
|
||||||
<script src="vendor/jquery/jquery.min.js"></script>
|
|
||||||
<script src="vendor/bootstrap/js/bootstrap.bundle.min.js"></script>
|
|
||||||
|
|
||||||
<!-- Core plugin JavaScript-->
|
|
||||||
<script src="vendor/jquery-easing/jquery.easing.min.js"></script>
|
|
||||||
|
|
||||||
<!-- Custom scripts for all pages-->
|
|
||||||
<script src="js/sb-admin-2.min.js"></script>
|
|
||||||
|
|
||||||
</body>
|
|
||||||
|
|
||||||
</html>
|
|
||||||
0
Views/Connections/3tenwfbf.n2i~
Normal file
0
Views/Connections/3tenwfbf.n2i~
Normal file
0
Views/Connections/4idojod2.b45~
Normal file
0
Views/Connections/4idojod2.b45~
Normal file
@@ -39,6 +39,14 @@
|
|||||||
<div class="col-lg-6">
|
<div class="col-lg-6">
|
||||||
<div class="p-5">
|
<div class="p-5">
|
||||||
<div class="text-center">
|
<div class="text-center">
|
||||||
|
@if (TempData["Info"] != null)
|
||||||
|
{
|
||||||
|
<div class="alert alert-info">@TempData["Info"]</div>
|
||||||
|
}
|
||||||
|
@if (TempData["ResetLink"] != null)
|
||||||
|
{
|
||||||
|
<div class="alert alert-secondary"><b>Lien (temporaire) :</b> <a href="@TempData["ResetLink"]">@TempData["ResetLink"]</a></div>
|
||||||
|
}
|
||||||
<h1 class="h4 text-gray-900 mb-2">Forgot Your Password?</h1>
|
<h1 class="h4 text-gray-900 mb-2">Forgot Your Password?</h1>
|
||||||
<p class="mb-4">We get it, stuff happens. Just enter your email address below
|
<p class="mb-4">We get it, stuff happens. Just enter your email address below
|
||||||
and we'll send you a link to reset your password!</p>
|
and we'll send you a link to reset your password!</p>
|
||||||
|
|||||||
@@ -2,6 +2,9 @@
|
|||||||
<html lang="en">
|
<html lang="en">
|
||||||
|
|
||||||
<head>
|
<head>
|
||||||
|
@{
|
||||||
|
Layout = null;
|
||||||
|
}
|
||||||
|
|
||||||
<meta charset="utf-8">
|
<meta charset="utf-8">
|
||||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||||
@@ -11,19 +14,27 @@
|
|||||||
|
|
||||||
<title>SB Admin 2 - Login</title>
|
<title>SB Admin 2 - Login</title>
|
||||||
|
|
||||||
|
<link rel="stylesheet" href="~/css/site.css" asp-append-version="true" />
|
||||||
|
<link rel="stylesheet" href="~/administration.styles.css" asp-append-version="true" />
|
||||||
|
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.1/font/bootstrap-icons.css">
|
||||||
<!-- Custom fonts for this template-->
|
<!-- Custom fonts for this template-->
|
||||||
<link href="vendor/fontawesome-free/css/all.min.css" rel="stylesheet" type="text/css">
|
<link href="https://fonts.googleapis.com/css?family=Nunito:200,300,400,600,700,800,900" rel="stylesheet">
|
||||||
<link
|
|
||||||
href="https://fonts.googleapis.com/css?family=Nunito:200,200i,300,300i,400,400i,600,600i,700,700i,800,800i,900,900i"
|
|
||||||
rel="stylesheet">
|
|
||||||
|
|
||||||
<!-- Custom styles for this template-->
|
<!-- Font Awesome -->
|
||||||
<link href="css/sb-admin-2.min.css" rel="stylesheet">
|
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.2/css/all.min.css" crossorigin="anonymous" referrerpolicy="no-referrer" />
|
||||||
|
|
||||||
|
<!-- Bootstrap CSS -->
|
||||||
|
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/5.3.3/css/bootstrap.min.css" crossorigin="anonymous" referrerpolicy="no-referrer" />
|
||||||
|
|
||||||
|
<!-- SB Admin 2 CSS (CDN community) -->
|
||||||
|
<link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/BlackrockDigital/startbootstrap-sb-admin-2@master/dist/css/sb-admin-2.min.css">
|
||||||
|
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body class="bg-gradient-primary">
|
<body class="bg-gradient-primary">
|
||||||
|
<video id="bg-video" autoplay muted loop playsinline>
|
||||||
|
<source src="~/images/bg.mp4" type="video/mp4" />
|
||||||
|
</video>
|
||||||
<div class="container">
|
<div class="container">
|
||||||
|
|
||||||
<!-- Outer Row -->
|
<!-- Outer Row -->
|
||||||
@@ -39,43 +50,30 @@
|
|||||||
<div class="col-lg-6">
|
<div class="col-lg-6">
|
||||||
<div class="p-5">
|
<div class="p-5">
|
||||||
<div class="text-center">
|
<div class="text-center">
|
||||||
<h1 class="h4 text-gray-900 mb-4">Welcome Back!</h1>
|
<h1 class="h4 text-gray-900 mb-4" style="font-weight: 800;margin-bottom: 8%!important;">
|
||||||
|
Welcome Back!
|
||||||
|
</h1>
|
||||||
</div>
|
</div>
|
||||||
<form class="user">
|
<form asp-controller="Connections" asp-action="Login" method="post" class="user">
|
||||||
|
@Html.AntiForgeryToken()
|
||||||
|
<input type="hidden" name="returnUrl" value="@Context.Request.Query["returnUrl"]" />
|
||||||
|
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<input type="email" class="form-control form-control-user"
|
<input type="text" name="username" class="form-control form-control-user"
|
||||||
id="exampleInputEmail" aria-describedby="emailHelp"
|
placeholder="Pseudo" autocomplete="username" required />
|
||||||
placeholder="Enter Email Address...">
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<input type="password" class="form-control form-control-user"
|
<input type="password" name="password" class="form-control form-control-user"
|
||||||
id="exampleInputPassword" placeholder="Password">
|
placeholder="Mot de passe" autocomplete="current-password" required />
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group">
|
|
||||||
<div class="custom-control custom-checkbox small">
|
<button type="submit" class="btn btn-primary btn-user btn-block">
|
||||||
<input type="checkbox" class="custom-control-input" id="customCheck">
|
Se connecter
|
||||||
<label class="custom-control-label" for="customCheck">Remember
|
</button>
|
||||||
Me</label>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<a href="index.html" class="btn btn-primary btn-user btn-block">
|
|
||||||
Login
|
|
||||||
</a>
|
|
||||||
<hr>
|
|
||||||
<a href="index.html" class="btn btn-google btn-user btn-block">
|
|
||||||
<i class="fab fa-google fa-fw"></i> Login with Google
|
|
||||||
</a>
|
|
||||||
<a href="index.html" class="btn btn-facebook btn-user btn-block">
|
|
||||||
<i class="fab fa-facebook-f fa-fw"></i> Login with Facebook
|
|
||||||
</a>
|
|
||||||
</form>
|
</form>
|
||||||
<hr>
|
|
||||||
<div class="text-center">
|
<div class="text-danger">@Html.ValidationSummary(false)</div>
|
||||||
<a class="small" href="forgot-password.html">Forgot Password?</a>
|
|
||||||
</div>
|
|
||||||
<div class="text-center">
|
|
||||||
<a class="small" href="register.html">Create an Account!</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -88,15 +86,20 @@
|
|||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Bootstrap core JavaScript-->
|
|
||||||
<script src="vendor/jquery/jquery.min.js"></script>
|
|
||||||
<script src="vendor/bootstrap/js/bootstrap.bundle.min.js"></script>
|
|
||||||
|
|
||||||
<!-- Core plugin JavaScript-->
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.7.1/jquery.min.js" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
|
||||||
<script src="vendor/jquery-easing/jquery.easing.min.js"></script>
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/5.3.3/js/bootstrap.bundle.min.js" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
|
||||||
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery-easing/1.4.1/jquery.easing.min.js" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
|
||||||
|
<script src="https://cdn.jsdelivr.net/gh/BlackrockDigital/startbootstrap-sb-admin-2@master/dist/js/sb-admin-2.min.js"></script>
|
||||||
|
|
||||||
<!-- Custom scripts for all pages-->
|
<script src="~/lib/jquery-easing/jquery.easing.js"></script>
|
||||||
<script src="js/sb-admin-2.min.js"></script>
|
<script src="https://unpkg.com/@@popperjs/core@2"></script>
|
||||||
|
<script src="https://unpkg.com/tippy.js@6/dist/tippy-bundle.umd.min.js"></script>
|
||||||
|
|
||||||
|
<script src="~/js/api.js" asp-append-version="true"></script>
|
||||||
|
<script src="~/js/site.js" asp-append-version="true"></script>
|
||||||
|
|
||||||
|
<script src="~/lib/datatable/datatables.min.js"></script>
|
||||||
|
|
||||||
</body>
|
</body>
|
||||||
|
|
||||||
|
|||||||
0
Views/Connections/d5e0rmn2.n54~
Normal file
0
Views/Connections/d5e0rmn2.n54~
Normal file
0
Views/Connections/dcmtrkdm.j5g~
Normal file
0
Views/Connections/dcmtrkdm.j5g~
Normal file
0
Views/Connections/jr3n0uyh.xig~
Normal file
0
Views/Connections/jr3n0uyh.xig~
Normal file
0
Views/Connections/qutlkkki.ndb~
Normal file
0
Views/Connections/qutlkkki.ndb~
Normal file
0
Views/Connections/wqomdnjo.1g3~
Normal file
0
Views/Connections/wqomdnjo.1g3~
Normal file
0
Views/Connections/xdmdr5nz.az0~
Normal file
0
Views/Connections/xdmdr5nz.az0~
Normal file
0
Views/Connections/ylzqhfgf.znz~
Normal file
0
Views/Connections/ylzqhfgf.znz~
Normal file
0
Views/Connections/zzbblwmn.g2p~
Normal file
0
Views/Connections/zzbblwmn.g2p~
Normal file
572
Views/Finances/Index.cshtml
Normal file
572
Views/Finances/Index.cshtml
Normal file
@@ -0,0 +1,572 @@
|
|||||||
|
@{
|
||||||
|
ViewData["Title"] = "Home Page";
|
||||||
|
}
|
||||||
|
<head>
|
||||||
|
<title>@ViewData["Title"] - administration</title>
|
||||||
|
<link rel="stylesheet" href="~/css/Finances/index.css" asp-append-version="true" />
|
||||||
|
|
||||||
|
<!-- Custom fonts for this template-->
|
||||||
|
<link href="~/lib/fontawesome-free/css/all.css" rel="stylesheet" type="text/css">
|
||||||
|
<link href="https://fonts.googleapis.com/css?family=Nunito:200,200i,300,300i,400,400i,600,600i,700,700i,800,800i,900,900i"
|
||||||
|
rel="stylesheet">
|
||||||
|
|
||||||
|
</head>
|
||||||
|
<!-- Page Wrapper -->
|
||||||
|
<div id="wrapper">
|
||||||
|
|
||||||
|
|
||||||
|
<div id="content-wrapper" class="d-flex flex-column">
|
||||||
|
|
||||||
|
<p id="idRevenues" hidden></p>
|
||||||
|
<p id="idExpenses" hidden></p>
|
||||||
|
<!-- Main Content -->
|
||||||
|
<div id="content">
|
||||||
|
|
||||||
|
<!-- End of Topbar -->
|
||||||
|
<!-- Begin Page Content -->
|
||||||
|
<div class="container-fluid">
|
||||||
|
|
||||||
|
<!-- Page Heading -->
|
||||||
|
<div class="d-sm-flex align-items-center justify-content-between mb-4">
|
||||||
|
<h1 class="h3 mb-0 text-gray-800">Dépenses</h1>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="row">
|
||||||
|
|
||||||
|
<!-- Earnings (Monthly) Card Example -->
|
||||||
|
<div class="col-xl-3 col-md-6 mb-4 cardDepense" id="LOYER">
|
||||||
|
<div class="card border-left-danger shadow h-100 py-2">
|
||||||
|
<div class="card-body">
|
||||||
|
<div class="row no-gutters align-items-center">
|
||||||
|
<div class="col mr-2">
|
||||||
|
<div class="text-xs font-weight-bold text-danger text-uppercase mb-1">
|
||||||
|
LOYER
|
||||||
|
</div>
|
||||||
|
<div class="h5 mb-0 font-weight-bold text-gray-800" id="loyer"></div>
|
||||||
|
</div>
|
||||||
|
<div class="col-auto">
|
||||||
|
<i class="fas fa-house-user fa-2x text-gray-300"></i>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<!-- Earnings (Monthly) Card Example -->
|
||||||
|
<div class="col-xl-3 col-md-6 mb-4 cardDepense" id="ORDURE">
|
||||||
|
<div class="card border-left-danger shadow h-100 py-2">
|
||||||
|
<div class="card-body">
|
||||||
|
<div class="row no-gutters align-items-center">
|
||||||
|
<div class="col mr-2">
|
||||||
|
<div class="text-xs font-weight-bold text-danger text-uppercase mb-1">
|
||||||
|
ORDURE
|
||||||
|
</div>
|
||||||
|
<div class="h5 mb-0 font-weight-bold text-gray-800" id="trash"></div>
|
||||||
|
</div>
|
||||||
|
<div class="col-auto">
|
||||||
|
<i class="fas fa-trash fa-2x text-gray-300"></i>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Earnings (Monthly) Card Example -->
|
||||||
|
<div class="col-xl-3 col-md-6 mb-4 cardDepense" id="ASSURANCE">
|
||||||
|
<div class="card border-left-danger shadow h-100 py-2">
|
||||||
|
<div class="card-body">
|
||||||
|
<div class="row no-gutters align-items-center">
|
||||||
|
<div class="col mr-2">
|
||||||
|
<div class="text-xs font-weight-bold text-danger text-uppercase mb-1">
|
||||||
|
ASSURANCE
|
||||||
|
</div>
|
||||||
|
<div class="h5 mb-0 font-weight-bold text-gray-800" id="insurance"></div>
|
||||||
|
</div>
|
||||||
|
<div class="col-auto">
|
||||||
|
<i class="fas fa-house-damage fa-2x text-gray-300"></i>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Earnings (Monthly) Card Example -->
|
||||||
|
<div class="col-xl-3 col-md-6 mb-4 cardDepense" id="WIFI">
|
||||||
|
<div class="card border-left-danger shadow h-100 py-2">
|
||||||
|
<div class="card-body">
|
||||||
|
<div class="row no-gutters align-items-center">
|
||||||
|
<div class="col mr-2">
|
||||||
|
<div class="text-xs font-weight-bold text-danger text-uppercase mb-1">
|
||||||
|
WIFI
|
||||||
|
</div>
|
||||||
|
<div class="h5 mb-0 font-weight-bold text-gray-800" id="wifi"></div>
|
||||||
|
</div>
|
||||||
|
<div class="col-auto">
|
||||||
|
<i class="fas fa-wifi fa-2x text-gray-300"></i>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Earnings (Monthly) Card Example -->
|
||||||
|
<div class="col-xl-3 col-md-6 mb-4 cardDepense" id="ELECTRICITE">
|
||||||
|
<div class="card border-left-danger shadow h-100 py-2">
|
||||||
|
<div class="card-body">
|
||||||
|
<div class="row no-gutters align-items-center">
|
||||||
|
<div class="col mr-2">
|
||||||
|
<div class="text-xs font-weight-bold text-danger text-uppercase mb-1">
|
||||||
|
ELECTRICITE
|
||||||
|
</div>
|
||||||
|
<div class="h5 mb-0 font-weight-bold text-gray-800" id="electricity"></div>
|
||||||
|
</div>
|
||||||
|
<div class="col-auto">
|
||||||
|
<i class="fas fa-bolt fa-2x text-gray-300"></i>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<!-- Earnings (Monthly) Card Example -->
|
||||||
|
<div class="col-xl-3 col-md-6 mb-4 cardDepense" id="COURSES">
|
||||||
|
<div class="card border-left-danger shadow h-100 py-2">
|
||||||
|
<div class="card-body">
|
||||||
|
<div class="row no-gutters align-items-center">
|
||||||
|
<div class="col mr-2">
|
||||||
|
<div class="text-xs font-weight-bold text-danger text-uppercase mb-1">
|
||||||
|
COURSES
|
||||||
|
</div>
|
||||||
|
<div class="h5 mb-0 font-weight-bold text-gray-800" id="groceries"></div>
|
||||||
|
</div>
|
||||||
|
<div class="col-auto">
|
||||||
|
<i class="fas fa-shopping-basket fa-2x text-gray-300"></i>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<!-- Earnings (Monthly) Card Example -->
|
||||||
|
<div class="col-xl-3 col-md-6 mb-4 cardDepense" id="ABONNEMENTS">
|
||||||
|
<div class="card border-left-danger shadow h-100 py-2">
|
||||||
|
<div class="card-body">
|
||||||
|
<div class="row no-gutters align-items-center">
|
||||||
|
<div class="col mr-2">
|
||||||
|
<div class="text-xs font-weight-bold text-danger text-uppercase mb-1">
|
||||||
|
ABONNEMENTS
|
||||||
|
</div>
|
||||||
|
<div class="h5 mb-0 font-weight-bold text-gray-800" id="additionalExpensesSub"></div>
|
||||||
|
</div>
|
||||||
|
<div class="col-auto">
|
||||||
|
<i class="fas fa-puzzle-piece fa-2x text-gray-300"></i>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="col-xl-3 col-md-6 mb-4 cardDepense" id="Autres_dépenses">
|
||||||
|
<div class="card border-left-danger shadow h-100 py-2">
|
||||||
|
<div class="card-body">
|
||||||
|
<div class="row no-gutters align-items-center">
|
||||||
|
<div class="col mr-2">
|
||||||
|
<div class="text-xs font-weight-bold text-danger text-uppercase mb-1">
|
||||||
|
Autres dépenses
|
||||||
|
</div>
|
||||||
|
<div class="h5 mb-0 font-weight-bold text-gray-800" id="additionalSourcesExpense"></div>
|
||||||
|
</div>
|
||||||
|
<div class="col-auto">
|
||||||
|
<i class="fas fa-comment fa-2x text-gray-300"></i>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="col-xl-3 col-md-6 mb-4 cardDepense" id="Mis_de_côté">
|
||||||
|
<div class="card border-left-danger shadow h-100 py-2">
|
||||||
|
<div class="card-body">
|
||||||
|
<div class="row no-gutters align-items-center">
|
||||||
|
<div class="col mr-2">
|
||||||
|
<div class="text-xs font-weight-bold text-danger text-uppercase mb-1">
|
||||||
|
Mis de côté
|
||||||
|
</div>
|
||||||
|
<div class="h5 mb-0 font-weight-bold text-gray-800" id="saving"></div>
|
||||||
|
</div>
|
||||||
|
<div class="col-auto">
|
||||||
|
<i class="fas fa-dollar-sign fa-2x text-gray-300"></i>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<br />
|
||||||
|
<h1 class="h3 mb-0 text-gray-800">Revenues</h1>
|
||||||
|
<br />
|
||||||
|
|
||||||
|
<div class="row">
|
||||||
|
<!-- Earnings (Monthly) Card Example -->
|
||||||
|
<div class="col-xl-3 col-md-6 mb-4 cardDepense" id="SALAIRE">
|
||||||
|
<div class="card border-left-success shadow h-100 py-2">
|
||||||
|
<div class="card-body">
|
||||||
|
<div class="row no-gutters align-items-center">
|
||||||
|
<div class="col mr-2">
|
||||||
|
<div class="text-xs font-weight-bold text-success text-uppercase mb-1">
|
||||||
|
SALAIRE
|
||||||
|
</div>
|
||||||
|
<div class="h5 mb-0 font-weight-bold text-gray-800" id="salaire"></div>
|
||||||
|
</div>
|
||||||
|
<div class="col-auto">
|
||||||
|
<i class="fas fa-user-shield fa-2x text-gray-300"></i>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<div class="col-xl-3 col-md-6 mb-4 cardDepense" id="Autres_gains">
|
||||||
|
<div class="card border-left-success shadow h-100 py-2">
|
||||||
|
<div class="card-body">
|
||||||
|
<div class="row no-gutters align-items-center">
|
||||||
|
<div class="col mr-2">
|
||||||
|
<div class="text-xs font-weight-bold text-success text-uppercase mb-1">
|
||||||
|
Autres gains
|
||||||
|
</div>
|
||||||
|
<div class="h5 mb-0 font-weight-bold text-gray-800" id="additionalRevenues"></div>
|
||||||
|
</div>
|
||||||
|
<div class="col-auto">
|
||||||
|
<i class="fas fa-chart-line fa-2x text-gray-300"></i>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<!-- Earnings (Monthly) Card Example -->
|
||||||
|
</div>
|
||||||
|
|
||||||
|
@* <hr class="row_divider"> *@
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@*
|
||||||
|
<div class="row">
|
||||||
|
|
||||||
|
<!-- Area Chart -->
|
||||||
|
<div class="col-xl-8 col-lg-7">
|
||||||
|
<div class="card shadow mb-4">
|
||||||
|
<!-- Card Header - Dropdown -->
|
||||||
|
<div class="card-header py-3 d-flex flex-row align-items-center justify-content-between">
|
||||||
|
<h6 class="m-0 font-weight-bold text-primary">Earnings Overview</h6>
|
||||||
|
<div class="dropdown no-arrow">
|
||||||
|
<a class="dropdown-toggle" href="#" role="button" id="dropdownMenuLink"
|
||||||
|
data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
|
||||||
|
<i class="fas fa-ellipsis-v fa-sm fa-fw text-gray-400"></i>
|
||||||
|
</a>
|
||||||
|
<div class="dropdown-menu dropdown-menu-right shadow animated--fade-in"
|
||||||
|
aria-labelledby="dropdownMenuLink">
|
||||||
|
<div class="dropdown-header">Dropdown Header:</div>
|
||||||
|
<a class="dropdown-item" href="#">Action</a>
|
||||||
|
<a class="dropdown-item" href="#">Another action</a>
|
||||||
|
<div class="dropdown-divider"></div>
|
||||||
|
<a class="dropdown-item" href="#">Something else here</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<!-- Card Body -->
|
||||||
|
<div class="card-body">
|
||||||
|
<div class="chart-area">
|
||||||
|
<canvas id="myAreaChart"></canvas>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Pie Chart -->
|
||||||
|
<div class="col-xl-4 col-lg-5">
|
||||||
|
<div class="card shadow mb-4">
|
||||||
|
<!-- Card Header - Dropdown -->
|
||||||
|
<div class="card-header py-3 d-flex flex-row align-items-center justify-content-between">
|
||||||
|
<h6 class="m-0 font-weight-bold text-primary">Revenue Sources</h6>
|
||||||
|
<div class="dropdown no-arrow">
|
||||||
|
<a class="dropdown-toggle" href="#" role="button" id="dropdownMenuLink"
|
||||||
|
data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
|
||||||
|
<i class="fas fa-ellipsis-v fa-sm fa-fw text-gray-400"></i>
|
||||||
|
</a>
|
||||||
|
<div class="dropdown-menu dropdown-menu-right shadow animated--fade-in"
|
||||||
|
aria-labelledby="dropdownMenuLink">
|
||||||
|
<div class="dropdown-header">Dropdown Header:</div>
|
||||||
|
<a class="dropdown-item" href="#">Action</a>
|
||||||
|
<a class="dropdown-item" href="#">Another action</a>
|
||||||
|
<div class="dropdown-divider"></div>
|
||||||
|
<a class="dropdown-item" href="#">Something else here</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<!-- Card Body -->
|
||||||
|
<div class="card-body">
|
||||||
|
<div class="chart-pie pt-4 pb-2">
|
||||||
|
<canvas id="myPieChart"></canvas>
|
||||||
|
</div>
|
||||||
|
<div class="mt-4 text-center small">
|
||||||
|
<span class="mr-2">
|
||||||
|
<i class="fas fa-circle text-primary"></i> Direct
|
||||||
|
</span>
|
||||||
|
<span class="mr-2">
|
||||||
|
<i class="fas fa-circle text-success"></i> Social
|
||||||
|
</span>
|
||||||
|
<span class="mr-2">
|
||||||
|
<i class="fas fa-circle text-info"></i> Referral
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="row">
|
||||||
|
|
||||||
|
<!-- Content Column -->
|
||||||
|
<div class="col-lg-6 mb-4">
|
||||||
|
|
||||||
|
<!-- Project Card Example -->
|
||||||
|
<div class="card shadow mb-4">
|
||||||
|
<div class="card-header py-3">
|
||||||
|
<h6 class="m-0 font-weight-bold text-primary">Projects</h6>
|
||||||
|
</div>
|
||||||
|
<div class="card-body">
|
||||||
|
<h4 class="small font-weight-bold">
|
||||||
|
Server Migration <span class="float-right">20%</span>
|
||||||
|
</h4>
|
||||||
|
<div class="progress mb-4">
|
||||||
|
<div class="progress-bar bg-danger" role="progressbar" style="width: 20%"
|
||||||
|
aria-valuenow="20" aria-valuemin="0" aria-valuemax="100"></div>
|
||||||
|
</div>
|
||||||
|
<h4 class="small font-weight-bold">
|
||||||
|
Sales Tracking <span class="float-right">40%</span>
|
||||||
|
</h4>
|
||||||
|
<div class="progress mb-4">
|
||||||
|
<div class="progress-bar bg-warning" role="progressbar" style="width: 40%"
|
||||||
|
aria-valuenow="40" aria-valuemin="0" aria-valuemax="100"></div>
|
||||||
|
</div>
|
||||||
|
<h4 class="small font-weight-bold">
|
||||||
|
Customer Database <span class="float-right">60%</span>
|
||||||
|
</h4>
|
||||||
|
<div class="progress mb-4">
|
||||||
|
<div class="progress-bar" role="progressbar" style="width: 60%"
|
||||||
|
aria-valuenow="60" aria-valuemin="0" aria-valuemax="100"></div>
|
||||||
|
</div>
|
||||||
|
<h4 class="small font-weight-bold">
|
||||||
|
Payout Details <span class="float-right">80%</span>
|
||||||
|
</h4>
|
||||||
|
<div class="progress mb-4">
|
||||||
|
<div class="progress-bar bg-info" role="progressbar" style="width: 80%"
|
||||||
|
aria-valuenow="80" aria-valuemin="0" aria-valuemax="100"></div>
|
||||||
|
</div>
|
||||||
|
<h4 class="small font-weight-bold">
|
||||||
|
Account Setup <span class="float-right">Complete!</span>
|
||||||
|
</h4>
|
||||||
|
<div class="progress">
|
||||||
|
<div class="progress-bar bg-success" role="progressbar" style="width: 100%"
|
||||||
|
aria-valuenow="100" aria-valuemin="0" aria-valuemax="100"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Color System -->
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-lg-6 mb-4">
|
||||||
|
<div class="card bg-primary text-white shadow">
|
||||||
|
<div class="card-body">
|
||||||
|
Primary
|
||||||
|
<div class="text-white-50 small">#4e73df</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-lg-6 mb-4">
|
||||||
|
<div class="card bg-success text-white shadow">
|
||||||
|
<div class="card-body">
|
||||||
|
Success
|
||||||
|
<div class="text-white-50 small">#1cc88a</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-lg-6 mb-4">
|
||||||
|
<div class="card bg-info text-white shadow">
|
||||||
|
<div class="card-body">
|
||||||
|
Info
|
||||||
|
<div class="text-white-50 small">#36b9cc</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-lg-6 mb-4">
|
||||||
|
<div class="card bg-warning text-white shadow">
|
||||||
|
<div class="card-body">
|
||||||
|
Warning
|
||||||
|
<div class="text-white-50 small">#f6c23e</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-lg-6 mb-4">
|
||||||
|
<div class="card bg-danger text-white shadow">
|
||||||
|
<div class="card-body">
|
||||||
|
Danger
|
||||||
|
<div class="text-white-50 small">#e74a3b</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-lg-6 mb-4">
|
||||||
|
<div class="card bg-secondary text-white shadow">
|
||||||
|
<div class="card-body">
|
||||||
|
Secondary
|
||||||
|
<div class="text-white-50 small">#858796</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-lg-6 mb-4">
|
||||||
|
<div class="card bg-light text-black shadow">
|
||||||
|
<div class="card-body">
|
||||||
|
Light
|
||||||
|
<div class="text-black-50 small">#f8f9fc</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-lg-6 mb-4">
|
||||||
|
<div class="card bg-dark text-white shadow">
|
||||||
|
<div class="card-body">
|
||||||
|
Dark
|
||||||
|
<div class="text-white-50 small">#5a5c69</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="col-lg-6 mb-4">
|
||||||
|
|
||||||
|
<!-- Illustrations -->
|
||||||
|
<div class="card shadow mb-4">
|
||||||
|
<div class="card-header py-3">
|
||||||
|
<h6 class="m-0 font-weight-bold text-primary">Illustrations</h6>
|
||||||
|
</div>
|
||||||
|
<div class="card-body">
|
||||||
|
<div class="text-center">
|
||||||
|
<img class="img-fluid px-3 px-sm-4 mt-3 mb-4" style="width: 25rem;"
|
||||||
|
src="~/images/undraw_posting_photo.svg" alt="...">
|
||||||
|
</div>
|
||||||
|
<p>
|
||||||
|
Add some quality, svg illustrations to your project courtesy of <a target="_blank" rel="nofollow" href="https://undraw.co/">unDraw</a>, a
|
||||||
|
constantly updated collection of beautiful svg images that you can use
|
||||||
|
completely free and without attribution!
|
||||||
|
</p>
|
||||||
|
<a target="_blank" rel="nofollow" href="https://undraw.co/">
|
||||||
|
Browse Illustrations on
|
||||||
|
unDraw →
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Approach -->
|
||||||
|
<div class="card shadow mb-4">
|
||||||
|
<div class="card-header py-3">
|
||||||
|
<h6 class="m-0 font-weight-bold text-primary">Development Approach</h6>
|
||||||
|
</div>
|
||||||
|
<div class="card-body">
|
||||||
|
<p>
|
||||||
|
SB Admin 2 makes extensive use of Bootstrap 4 utility classes in order to reduce
|
||||||
|
CSS bloat and poor page performance. Custom CSS classes are used to create
|
||||||
|
custom components and custom utility classes.
|
||||||
|
</p>
|
||||||
|
<p class="mb-0">
|
||||||
|
Before working with this theme, you should become familiar with the
|
||||||
|
Bootstrap framework, especially the utility classes.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div> *@
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="col-xl-3 col-md-6 mb-4 cardDepense" style="margin: auto!important;margin-right: 0!important;margin-top: 0 !important; flex: 0 0 25%;max-width: 25%;">
|
||||||
|
<div class="card border-left-primary shadow h-100 py-2">
|
||||||
|
<div class="card-body">
|
||||||
|
<div class="row no-gutters align-items-center">
|
||||||
|
<div class="col mr-2">
|
||||||
|
<div class="text-xs font-weight-bold text-primary text-uppercase mb-1">
|
||||||
|
Restants
|
||||||
|
</div>
|
||||||
|
<div class="h5 mb-0 font-weight-bold text-gray-800" id="result"></div>
|
||||||
|
</div>
|
||||||
|
<div class="col-auto">
|
||||||
|
<i class="fas fa-dollar fa-2x text-gray-300"></i>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<!-- /.container-fluid -->
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<!-- End of Main Content -->
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<!-- End of Content Wrapper -->
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<!-- End of Page Wrapper -->
|
||||||
|
<!-- Scroll to Top Button-->
|
||||||
|
<a class="scroll-to-top rounded" href="#page-top">
|
||||||
|
<i class="fas fa-angle-up"></i>
|
||||||
|
</a>
|
||||||
|
|
||||||
|
|
||||||
|
<!-- Logout Modal-->
|
||||||
|
<div class="modal fade" id="CRUDModal" tabindex="-1" role="dialog" aria-labelledby="CRUDModalLabel"
|
||||||
|
aria-hidden="true">
|
||||||
|
<div class="modal-dialog modal-xl" role="document">
|
||||||
|
<div class="modal-content">
|
||||||
|
<div class="modal-header">
|
||||||
|
<h5 class="modal-title" id="CRUDModalLabel"></h5>
|
||||||
|
<button class="close" type="button" data-dismiss="modal" aria-label="Close">
|
||||||
|
<span aria-hidden="true" onclick="$('#CRUDModal').modal('hide');">×</span>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<div class="modal-body">
|
||||||
|
<h5 class="subTitleModal" id="monthOfToday"></h5>
|
||||||
|
<table id="expensesTable" class="display compact" style="width:100%"></table>
|
||||||
|
<br />
|
||||||
|
<h5 class="subTitleModal">Dernier mois...</h5>
|
||||||
|
<table id="lastsMonthTable" class="display compact" style="width:100%"></table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<!-- Logout Modal-->
|
||||||
|
<div class="modal fade" id="logoutModal" tabindex="-1" role="dialog" aria-labelledby="exampleModalLabel"
|
||||||
|
aria-hidden="true">
|
||||||
|
<div class="modal-dialog" role="document">
|
||||||
|
<div class="modal-content">
|
||||||
|
<div class="modal-header">
|
||||||
|
<h5 class="modal-title" id="exampleModalLabel">Ready to Leave?</h5>
|
||||||
|
<button class="close" type="button" data-dismiss="modal" aria-label="Close">
|
||||||
|
<span aria-hidden="true">×</span>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<div class="modal-body">Select "Logout" below if you are ready to end your current session.</div>
|
||||||
|
<div class="modal-footer">
|
||||||
|
<button class="btn btn-secondary" type="button" data-dismiss="modal">Cancel</button>
|
||||||
|
<a class="btn btn-primary" href="login.html">Logout</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<script src="~/js/Finances/index.js" asp-append-version="true"></script>
|
||||||
56
Views/HelloFresh/Cuisine.cshtml
Normal file
56
Views/HelloFresh/Cuisine.cshtml
Normal file
@@ -0,0 +1,56 @@
|
|||||||
|
@{
|
||||||
|
ViewData["Title"] = "Cuisine";
|
||||||
|
}
|
||||||
|
<head>
|
||||||
|
<title>@ViewData["Title"]</title>
|
||||||
|
<link rel="stylesheet" href="~/css/HelloFresh/cuisine.css" asp-append-version="true" />
|
||||||
|
|
||||||
|
<link rel="stylesheet" href="https://unpkg.com/tippy.js@6/dist/tippy.css" />
|
||||||
|
|
||||||
|
<!-- Custom fonts for this template-->
|
||||||
|
<link href="~/lib/fontawesome-free/css/all.css" rel="stylesheet" type="text/css">
|
||||||
|
<link href="https://fonts.googleapis.com/css?family=Nunito:200,200i,300,300i,400,400i,600,600i,700,700i,800,800i,900,900i" rel="stylesheet">
|
||||||
|
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<section id="cuisineApp" class="cui-root">
|
||||||
|
<!-- Side panel (repliable) -->
|
||||||
|
<aside id="cuiSide" class="cui-side">
|
||||||
|
<header class="cui-side-head">
|
||||||
|
<h2>Recettes</h2>
|
||||||
|
<button id="toggleSide" class="ghost" aria-expanded="true" title="Replier/ouvrir">⟨</button>
|
||||||
|
</header>
|
||||||
|
<div id="recipeScroller" class="cui-cards"></div>
|
||||||
|
</aside>
|
||||||
|
|
||||||
|
<!-- Main PDF area -->
|
||||||
|
<main class="cui-main">
|
||||||
|
<div class="cui-toolbar">
|
||||||
|
<div class="cui-title">
|
||||||
|
<span id="currentName">Sélectionnez une recette</span>
|
||||||
|
</div>
|
||||||
|
<div class="cui-actions">
|
||||||
|
<button id="openPdf" class="primary" disabled>Ouvrir le PDF</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="cui-view">
|
||||||
|
<!-- Aperçu non plein écran -->
|
||||||
|
<iframe id="pdfPreview" class="cui-iframe" title="Aperçu PDF"></iframe>
|
||||||
|
<div id="pdfPlaceholder" class="cui-placeholder">
|
||||||
|
Choisissez une recette pour afficher son PDF.
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</main>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<!-- Overlay plein écran -->
|
||||||
|
<div id="viewerOverlay" class="viewer hidden" aria-hidden="true">
|
||||||
|
<div class="viewer-top">
|
||||||
|
<button id="closeViewer" class="ghost" aria-label="Fermer">✕</button>
|
||||||
|
<div id="viewerTitle" class="viewer-title">PDF</div>
|
||||||
|
</div>
|
||||||
|
<iframe id="pdfFrameFull" class="viewer-iframe" title="Lecteur PDF"></iframe>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script src="~/js/HelloFresh/cuisine.js" asp-append-version="true"></script>
|
||||||
32
Views/HelloFresh/Historique.cshtml
Normal file
32
Views/HelloFresh/Historique.cshtml
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
@{
|
||||||
|
ViewData["Title"] = "Historique";
|
||||||
|
}
|
||||||
|
<head>
|
||||||
|
<title>@ViewData["Title"]</title>
|
||||||
|
<link rel="stylesheet" href="~/css/HelloFresh/historique.css" asp-append-version="true" />
|
||||||
|
<link href="~/lib/fontawesome-free/css/all.css" rel="stylesheet" type="text/css">
|
||||||
|
<link href="https://fonts.googleapis.com/css?family=Nunito:400,700,800" rel="stylesheet">
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<section id="historiqueBoard" class="hf-ingredients">
|
||||||
|
<div class="hf-head">
|
||||||
|
<h2>Historique des recettes</h2>
|
||||||
|
<div class="hf-qty" style="gap:12px">
|
||||||
|
<label for="historyScope">Portée :</label>
|
||||||
|
<select id="historyScope">
|
||||||
|
<option value="mine" selected>Mes archives</option>
|
||||||
|
<option value="all">Tous les utilisateurs</option>
|
||||||
|
</select>
|
||||||
|
|
||||||
|
<!-- 🔎 Recherche -->
|
||||||
|
<input id="historySearch" type="search"
|
||||||
|
placeholder="Rechercher une recette…"
|
||||||
|
style="padding:6px 10px;border:1px solid #cfcfcf;border-radius:8px;min-width:240px">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div id="historyContainer" class="history-sections"></div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
|
||||||
|
<script src="~/js/HelloFresh/historique.js" asp-append-version="true"></script>
|
||||||
135
Views/HelloFresh/Index.cshtml
Normal file
135
Views/HelloFresh/Index.cshtml
Normal file
@@ -0,0 +1,135 @@
|
|||||||
|
@{
|
||||||
|
ViewData["Title"] = "Home Page";
|
||||||
|
}
|
||||||
|
<head>
|
||||||
|
<title>@ViewData["Title"] - Hello Fresh</title>
|
||||||
|
<link rel="stylesheet" href="~/css/HelloFresh/index.css" asp-append-version="true" />
|
||||||
|
|
||||||
|
<link rel="stylesheet" href="https://unpkg.com/tippy.js@6/dist/tippy.css" />
|
||||||
|
|
||||||
|
<!-- Custom fonts for this template-->
|
||||||
|
<link href="~/lib/fontawesome-free/css/all.css" rel="stylesheet" type="text/css">
|
||||||
|
<link href="https://fonts.googleapis.com/css?family=Nunito:200,200i,300,300i,400,400i,600,600i,700,700i,800,800i,900,900i" rel="stylesheet">
|
||||||
|
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<!-- juste sous la topbar, au début de .content -->
|
||||||
|
<div class="sticky-search">
|
||||||
|
<form class="form-inline w-100 navbar-search">
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<!-- ANCRE + CARD flottante -->
|
||||||
|
<div id="filterAnchor" class="filter-anchor">
|
||||||
|
<button id="filterOpenBtn" class="hf-icon-btn" type="button" title="Filtres">
|
||||||
|
<svg width="20" height="20" viewBox="0 0 24 24" aria-hidden="true"><path d="M3 5h18v2l-7 7v4l-4 2v-6L3 7V5z" /></svg>
|
||||||
|
<span id="activeFilterBadge" class="hf-badge" style="display:none;"></span>
|
||||||
|
</button>
|
||||||
|
|
||||||
|
<!-- CARD flottante -->
|
||||||
|
<div id="filtersCard" class="hf-filter-card is-floating" hidden>
|
||||||
|
<div class="hf-filter-header">
|
||||||
|
<div class="title">
|
||||||
|
<svg width="18" height="18" viewBox="0 0 24 24" aria-hidden="true"><path d="M3 5h18v2l-7 7v4l-4 2v-6L3 7V5z" /></svg>
|
||||||
|
<span>Filtres</span>
|
||||||
|
</div>
|
||||||
|
<span id="activeFilterBadgeClone" class="hf-badge" style="display:none;"></span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="hf-filter-body">
|
||||||
|
<!-- Ingrédients -->
|
||||||
|
<section class="hf-field">
|
||||||
|
<label class="hf-section-title">Ingrédients</label>
|
||||||
|
<div id="chipIngredients" class="hf-chip-cloud"></div>
|
||||||
|
<select id="filterIngredients" multiple style="width:100%"></select>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<!-- Tags -->
|
||||||
|
<section class="hf-field">
|
||||||
|
<label class="hf-section-title">Tags</label>
|
||||||
|
<div id="chipTags" class="hf-chip-cloud"></div>
|
||||||
|
<select id="filterTags" multiple style="width:100%"></select>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<!-- Temps -->
|
||||||
|
<section class="hf-field">
|
||||||
|
<label class="hf-section-title">Temps (minutes)</label>
|
||||||
|
<div class="hf-time-row">
|
||||||
|
<input id="filterTimeMin" type="number" min="0" inputmode="numeric" placeholder="Min" class="hf-input">
|
||||||
|
<span class="hf-sep">–</span>
|
||||||
|
<input id="filterTimeMax" type="number" min="0" inputmode="numeric" placeholder="Max" class="hf-input">
|
||||||
|
</div>
|
||||||
|
<div class="hf-chips">
|
||||||
|
<button class="hf-chip" type="button" data-tmax="15">≤ 15</button>
|
||||||
|
<button class="hf-chip" type="button" data-tmax="30">≤ 30</button>
|
||||||
|
<button class="hf-chip" type="button" data-tmax="45">≤ 45</button>
|
||||||
|
<button class="hf-chip" type="button" data-tmax="60">≤ 60</button>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="hf-filter-footer">
|
||||||
|
<button id="clearFilters" class="hf-btn ghost" type="button">Tout effacer</button>
|
||||||
|
<button id="applyFilters" class="hf-btn primary" type="button">Appliquer</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="input-group" id="divSearch">
|
||||||
|
<input type="text" class="form-control bg-light border-0 small" placeholder="Search for..."
|
||||||
|
aria-label="Search" aria-describedby="basic-addon2">
|
||||||
|
<div class="input-group-append">
|
||||||
|
<button class="btn btn-primary" type="button">
|
||||||
|
<i class="fas fa-search fa-sm"></i>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<button id="archiveAllBtn" class="btn btn-secondary">
|
||||||
|
<i class="bi bi-tag"></i>
|
||||||
|
</button>
|
||||||
|
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<div class="section-toggle" id="ownedSection">
|
||||||
|
<hr class="section-hr" />
|
||||||
|
<button class="section-chip" type="button">
|
||||||
|
<span class="collapse-text">Afficher recettes choisies</span>
|
||||||
|
<span id="ownedCount" class="owned-count">(0/14)</span>
|
||||||
|
<span class="collapse-icon">▼</span>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div id="recipeOwnedWrap" class="collapse-wrap" aria-hidden="true">
|
||||||
|
<div id="recipeGridOwned" class="grid"></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<!-- Grille principale -->
|
||||||
|
<div id="recipeGrid" class="grid"></div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<div id="paginationControls" class="pagination-modern">
|
||||||
|
<button id="prevPage" class="pagination-btn" title="Page précédente">⬅</button>
|
||||||
|
<span id="pageInfo">1/1</span>
|
||||||
|
<button id="nextPage" class="pagination-btn" title="Page suivante">➡</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Modal PDF -->
|
||||||
|
<div class="modal fade" id="pdfModal" tabindex="-1" role="dialog" aria-hidden="true">
|
||||||
|
<div class="modal-dialog modal-dialog-centered modal-xl" role="document">
|
||||||
|
<div class="modal-content">
|
||||||
|
<div class="modal-body p-0" style="height:80vh;">
|
||||||
|
<iframe id="pdfFrame" src="" width="100%" height="100%" style="border:0;"></iframe>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<script src="~/js/HelloFresh/index.js" asp-append-version="true"></script>
|
||||||
|
<script src="~/js/HelloFresh/tagsColor.js" asp-append-version="true"></script>
|
||||||
42
Views/HelloFresh/Ingredients.cshtml
Normal file
42
Views/HelloFresh/Ingredients.cshtml
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
@{
|
||||||
|
ViewData["Title"] = "Home Page";
|
||||||
|
}
|
||||||
|
<head>
|
||||||
|
<title>@ViewData["Title"]</title>
|
||||||
|
<link rel="stylesheet" href="~/css/HelloFresh/ingredients.css" asp-append-version="true" />
|
||||||
|
|
||||||
|
<link rel="stylesheet" href="https://unpkg.com/tippy.js@6/dist/tippy.css" />
|
||||||
|
|
||||||
|
<!-- Custom fonts for this template-->
|
||||||
|
<link href="~/lib/fontawesome-free/css/all.css" rel="stylesheet" type="text/css">
|
||||||
|
<link href="https://fonts.googleapis.com/css?family=Nunito:200,200i,300,300i,400,400i,600,600i,700,700i,800,800i,900,900i" rel="stylesheet">
|
||||||
|
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<section id="recipesAll" class="recipes-section">
|
||||||
|
<div id="recipeStrip" class="hscroll grid"></div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section id="ingredientsBoard" class="hf-ingredients">
|
||||||
|
<div id="titleAndSearch">
|
||||||
|
<div class="hf-head">
|
||||||
|
<h2>Ingrédients</h2>
|
||||||
|
</div>
|
||||||
|
<div class="hf-search">
|
||||||
|
<input id="hfSearch" type="search" class="form-control" placeholder="Rechercher un ingrédient..." />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- liste principale -->
|
||||||
|
<ul id="ingredientsList" class="hf-grid"></ul>
|
||||||
|
|
||||||
|
<!-- séparation -->
|
||||||
|
<hr class="hf-sep" />
|
||||||
|
|
||||||
|
<!-- “à avoir chez soi” -->
|
||||||
|
<h3 class="hf-subtitle">Ingrédients à avoir chez soi</h3>
|
||||||
|
<ul id="neededIngredients" class="hf-grid"></ul>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<script src="~/js/HelloFresh/ingredients.js" asp-append-version="true"></script>
|
||||||
@@ -3,7 +3,7 @@
|
|||||||
}
|
}
|
||||||
<head>
|
<head>
|
||||||
<title>@ViewData["Title"] - administration</title>
|
<title>@ViewData["Title"] - administration</title>
|
||||||
<link rel="stylesheet" href="~/css/index.css" asp-append-version="true" />
|
<link rel="stylesheet" href="~/css/home.css" asp-append-version="true" />
|
||||||
|
|
||||||
<!-- Custom fonts for this template-->
|
<!-- Custom fonts for this template-->
|
||||||
<link href="~/lib/fontawesome-free/css/all.css" rel="stylesheet" type="text/css">
|
<link href="~/lib/fontawesome-free/css/all.css" rel="stylesheet" type="text/css">
|
||||||
@@ -11,819 +11,10 @@
|
|||||||
rel="stylesheet">
|
rel="stylesheet">
|
||||||
|
|
||||||
</head>
|
</head>
|
||||||
<!-- Page Wrapper -->
|
|
||||||
<div id="wrapper">
|
|
||||||
|
|
||||||
<!-- Sidebar -->
|
<div id="containerCard">
|
||||||
<ul class="navbar-nav bg-gradient-primary sidebar sidebar-dark accordion" id="accordionSidebar">
|
<img class="cardHome" src="~/images/HFHome.png" id="cardButtonHelloFresh" onclick="window.location.href = '/HelloFresh'" />
|
||||||
|
@* <img class="cardHome" src="~/images/Finance.png" id="cardButtonFinances" onclick="window.location.href = '/Finances'" /> *@
|
||||||
<!-- Sidebar - Brand -->
|
|
||||||
<a class="sidebar-brand d-flex align-items-center justify-content-center" href="index.html">
|
|
||||||
<div class="sidebar-brand-icon rotate-n-15">
|
|
||||||
<i class="fas fa-laugh-wink"></i>
|
|
||||||
</div>
|
|
||||||
<div class="sidebar-brand-text mx-3">Dashboard</div>
|
|
||||||
</a>
|
|
||||||
|
|
||||||
<!-- Divider -->
|
|
||||||
<hr class="sidebar-divider my-0">
|
|
||||||
|
|
||||||
<!-- Nav Item - Dashboard -->
|
|
||||||
<li class="nav-item active">
|
|
||||||
<a class="nav-link" href="index.html">
|
|
||||||
<i class="fas fa-fw fa-tachometer-alt"></i>
|
|
||||||
<span>Dashboard</span>
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
|
|
||||||
<!-- Divider -->
|
|
||||||
<hr class="sidebar-divider">
|
|
||||||
|
|
||||||
<!-- Heading -->
|
|
||||||
<div class="sidebar-heading">
|
|
||||||
Addons
|
|
||||||
</div>
|
|
||||||
<li class="nav-item">
|
|
||||||
<a class="nav-link collapsed d-flex justify-content-between align-items-center" href="#"
|
|
||||||
data-bs-toggle="collapse" data-bs-target="#collapsePages"
|
|
||||||
aria-expanded="false" aria-controls="collapsePages" onclick="$('#collapsePages').collapse('toggle'); return false;">
|
|
||||||
<div>
|
|
||||||
<i class="fas fa-fw fa-folder"></i>
|
|
||||||
<span>Pages</span>
|
|
||||||
</div>
|
|
||||||
<i class="fas fa-angle-down rotate-icon"></i>
|
|
||||||
</a>
|
|
||||||
<div id="collapsePages" class="collapse" data-bs-parent="#accordionSidebar">
|
|
||||||
<div class="bg-white py-2 collapse-inner rounded">
|
|
||||||
<h6 class="collapse-header">Login Screens:</h6>
|
|
||||||
<a class="collapse-item" href="/pages/Connections/Login">Login</a>
|
|
||||||
<a class="collapse-item" href="/pages/Connections/Register">Register</a>
|
|
||||||
<a class="collapse-item" href="/pages/Connections/ForgotPassword">Forgot Password</a>
|
|
||||||
<div class="collapse-divider"></div>
|
|
||||||
<h6 class="collapse-header">Other Pages:</h6>
|
|
||||||
<a class="collapse-item" href="/pages/Utilities/404">404 Page</a>
|
|
||||||
<a class="collapse-item" href="/pages/Utilities/Blank">Blank Page</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</li>
|
|
||||||
|
|
||||||
|
|
||||||
<!-- Nav Item - Charts -->
|
|
||||||
<li class="nav-item">
|
|
||||||
<a class="nav-link" href="charts.html">
|
|
||||||
<i class="fas fa-fw fa-chart-area"></i>
|
|
||||||
<span>Charts</span>
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
|
|
||||||
|
|
||||||
<!-- Sidebar Toggler (Sidebar) -->
|
|
||||||
<div class="text-center d-none d-md-inline">
|
|
||||||
<button class="rounded-circle border-0" id="sidebarToggle"></button>
|
|
||||||
</div>
|
|
||||||
</ul>
|
|
||||||
<!-- End of Sidebar -->
|
|
||||||
<!-- Content Wrapper -->
|
|
||||||
<div id="content-wrapper" class="d-flex flex-column">
|
|
||||||
|
|
||||||
<!-- Main Content -->
|
|
||||||
<div id="content">
|
|
||||||
|
|
||||||
<nav class="navbar navbar-expand navbar-light bg-white topbar mb-4 static-top shadow">
|
|
||||||
|
|
||||||
<!-- Sidebar Toggle (Topbar) -->
|
|
||||||
<button id="sidebarToggleTop" class="btn btn-link d-md-none rounded-circle mr-3">
|
|
||||||
<i class="fa fa-bars"></i>
|
|
||||||
</button>
|
|
||||||
|
|
||||||
<!-- Topbar Search -->
|
|
||||||
<form class="d-none d-sm-inline-block form-inline mr-auto ml-md-3 my-2 my-md-0 mw-100 navbar-search">
|
|
||||||
<div class="input-group">
|
|
||||||
<input type="text" class="form-control bg-light border-0 small" placeholder="Search for..."
|
|
||||||
aria-label="Search" aria-describedby="basic-addon2">
|
|
||||||
<div class="input-group-append">
|
|
||||||
<button class="btn btn-primary" type="button">
|
|
||||||
<i class="fas fa-search fa-sm"></i>
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
|
|
||||||
<!-- Topbar Navbar -->
|
|
||||||
<ul class="navbar-nav ml-auto">
|
|
||||||
|
|
||||||
<!-- Nav Item - Search Dropdown (Visible Only XS) -->
|
|
||||||
<li class="nav-item dropdown no-arrow d-sm-none">
|
|
||||||
<a class="nav-link dropdown-toggle" href="#" id="searchDropdown" role="button"
|
|
||||||
data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
|
|
||||||
<i class="fas fa-search fa-fw"></i>
|
|
||||||
</a>
|
|
||||||
<!-- Dropdown - Messages -->
|
|
||||||
<div class="dropdown-menu dropdown-menu-right p-3 shadow animated--grow-in"
|
|
||||||
aria-labelledby="searchDropdown">
|
|
||||||
<form class="form-inline mr-auto w-100 navbar-search">
|
|
||||||
<div class="input-group">
|
|
||||||
<input type="text" class="form-control bg-light border-0 small"
|
|
||||||
placeholder="Search for..." aria-label="Search"
|
|
||||||
aria-describedby="basic-addon2">
|
|
||||||
<div class="input-group-append">
|
|
||||||
<button class="btn btn-primary" type="button">
|
|
||||||
<i class="fas fa-search fa-sm"></i>
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
</li>
|
|
||||||
|
|
||||||
<!-- Nav Item - Alerts -->
|
|
||||||
<li class="nav-item dropdown no-arrow mx-1">
|
|
||||||
<a class="nav-link dropdown-toggle" href="#" id="alertsDropdown" role="button"
|
|
||||||
data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
|
|
||||||
<i class="fas fa-bell fa-fw"></i>
|
|
||||||
<!-- Counter - Alerts -->
|
|
||||||
<span class="badge badge-danger badge-counter">3+</span>
|
|
||||||
</a>
|
|
||||||
<!-- Dropdown - Alerts -->
|
|
||||||
<div class="dropdown-list dropdown-menu dropdown-menu-right shadow animated--grow-in"
|
|
||||||
aria-labelledby="alertsDropdown">
|
|
||||||
<h6 class="dropdown-header">
|
|
||||||
Alerts Center
|
|
||||||
</h6>
|
|
||||||
<a class="dropdown-item d-flex align-items-center" href="#">
|
|
||||||
<div class="mr-3">
|
|
||||||
<div class="icon-circle bg-primary">
|
|
||||||
<i class="fas fa-file-alt text-white"></i>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<div class="small text-gray-500">December 12, 2019</div>
|
|
||||||
<span class="font-weight-bold">A new monthly report is ready to download!</span>
|
|
||||||
</div>
|
|
||||||
</a>
|
|
||||||
<a class="dropdown-item d-flex align-items-center" href="#">
|
|
||||||
<div class="mr-3">
|
|
||||||
<div class="icon-circle bg-success">
|
|
||||||
<i class="fas fa-donate text-white"></i>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<div class="small text-gray-500">December 7, 2019</div>
|
|
||||||
$290.29 has been deposited into your account!
|
|
||||||
</div>
|
|
||||||
</a>
|
|
||||||
<a class="dropdown-item d-flex align-items-center" href="#">
|
|
||||||
<div class="mr-3">
|
|
||||||
<div class="icon-circle bg-warning">
|
|
||||||
<i class="fas fa-exclamation-triangle text-white"></i>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<div class="small text-gray-500">December 2, 2019</div>
|
|
||||||
Spending Alert: We've noticed unusually high spending for your account.
|
|
||||||
</div>
|
|
||||||
</a>
|
|
||||||
<a class="dropdown-item text-center small text-gray-500" href="#">Show All Alerts</a>
|
|
||||||
</div>
|
|
||||||
</li>
|
|
||||||
|
|
||||||
<!-- Nav Item - Messages -->
|
|
||||||
<li class="nav-item dropdown no-arrow mx-1">
|
|
||||||
<a class="nav-link dropdown-toggle" href="#" id="messagesDropdown" role="button"
|
|
||||||
data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
|
|
||||||
<i class="fas fa-envelope fa-fw"></i>
|
|
||||||
<!-- Counter - Messages -->
|
|
||||||
<span class="badge badge-danger badge-counter">7</span>
|
|
||||||
</a>
|
|
||||||
<!-- Dropdown - Messages -->
|
|
||||||
<div class="dropdown-list dropdown-menu dropdown-menu-right shadow animated--grow-in"
|
|
||||||
aria-labelledby="messagesDropdown">
|
|
||||||
<h6 class="dropdown-header">
|
|
||||||
Message Center
|
|
||||||
</h6>
|
|
||||||
<a class="dropdown-item d-flex align-items-center" href="#">
|
|
||||||
<div class="dropdown-list-image mr-3">
|
|
||||||
<img class="rounded-circle" src="~/images/undraw_profile_1.svg"
|
|
||||||
alt="...">
|
|
||||||
<div class="status-indicator bg-success"></div>
|
|
||||||
</div>
|
|
||||||
<div class="font-weight-bold">
|
|
||||||
<div class="text-truncate">
|
|
||||||
Hi there! I am wondering if you can help me with a
|
|
||||||
problem I've been having.
|
|
||||||
</div>
|
|
||||||
<div class="small text-gray-500">Emily Fowler · 58m</div>
|
|
||||||
</div>
|
|
||||||
</a>
|
|
||||||
<a class="dropdown-item d-flex align-items-center" href="#">
|
|
||||||
<div class="dropdown-list-image mr-3">
|
|
||||||
<img class="rounded-circle" src="~/images/undraw_profile_2.svg"
|
|
||||||
alt="...">
|
|
||||||
<div class="status-indicator"></div>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<div class="text-truncate">
|
|
||||||
I have the photos that you ordered last month, how
|
|
||||||
would you like them sent to you?
|
|
||||||
</div>
|
|
||||||
<div class="small text-gray-500">Jae Chun · 1d</div>
|
|
||||||
</div>
|
|
||||||
</a>
|
|
||||||
<a class="dropdown-item d-flex align-items-center" href="#">
|
|
||||||
<div class="dropdown-list-image mr-3">
|
|
||||||
<img class="rounded-circle" src="~/images/undraw_profile_3.svg"
|
|
||||||
alt="...">
|
|
||||||
<div class="status-indicator bg-warning"></div>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<div class="text-truncate">
|
|
||||||
Last month's report looks great, I am very happy with
|
|
||||||
the progress so far, keep up the good work!
|
|
||||||
</div>
|
|
||||||
<div class="small text-gray-500">Morgan Alvarez · 2d</div>
|
|
||||||
</div>
|
|
||||||
</a>
|
|
||||||
<a class="dropdown-item d-flex align-items-center" href="#">
|
|
||||||
<div class="dropdown-list-image mr-3">
|
|
||||||
<img class="rounded-circle" src="https://source.unsplash.com/Mv9hjnEUHR4/60x60"
|
|
||||||
alt="...">
|
|
||||||
<div class="status-indicator bg-success"></div>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<div class="text-truncate">
|
|
||||||
Am I a good boy? The reason I ask is because someone
|
|
||||||
told me that people say this to all dogs, even if they aren't good...
|
|
||||||
</div>
|
|
||||||
<div class="small text-gray-500">Chicken the Dog · 2w</div>
|
|
||||||
</div>
|
|
||||||
</a>
|
|
||||||
<a class="dropdown-item text-center small text-gray-500" href="#">Read More Messages</a>
|
|
||||||
</div>
|
|
||||||
</li>
|
|
||||||
|
|
||||||
<div class="topbar-divider d-none d-sm-block"></div>
|
|
||||||
|
|
||||||
<!-- Nav Item - User Information -->
|
|
||||||
<li class="nav-item dropdown no-arrow">
|
|
||||||
<a class="nav-link dropdown-toggle" href="#" id="userDropdown" role="button"
|
|
||||||
data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
|
|
||||||
<span class="mr-2 d-none d-lg-inline text-gray-600 small">Douglas McGee</span>
|
|
||||||
<img class="img-profile rounded-circle"
|
|
||||||
src="~/images/undraw_profile.svg">
|
|
||||||
</a>
|
|
||||||
<!-- Dropdown - User Information -->
|
|
||||||
<div class="dropdown-menu dropdown-menu-right shadow animated--grow-in"
|
|
||||||
aria-labelledby="userDropdown">
|
|
||||||
<a class="dropdown-item" href="#">
|
|
||||||
<i class="fas fa-user fa-sm fa-fw mr-2 text-gray-400"></i>
|
|
||||||
Profile
|
|
||||||
</a>
|
|
||||||
<a class="dropdown-item" href="#">
|
|
||||||
<i class="fas fa-cogs fa-sm fa-fw mr-2 text-gray-400"></i>
|
|
||||||
Settings
|
|
||||||
</a>
|
|
||||||
<a class="dropdown-item" href="#">
|
|
||||||
<i class="fas fa-list fa-sm fa-fw mr-2 text-gray-400"></i>
|
|
||||||
Activity Log
|
|
||||||
</a>
|
|
||||||
<div class="dropdown-divider"></div>
|
|
||||||
<a class="dropdown-item" href="#" data-toggle="modal" data-target="#logoutModal">
|
|
||||||
<i class="fas fa-sign-out-alt fa-sm fa-fw mr-2 text-gray-400"></i>
|
|
||||||
Logout
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
</li>
|
|
||||||
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
</nav>
|
|
||||||
<!-- End of Topbar -->
|
|
||||||
<!-- Begin Page Content -->
|
|
||||||
<div class="container-fluid">
|
|
||||||
|
|
||||||
<!-- Page Heading -->
|
|
||||||
<div class="d-sm-flex align-items-center justify-content-between mb-4">
|
|
||||||
<h1 class="h3 mb-0 text-gray-800">Dépenses</h1>
|
|
||||||
<a href="#" class="d-none d-sm-inline-block btn btn-sm btn-primary shadow-sm">
|
|
||||||
<i class="fas fa-download fa-sm text-white-50"></i> Generate Report
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="row">
|
|
||||||
|
|
||||||
<!-- Earnings (Monthly) Card Example -->
|
|
||||||
<div class="col-xl-3 col-md-6 mb-4">
|
|
||||||
<div class="card border-left-danger shadow h-100 py-2">
|
|
||||||
<div class="card-body">
|
|
||||||
<div class="row no-gutters align-items-center">
|
|
||||||
<div class="col mr-2">
|
|
||||||
<div class="text-xs font-weight-bold text-danger text-uppercase mb-1">
|
|
||||||
LOYER
|
|
||||||
</div>
|
|
||||||
<div class="h5 mb-0 font-weight-bold text-gray-800" id="loyer"></div>
|
|
||||||
</div>
|
|
||||||
<div class="col-auto">
|
|
||||||
<i class="fas fa-house-user fa-2x text-gray-300"></i>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
<!-- Earnings (Monthly) Card Example -->
|
|
||||||
<div class="col-xl-3 col-md-6 mb-4">
|
|
||||||
<div class="card border-left-danger shadow h-100 py-2">
|
|
||||||
<div class="card-body">
|
|
||||||
<div class="row no-gutters align-items-center">
|
|
||||||
<div class="col mr-2">
|
|
||||||
<div class="text-xs font-weight-bold text-danger text-uppercase mb-1">
|
|
||||||
ORDURE
|
|
||||||
</div>
|
|
||||||
<div class="h5 mb-0 font-weight-bold text-gray-800" id="trash"></div>
|
|
||||||
</div>
|
|
||||||
<div class="col-auto">
|
|
||||||
<i class="fas fa-trash fa-2x text-gray-300"></i>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Earnings (Monthly) Card Example -->
|
|
||||||
<div class="col-xl-3 col-md-6 mb-4">
|
|
||||||
<div class="card border-left-danger shadow h-100 py-2">
|
|
||||||
<div class="card-body">
|
|
||||||
<div class="row no-gutters align-items-center">
|
|
||||||
<div class="col mr-2">
|
|
||||||
<div class="text-xs font-weight-bold text-danger text-uppercase mb-1">
|
|
||||||
ASSURANCE
|
|
||||||
</div>
|
|
||||||
<div class="h5 mb-0 font-weight-bold text-gray-800" id="insurance"></div>
|
|
||||||
</div>
|
|
||||||
<div class="col-auto">
|
|
||||||
<i class="fas fa-house-damage fa-2x text-gray-300"></i>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Earnings (Monthly) Card Example -->
|
|
||||||
<div class="col-xl-3 col-md-6 mb-4">
|
|
||||||
<div class="card border-left-danger shadow h-100 py-2">
|
|
||||||
<div class="card-body">
|
|
||||||
<div class="row no-gutters align-items-center">
|
|
||||||
<div class="col mr-2">
|
|
||||||
<div class="text-xs font-weight-bold text-danger text-uppercase mb-1">
|
|
||||||
WIFI
|
|
||||||
</div>
|
|
||||||
<div class="h5 mb-0 font-weight-bold text-gray-800" id="wifi"></div>
|
|
||||||
</div>
|
|
||||||
<div class="col-auto">
|
|
||||||
<i class="fas fa-wifi fa-2x text-gray-300"></i>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Earnings (Monthly) Card Example -->
|
|
||||||
<div class="col-xl-3 col-md-6 mb-4">
|
|
||||||
<div class="card border-left-danger shadow h-100 py-2">
|
|
||||||
<div class="card-body">
|
|
||||||
<div class="row no-gutters align-items-center">
|
|
||||||
<div class="col mr-2">
|
|
||||||
<div class="text-xs font-weight-bold text-danger text-uppercase mb-1">
|
|
||||||
ELECTRICITE
|
|
||||||
</div>
|
|
||||||
<div class="h5 mb-0 font-weight-bold text-gray-800" id="electricity"></div>
|
|
||||||
</div>
|
|
||||||
<div class="col-auto">
|
|
||||||
<i class="fas fa-bolt fa-2x text-gray-300"></i>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<!-- Earnings (Monthly) Card Example -->
|
|
||||||
<div class="col-xl-3 col-md-6 mb-4">
|
|
||||||
<div class="card border-left-danger shadow h-100 py-2">
|
|
||||||
<div class="card-body">
|
|
||||||
<div class="row no-gutters align-items-center">
|
|
||||||
<div class="col mr-2">
|
|
||||||
<div class="text-xs font-weight-bold text-danger text-uppercase mb-1">
|
|
||||||
COURSES
|
|
||||||
</div>
|
|
||||||
<div class="h5 mb-0 font-weight-bold text-gray-800" id="groceries"></div>
|
|
||||||
</div>
|
|
||||||
<div class="col-auto">
|
|
||||||
<i class="fas fa-shopping-basket fa-2x text-gray-300"></i>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<!-- Earnings (Monthly) Card Example -->
|
|
||||||
<div class="col-xl-3 col-md-6 mb-4">
|
|
||||||
<div class="card border-left-danger shadow h-100 py-2">
|
|
||||||
<div class="card-body">
|
|
||||||
<div class="row no-gutters align-items-center">
|
|
||||||
<div class="col mr-2">
|
|
||||||
<div class="text-xs font-weight-bold text-danger text-uppercase mb-1">
|
|
||||||
ABONNEMENTS
|
|
||||||
</div>
|
|
||||||
<div class="h5 mb-0 font-weight-bold text-gray-800" id="additionalExpensesSub"></div>
|
|
||||||
</div>
|
|
||||||
<div class="col-auto">
|
|
||||||
<i class="fas fa-puzzle-piece fa-2x text-gray-300"></i>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="col-xl-3 col-md-6 mb-4">
|
|
||||||
<div class="card border-left-danger shadow h-100 py-2">
|
|
||||||
<div class="card-body">
|
|
||||||
<div class="row no-gutters align-items-center">
|
|
||||||
<div class="col mr-2">
|
|
||||||
<div class="text-xs font-weight-bold text-danger text-uppercase mb-1">
|
|
||||||
Autres dépenses
|
|
||||||
</div>
|
|
||||||
<div class="h5 mb-0 font-weight-bold text-gray-800" id="additionalSourcesExpense"></div>
|
|
||||||
</div>
|
|
||||||
<div class="col-auto">
|
|
||||||
<i class="fas fa-comment fa-2x text-gray-300"></i>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="col-xl-3 col-md-6 mb-4">
|
|
||||||
<div class="card border-left-danger shadow h-100 py-2">
|
|
||||||
<div class="card-body">
|
|
||||||
<div class="row no-gutters align-items-center">
|
|
||||||
<div class="col mr-2">
|
|
||||||
<div class="text-xs font-weight-bold text-danger text-uppercase mb-1">
|
|
||||||
Mis de côté
|
|
||||||
</div>
|
|
||||||
<div class="h5 mb-0 font-weight-bold text-gray-800" id="saving"></div>
|
|
||||||
</div>
|
|
||||||
<div class="col-auto">
|
|
||||||
<i class="fas fa-dollar-sign fa-2x text-gray-300"></i>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="row">
|
|
||||||
<!-- Earnings (Monthly) Card Example -->
|
|
||||||
<div class="col-xl-3 col-md-6 mb-4">
|
|
||||||
<div class="card border-left-success shadow h-100 py-2">
|
|
||||||
<div class="card-body">
|
|
||||||
<div class="row no-gutters align-items-center">
|
|
||||||
<div class="col mr-2">
|
|
||||||
<div class="text-xs font-weight-bold text-success text-uppercase mb-1">
|
|
||||||
SALAIRE
|
|
||||||
</div>
|
|
||||||
<div class="h5 mb-0 font-weight-bold text-gray-800" id="salaire"></div>
|
|
||||||
</div>
|
|
||||||
<div class="col-auto">
|
|
||||||
<i class="fas fa-user-shield fa-2x text-gray-300"></i>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
<div class="col-xl-3 col-md-6 mb-4">
|
|
||||||
<div class="card border-left-success shadow h-100 py-2">
|
|
||||||
<div class="card-body">
|
|
||||||
<div class="row no-gutters align-items-center">
|
|
||||||
<div class="col mr-2">
|
|
||||||
<div class="text-xs font-weight-bold text-success text-uppercase mb-1">
|
|
||||||
Autres gains
|
|
||||||
</div>
|
|
||||||
<div class="h5 mb-0 font-weight-bold text-gray-800" id="additionalRevenues"></div>
|
|
||||||
</div>
|
|
||||||
<div class="col-auto">
|
|
||||||
<i class="fas fa-chart-line fa-2x text-gray-300"></i>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<!-- Earnings (Monthly) Card Example -->
|
|
||||||
<div class="col-xl-3 col-md-6 mb-4" style="margin: auto!important;margin-right: 0!important;margin-top: 0 !important; flex: 0 0 25%;max-width: 25%;">
|
|
||||||
<div class="card border-left-primary shadow h-100 py-2">
|
|
||||||
<div class="card-body">
|
|
||||||
<div class="row no-gutters align-items-center">
|
|
||||||
<div class="col mr-2">
|
|
||||||
<div class="text-xs font-weight-bold text-primary text-uppercase mb-1">
|
|
||||||
Restants
|
|
||||||
</div>
|
|
||||||
<div class="h5 mb-0 font-weight-bold text-gray-800" id="result"></div>
|
|
||||||
</div>
|
|
||||||
<div class="col-auto">
|
|
||||||
<i class="fas fa-dollar fa-2x text-gray-300"></i>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<hr class="row_divider">
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<div class="row">
|
|
||||||
|
|
||||||
<!-- Area Chart -->
|
|
||||||
<div class="col-xl-8 col-lg-7">
|
|
||||||
<div class="card shadow mb-4">
|
|
||||||
<!-- Card Header - Dropdown -->
|
|
||||||
<div class="card-header py-3 d-flex flex-row align-items-center justify-content-between">
|
|
||||||
<h6 class="m-0 font-weight-bold text-primary">Earnings Overview</h6>
|
|
||||||
<div class="dropdown no-arrow">
|
|
||||||
<a class="dropdown-toggle" href="#" role="button" id="dropdownMenuLink"
|
|
||||||
data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
|
|
||||||
<i class="fas fa-ellipsis-v fa-sm fa-fw text-gray-400"></i>
|
|
||||||
</a>
|
|
||||||
<div class="dropdown-menu dropdown-menu-right shadow animated--fade-in"
|
|
||||||
aria-labelledby="dropdownMenuLink">
|
|
||||||
<div class="dropdown-header">Dropdown Header:</div>
|
|
||||||
<a class="dropdown-item" href="#">Action</a>
|
|
||||||
<a class="dropdown-item" href="#">Another action</a>
|
|
||||||
<div class="dropdown-divider"></div>
|
|
||||||
<a class="dropdown-item" href="#">Something else here</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<!-- Card Body -->
|
|
||||||
<div class="card-body">
|
|
||||||
<div class="chart-area">
|
|
||||||
<canvas id="myAreaChart"></canvas>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Pie Chart -->
|
|
||||||
<div class="col-xl-4 col-lg-5">
|
|
||||||
<div class="card shadow mb-4">
|
|
||||||
<!-- Card Header - Dropdown -->
|
|
||||||
<div class="card-header py-3 d-flex flex-row align-items-center justify-content-between">
|
|
||||||
<h6 class="m-0 font-weight-bold text-primary">Revenue Sources</h6>
|
|
||||||
<div class="dropdown no-arrow">
|
|
||||||
<a class="dropdown-toggle" href="#" role="button" id="dropdownMenuLink"
|
|
||||||
data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
|
|
||||||
<i class="fas fa-ellipsis-v fa-sm fa-fw text-gray-400"></i>
|
|
||||||
</a>
|
|
||||||
<div class="dropdown-menu dropdown-menu-right shadow animated--fade-in"
|
|
||||||
aria-labelledby="dropdownMenuLink">
|
|
||||||
<div class="dropdown-header">Dropdown Header:</div>
|
|
||||||
<a class="dropdown-item" href="#">Action</a>
|
|
||||||
<a class="dropdown-item" href="#">Another action</a>
|
|
||||||
<div class="dropdown-divider"></div>
|
|
||||||
<a class="dropdown-item" href="#">Something else here</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<!-- Card Body -->
|
|
||||||
<div class="card-body">
|
|
||||||
<div class="chart-pie pt-4 pb-2">
|
|
||||||
<canvas id="myPieChart"></canvas>
|
|
||||||
</div>
|
|
||||||
<div class="mt-4 text-center small">
|
|
||||||
<span class="mr-2">
|
|
||||||
<i class="fas fa-circle text-primary"></i> Direct
|
|
||||||
</span>
|
|
||||||
<span class="mr-2">
|
|
||||||
<i class="fas fa-circle text-success"></i> Social
|
|
||||||
</span>
|
|
||||||
<span class="mr-2">
|
|
||||||
<i class="fas fa-circle text-info"></i> Referral
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="row">
|
|
||||||
|
|
||||||
<!-- Content Column -->
|
|
||||||
<div class="col-lg-6 mb-4">
|
|
||||||
|
|
||||||
<!-- Project Card Example -->
|
|
||||||
<div class="card shadow mb-4">
|
|
||||||
<div class="card-header py-3">
|
|
||||||
<h6 class="m-0 font-weight-bold text-primary">Projects</h6>
|
|
||||||
</div>
|
|
||||||
<div class="card-body">
|
|
||||||
<h4 class="small font-weight-bold">
|
|
||||||
Server Migration <span class="float-right">20%</span>
|
|
||||||
</h4>
|
|
||||||
<div class="progress mb-4">
|
|
||||||
<div class="progress-bar bg-danger" role="progressbar" style="width: 20%"
|
|
||||||
aria-valuenow="20" aria-valuemin="0" aria-valuemax="100"></div>
|
|
||||||
</div>
|
|
||||||
<h4 class="small font-weight-bold">
|
|
||||||
Sales Tracking <span class="float-right">40%</span>
|
|
||||||
</h4>
|
|
||||||
<div class="progress mb-4">
|
|
||||||
<div class="progress-bar bg-warning" role="progressbar" style="width: 40%"
|
|
||||||
aria-valuenow="40" aria-valuemin="0" aria-valuemax="100"></div>
|
|
||||||
</div>
|
|
||||||
<h4 class="small font-weight-bold">
|
|
||||||
Customer Database <span class="float-right">60%</span>
|
|
||||||
</h4>
|
|
||||||
<div class="progress mb-4">
|
|
||||||
<div class="progress-bar" role="progressbar" style="width: 60%"
|
|
||||||
aria-valuenow="60" aria-valuemin="0" aria-valuemax="100"></div>
|
|
||||||
</div>
|
|
||||||
<h4 class="small font-weight-bold">
|
|
||||||
Payout Details <span class="float-right">80%</span>
|
|
||||||
</h4>
|
|
||||||
<div class="progress mb-4">
|
|
||||||
<div class="progress-bar bg-info" role="progressbar" style="width: 80%"
|
|
||||||
aria-valuenow="80" aria-valuemin="0" aria-valuemax="100"></div>
|
|
||||||
</div>
|
|
||||||
<h4 class="small font-weight-bold">
|
|
||||||
Account Setup <span class="float-right">Complete!</span>
|
|
||||||
</h4>
|
|
||||||
<div class="progress">
|
|
||||||
<div class="progress-bar bg-success" role="progressbar" style="width: 100%"
|
|
||||||
aria-valuenow="100" aria-valuemin="0" aria-valuemax="100"></div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Color System -->
|
|
||||||
<div class="row">
|
|
||||||
<div class="col-lg-6 mb-4">
|
|
||||||
<div class="card bg-primary text-white shadow">
|
|
||||||
<div class="card-body">
|
|
||||||
Primary
|
|
||||||
<div class="text-white-50 small">#4e73df</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="col-lg-6 mb-4">
|
|
||||||
<div class="card bg-success text-white shadow">
|
|
||||||
<div class="card-body">
|
|
||||||
Success
|
|
||||||
<div class="text-white-50 small">#1cc88a</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="col-lg-6 mb-4">
|
|
||||||
<div class="card bg-info text-white shadow">
|
|
||||||
<div class="card-body">
|
|
||||||
Info
|
|
||||||
<div class="text-white-50 small">#36b9cc</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="col-lg-6 mb-4">
|
|
||||||
<div class="card bg-warning text-white shadow">
|
|
||||||
<div class="card-body">
|
|
||||||
Warning
|
|
||||||
<div class="text-white-50 small">#f6c23e</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="col-lg-6 mb-4">
|
|
||||||
<div class="card bg-danger text-white shadow">
|
|
||||||
<div class="card-body">
|
|
||||||
Danger
|
|
||||||
<div class="text-white-50 small">#e74a3b</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="col-lg-6 mb-4">
|
|
||||||
<div class="card bg-secondary text-white shadow">
|
|
||||||
<div class="card-body">
|
|
||||||
Secondary
|
|
||||||
<div class="text-white-50 small">#858796</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="col-lg-6 mb-4">
|
|
||||||
<div class="card bg-light text-black shadow">
|
|
||||||
<div class="card-body">
|
|
||||||
Light
|
|
||||||
<div class="text-black-50 small">#f8f9fc</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="col-lg-6 mb-4">
|
|
||||||
<div class="card bg-dark text-white shadow">
|
|
||||||
<div class="card-body">
|
|
||||||
Dark
|
|
||||||
<div class="text-white-50 small">#5a5c69</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="col-lg-6 mb-4">
|
|
||||||
|
|
||||||
<!-- Illustrations -->
|
|
||||||
<div class="card shadow mb-4">
|
|
||||||
<div class="card-header py-3">
|
|
||||||
<h6 class="m-0 font-weight-bold text-primary">Illustrations</h6>
|
|
||||||
</div>
|
|
||||||
<div class="card-body">
|
|
||||||
<div class="text-center">
|
|
||||||
<img class="img-fluid px-3 px-sm-4 mt-3 mb-4" style="width: 25rem;"
|
|
||||||
src="~/images/undraw_posting_photo.svg" alt="...">
|
|
||||||
</div>
|
|
||||||
<p>
|
|
||||||
Add some quality, svg illustrations to your project courtesy of <a target="_blank" rel="nofollow" href="https://undraw.co/">unDraw</a>, a
|
|
||||||
constantly updated collection of beautiful svg images that you can use
|
|
||||||
completely free and without attribution!
|
|
||||||
</p>
|
|
||||||
<a target="_blank" rel="nofollow" href="https://undraw.co/">
|
|
||||||
Browse Illustrations on
|
|
||||||
unDraw →
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Approach -->
|
|
||||||
<div class="card shadow mb-4">
|
|
||||||
<div class="card-header py-3">
|
|
||||||
<h6 class="m-0 font-weight-bold text-primary">Development Approach</h6>
|
|
||||||
</div>
|
|
||||||
<div class="card-body">
|
|
||||||
<p>
|
|
||||||
SB Admin 2 makes extensive use of Bootstrap 4 utility classes in order to reduce
|
|
||||||
CSS bloat and poor page performance. Custom CSS classes are used to create
|
|
||||||
custom components and custom utility classes.
|
|
||||||
</p>
|
|
||||||
<p class="mb-0">
|
|
||||||
Before working with this theme, you should become familiar with the
|
|
||||||
Bootstrap framework, especially the utility classes.
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
<!-- /.container-fluid -->
|
|
||||||
|
|
||||||
</div>
|
|
||||||
<!-- End of Main Content -->
|
|
||||||
<!-- Footer -->
|
|
||||||
<footer class="sticky-footer bg-white">
|
|
||||||
<div class="container my-auto">
|
|
||||||
<div class="copyright text-center my-auto">
|
|
||||||
<span>Copyright © Your Website 2021</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</footer>
|
|
||||||
<!-- End of Footer -->
|
|
||||||
|
|
||||||
</div>
|
|
||||||
<!-- End of Content Wrapper -->
|
|
||||||
|
|
||||||
</div>
|
|
||||||
<!-- End of Page Wrapper -->
|
|
||||||
<!-- Scroll to Top Button-->
|
|
||||||
<a class="scroll-to-top rounded" href="#page-top">
|
|
||||||
<i class="fas fa-angle-up"></i>
|
|
||||||
</a>
|
|
||||||
|
|
||||||
<!-- Logout Modal-->
|
|
||||||
<div class="modal fade" id="logoutModal" tabindex="-1" role="dialog" aria-labelledby="exampleModalLabel"
|
|
||||||
aria-hidden="true">
|
|
||||||
<div class="modal-dialog" role="document">
|
|
||||||
<div class="modal-content">
|
|
||||||
<div class="modal-header">
|
|
||||||
<h5 class="modal-title" id="exampleModalLabel">Ready to Leave?</h5>
|
|
||||||
<button class="close" type="button" data-dismiss="modal" aria-label="Close">
|
|
||||||
<span aria-hidden="true">×</span>
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
<div class="modal-body">Select "Logout" below if you are ready to end your current session.</div>
|
|
||||||
<div class="modal-footer">
|
|
||||||
<button class="btn btn-secondary" type="button" data-dismiss="modal">Cancel</button>
|
|
||||||
<a class="btn btn-primary" href="login.html">Logout</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<script src="~/js/home.js" asp-append-version="true"></script>
|
||||||
<script src="~/js/index.js" asp-append-version="true"></script>
|
|
||||||
|
|||||||
@@ -9,26 +9,113 @@
|
|||||||
<link rel="stylesheet" href="~/css/site.css" asp-append-version="true" />
|
<link rel="stylesheet" href="~/css/site.css" asp-append-version="true" />
|
||||||
<link rel="stylesheet" href="~/administration.styles.css" asp-append-version="true" />
|
<link rel="stylesheet" href="~/administration.styles.css" asp-append-version="true" />
|
||||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.1/font/bootstrap-icons.css">
|
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.1/font/bootstrap-icons.css">
|
||||||
|
<link href="https://cdn.jsdelivr.net/npm/select2@4.1.0-rc.0/dist/css/select2.min.css" rel="stylesheet" />
|
||||||
|
|
||||||
|
|
||||||
|
<link rel="stylesheet" href="~/lib/datatable/datatables.min.css" />
|
||||||
</head>
|
</head>
|
||||||
<body id="page-top">
|
<body id="page-top">
|
||||||
|
|
||||||
|
<nav class="navbar navbar-expand navbar-light bg-white topbar mb-4 static-top shadow">
|
||||||
|
<div class="container-fluid">
|
||||||
|
<!-- Logo -->
|
||||||
|
<a class="navbar-brand d-flex align-items-center" href="/" style="gap: 8px;">
|
||||||
|
<img src="~/images/logo.png" alt="Accueil" style="height: 45px; width: 45px;">
|
||||||
|
</a>
|
||||||
|
|
||||||
@RenderBody()
|
<div class="collapse navbar-collapse" id="navbarSupportedContent">
|
||||||
|
<ul class="navbar-nav me-auto mb-2 mb-lg-0">
|
||||||
|
@* <li class="nav-item">
|
||||||
|
<a class="nav-link titleSidebar" style="cursor: pointer" onclick="window.location.href = '/Finances'" aria-current="page" href="#">Finances</a>
|
||||||
|
</li> *@
|
||||||
|
<li class="nav-item dropdown">
|
||||||
|
<a href="javascript:void(0)" class="nav-link dropdown-toggle" role="button" data-bs-toggle="dropdown" aria-expanded="false">
|
||||||
|
Hello Fresh
|
||||||
|
</a>
|
||||||
|
<ul class="dropdown-menu">
|
||||||
|
<li><a class="dropdown-item" onclick="window.location.href = '/HelloFresh'">Choix des recettes</a></li>
|
||||||
|
<li><a class="dropdown-item" onclick="window.location.href = '/HelloFresh/ingredients'">Ingrédients</a></li>
|
||||||
|
<li><a class="dropdown-item" onclick="window.location.href = '/HelloFresh/historique'">Historique</a></li>
|
||||||
|
<li><a class="dropdown-item" onclick="window.location.href = '/HelloFresh/cuisine'">Cuisine</a></li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
<!-- Menu utilisateur à droite -->
|
||||||
|
<ul class="navbar-nav ms-auto">
|
||||||
|
<li class="nav-item dropdown no-arrow">
|
||||||
|
<a class="nav-link dropdown-toggle" href="#" id="userDropdown" role="button"
|
||||||
|
data-bs-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
|
||||||
|
<span class="mr-2 d-none d-lg-inline text-gray-600 small">
|
||||||
|
@{
|
||||||
|
var userName = Context.Session.GetString("UserName");
|
||||||
|
}
|
||||||
|
@userName
|
||||||
|
</span>
|
||||||
|
<img class="img-profile rounded-circle" src="/images/undraw_profile.svg">
|
||||||
|
</a>
|
||||||
|
<div class="dropdown-menu dropdown-menu-right shadow animated--grow-in"
|
||||||
|
aria-labelledby="userDropdown">
|
||||||
|
<a class="dropdown-item" href="#">
|
||||||
|
<i class="fas fa-user fa-sm fa-fw mr-2 text-gray-400"></i>
|
||||||
|
Profile
|
||||||
|
</a>
|
||||||
|
<a class="dropdown-item" href="#">
|
||||||
|
<i class="fas fa-cogs fa-sm fa-fw mr-2 text-gray-400"></i>
|
||||||
|
Settings
|
||||||
|
</a>
|
||||||
|
<a class="dropdown-item" href="#">
|
||||||
|
<i class="fas fa-list fa-sm fa-fw mr-2 text-gray-400"></i>
|
||||||
|
Activity Log
|
||||||
|
</a>
|
||||||
|
<div class="dropdown-divider"></div>
|
||||||
|
<form asp-controller="Connections" asp-action="Logout" method="post" class="dropdown-item p-0 m-0">
|
||||||
|
@Html.AntiForgeryToken()
|
||||||
|
<button type="submit" class="btn w-100 text-start">
|
||||||
|
<i class="fas fa-sign-out-alt fa-sm fa-fw mr-2 text-gray-400"></i> Logout
|
||||||
|
</button>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</nav>
|
||||||
|
|
||||||
|
<div class="main-wrapper">
|
||||||
|
@* <div class="sidebar">
|
||||||
|
<h2 class="titleSidebar" style="cursor: pointer" onclick="window.location.href = '/Finances'">Finances</h2>
|
||||||
|
<h2 class="titleSidebar">Hello Fresh</h2>
|
||||||
|
<ul class="ulSidebar">
|
||||||
|
<li class="subTitle" onclick="window.location.href = '/HelloFresh'">Recettes</li>
|
||||||
|
<li class="subTitle" onclick="window.location.href = '/HelloFresh/ingredients'">Ingrédients</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
@* <img class="logoSidebar" onclick="window.location.href = '/Finances'" src="~/images/cardLogo.png" />
|
||||||
|
<img class="logoSidebar" onclick="window.location.href = '/HelloFresh'" src="~/images/HFLogo.png" />
|
||||||
|
</div> *@
|
||||||
|
|
||||||
|
<div class="content">
|
||||||
|
@RenderBody()
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<script src="~/lib/jquery/dist/jquery.min.js"></script>
|
<script src="~/lib/jquery/dist/jquery.min.js"></script>
|
||||||
<script src="~/lib/bootstrap/dist/js/bootstrap.bundle.min.js"></script>
|
<script src="~/lib/bootstrap/dist/js/bootstrap.bundle.min.js"></script>
|
||||||
|
|
||||||
<!-- Page level plugins -->
|
|
||||||
<script src="~/lib/chart.js/Chart.min.js"></script>
|
|
||||||
|
|
||||||
<!-- Page level custom scripts -->
|
|
||||||
<script src="~/js/demo/chart-area-demo.js"></script>
|
|
||||||
<script src="~/js/demo/chart-pie-demo.js"></script>
|
|
||||||
<script src="~/js/demo/chart-bar-demo.js"></script>
|
|
||||||
<script src="~/lib/jquery-easing/jquery.easing.js"></script>
|
<script src="~/lib/jquery-easing/jquery.easing.js"></script>
|
||||||
|
|
||||||
|
<!-- ✅ Popper.js -->
|
||||||
|
<script src="https://unpkg.com/@@popperjs/core@2"></script>
|
||||||
|
|
||||||
|
<!-- ✅ Tippy.js -->
|
||||||
|
<script src="https://unpkg.com/tippy.js@6/dist/tippy-bundle.umd.min.js"></script>
|
||||||
|
|
||||||
<script src="~/js/api.js" asp-append-version="true"></script>
|
<script src="~/js/api.js" asp-append-version="true"></script>
|
||||||
<script src="~/js/site.js" asp-append-version="true"></script>
|
<script src="~/js/site.js" asp-append-version="true"></script>
|
||||||
|
<!-- Select2 -->
|
||||||
|
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/select2@4.1.0-rc.0/dist/css/select2.min.css">
|
||||||
|
<script src="https://cdn.jsdelivr.net/npm/select2@4.1.0-rc.0/dist/js/select2.min.js" crossorigin="anonymous"></script>
|
||||||
|
<script src="~/lib/datatable/datatables.min.js" ></script>
|
||||||
@await RenderSectionAsync("Scripts", required: false)
|
@await RenderSectionAsync("Scripts", required: false)
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
@@ -1,929 +0,0 @@
|
|||||||
<!DOCTYPE html>
|
|
||||||
<html lang="en">
|
|
||||||
|
|
||||||
<head>
|
|
||||||
|
|
||||||
<meta charset="utf-8">
|
|
||||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
|
||||||
<meta name="description" content="">
|
|
||||||
<meta name="author" content="">
|
|
||||||
|
|
||||||
<title>SB Admin 2 - Tables</title>
|
|
||||||
|
|
||||||
<!-- Custom fonts for this template -->
|
|
||||||
<link href="vendor/fontawesome-free/css/all.min.css" rel="stylesheet" type="text/css">
|
|
||||||
<link
|
|
||||||
href="https://fonts.googleapis.com/css?family=Nunito:200,200i,300,300i,400,400i,600,600i,700,700i,800,800i,900,900i"
|
|
||||||
rel="stylesheet">
|
|
||||||
|
|
||||||
<!-- Custom styles for this template -->
|
|
||||||
<link href="css/sb-admin-2.min.css" rel="stylesheet">
|
|
||||||
|
|
||||||
<!-- Custom styles for this page -->
|
|
||||||
<link href="vendor/datatables/dataTables.bootstrap4.min.css" rel="stylesheet">
|
|
||||||
|
|
||||||
</head>
|
|
||||||
|
|
||||||
<body id="page-top">
|
|
||||||
|
|
||||||
<!-- Page Wrapper -->
|
|
||||||
<div id="wrapper">
|
|
||||||
|
|
||||||
<!-- Sidebar -->
|
|
||||||
<ul class="navbar-nav bg-gradient-primary sidebar sidebar-dark accordion" id="accordionSidebar">
|
|
||||||
|
|
||||||
<!-- Sidebar - Brand -->
|
|
||||||
<a class="sidebar-brand d-flex align-items-center justify-content-center" href="index.html">
|
|
||||||
<div class="sidebar-brand-icon rotate-n-15">
|
|
||||||
<i class="fas fa-laugh-wink"></i>
|
|
||||||
</div>
|
|
||||||
<div class="sidebar-brand-text mx-3">SB Admin <sup>2</sup></div>
|
|
||||||
</a>
|
|
||||||
|
|
||||||
<!-- Divider -->
|
|
||||||
<hr class="sidebar-divider my-0">
|
|
||||||
|
|
||||||
<!-- Nav Item - Dashboard -->
|
|
||||||
<li class="nav-item">
|
|
||||||
<a class="nav-link" href="index.html">
|
|
||||||
<i class="fas fa-fw fa-tachometer-alt"></i>
|
|
||||||
<span>Dashboard</span></a>
|
|
||||||
</li>
|
|
||||||
|
|
||||||
<!-- Divider -->
|
|
||||||
<hr class="sidebar-divider">
|
|
||||||
|
|
||||||
<!-- Heading -->
|
|
||||||
<div class="sidebar-heading">
|
|
||||||
Interface
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Nav Item - Pages Collapse Menu -->
|
|
||||||
<li class="nav-item">
|
|
||||||
<a class="nav-link collapsed" href="#" data-toggle="collapse" data-target="#collapseTwo"
|
|
||||||
aria-expanded="true" aria-controls="collapseTwo">
|
|
||||||
<i class="fas fa-fw fa-cog"></i>
|
|
||||||
<span>Components</span>
|
|
||||||
</a>
|
|
||||||
<div id="collapseTwo" class="collapse" aria-labelledby="headingTwo" data-parent="#accordionSidebar">
|
|
||||||
<div class="bg-white py-2 collapse-inner rounded">
|
|
||||||
<h6 class="collapse-header">Custom Components:</h6>
|
|
||||||
<a class="collapse-item" href="buttons.html">Buttons</a>
|
|
||||||
<a class="collapse-item" href="cards.html">Cards</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</li>
|
|
||||||
|
|
||||||
<!-- Nav Item - Utilities Collapse Menu -->
|
|
||||||
<li class="nav-item">
|
|
||||||
<a class="nav-link collapsed" href="#" data-toggle="collapse" data-target="#collapseUtilities"
|
|
||||||
aria-expanded="true" aria-controls="collapseUtilities">
|
|
||||||
<i class="fas fa-fw fa-wrench"></i>
|
|
||||||
<span>Utilities</span>
|
|
||||||
</a>
|
|
||||||
<div id="collapseUtilities" class="collapse" aria-labelledby="headingUtilities"
|
|
||||||
data-parent="#accordionSidebar">
|
|
||||||
<div class="bg-white py-2 collapse-inner rounded">
|
|
||||||
<h6 class="collapse-header">Custom Utilities:</h6>
|
|
||||||
<a class="collapse-item" href="utilities-color.html">Colors</a>
|
|
||||||
<a class="collapse-item" href="utilities-border.html">Borders</a>
|
|
||||||
<a class="collapse-item" href="utilities-animation.html">Animations</a>
|
|
||||||
<a class="collapse-item" href="utilities-other.html">Other</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</li>
|
|
||||||
|
|
||||||
<!-- Divider -->
|
|
||||||
<hr class="sidebar-divider">
|
|
||||||
|
|
||||||
<!-- Heading -->
|
|
||||||
<div class="sidebar-heading">
|
|
||||||
Addons
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Nav Item - Pages Collapse Menu -->
|
|
||||||
<li class="nav-item">
|
|
||||||
<a class="nav-link collapsed" href="#" data-toggle="collapse" data-target="#collapsePages"
|
|
||||||
aria-expanded="true" aria-controls="collapsePages">
|
|
||||||
<i class="fas fa-fw fa-folder"></i>
|
|
||||||
<span>Pages</span>
|
|
||||||
</a>
|
|
||||||
<div id="collapsePages" class="collapse" aria-labelledby="headingPages" data-parent="#accordionSidebar">
|
|
||||||
<div class="bg-white py-2 collapse-inner rounded">
|
|
||||||
<h6 class="collapse-header">Login Screens:</h6>
|
|
||||||
<a class="collapse-item" href="login.html">Login</a>
|
|
||||||
<a class="collapse-item" href="register.html">Register</a>
|
|
||||||
<a class="collapse-item" href="forgot-password.html">Forgot Password</a>
|
|
||||||
<div class="collapse-divider"></div>
|
|
||||||
<h6 class="collapse-header">Other Pages:</h6>
|
|
||||||
<a class="collapse-item" href="404.html">404 Page</a>
|
|
||||||
<a class="collapse-item" href="blank.html">Blank Page</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</li>
|
|
||||||
|
|
||||||
<!-- Nav Item - Charts -->
|
|
||||||
<li class="nav-item">
|
|
||||||
<a class="nav-link" href="charts.html">
|
|
||||||
<i class="fas fa-fw fa-chart-area"></i>
|
|
||||||
<span>Charts</span></a>
|
|
||||||
</li>
|
|
||||||
|
|
||||||
<!-- Nav Item - Tables -->
|
|
||||||
<li class="nav-item active">
|
|
||||||
<a class="nav-link" href="tables.html">
|
|
||||||
<i class="fas fa-fw fa-table"></i>
|
|
||||||
<span>Tables</span></a>
|
|
||||||
</li>
|
|
||||||
|
|
||||||
<!-- Divider -->
|
|
||||||
<hr class="sidebar-divider d-none d-md-block">
|
|
||||||
|
|
||||||
<!-- Sidebar Toggler (Sidebar) -->
|
|
||||||
<div class="text-center d-none d-md-inline">
|
|
||||||
<button class="rounded-circle border-0" id="sidebarToggle"></button>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</ul>
|
|
||||||
<!-- End of Sidebar -->
|
|
||||||
|
|
||||||
<!-- Content Wrapper -->
|
|
||||||
<div id="content-wrapper" class="d-flex flex-column">
|
|
||||||
|
|
||||||
<!-- Main Content -->
|
|
||||||
<div id="content">
|
|
||||||
|
|
||||||
<!-- Topbar -->
|
|
||||||
<nav class="navbar navbar-expand navbar-light bg-white topbar mb-4 static-top shadow">
|
|
||||||
|
|
||||||
<!-- Sidebar Toggle (Topbar) -->
|
|
||||||
<form class="form-inline">
|
|
||||||
<button id="sidebarToggleTop" class="btn btn-link d-md-none rounded-circle mr-3">
|
|
||||||
<i class="fa fa-bars"></i>
|
|
||||||
</button>
|
|
||||||
</form>
|
|
||||||
|
|
||||||
<!-- Topbar Search -->
|
|
||||||
<form
|
|
||||||
class="d-none d-sm-inline-block form-inline mr-auto ml-md-3 my-2 my-md-0 mw-100 navbar-search">
|
|
||||||
<div class="input-group">
|
|
||||||
<input type="text" class="form-control bg-light border-0 small" placeholder="Search for..."
|
|
||||||
aria-label="Search" aria-describedby="basic-addon2">
|
|
||||||
<div class="input-group-append">
|
|
||||||
<button class="btn btn-primary" type="button">
|
|
||||||
<i class="fas fa-search fa-sm"></i>
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
|
|
||||||
<!-- Topbar Navbar -->
|
|
||||||
<ul class="navbar-nav ml-auto">
|
|
||||||
|
|
||||||
<!-- Nav Item - Search Dropdown (Visible Only XS) -->
|
|
||||||
<li class="nav-item dropdown no-arrow d-sm-none">
|
|
||||||
<a class="nav-link dropdown-toggle" href="#" id="searchDropdown" role="button"
|
|
||||||
data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
|
|
||||||
<i class="fas fa-search fa-fw"></i>
|
|
||||||
</a>
|
|
||||||
<!-- Dropdown - Messages -->
|
|
||||||
<div class="dropdown-menu dropdown-menu-right p-3 shadow animated--grow-in"
|
|
||||||
aria-labelledby="searchDropdown">
|
|
||||||
<form class="form-inline mr-auto w-100 navbar-search">
|
|
||||||
<div class="input-group">
|
|
||||||
<input type="text" class="form-control bg-light border-0 small"
|
|
||||||
placeholder="Search for..." aria-label="Search"
|
|
||||||
aria-describedby="basic-addon2">
|
|
||||||
<div class="input-group-append">
|
|
||||||
<button class="btn btn-primary" type="button">
|
|
||||||
<i class="fas fa-search fa-sm"></i>
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
</li>
|
|
||||||
|
|
||||||
<!-- Nav Item - Alerts -->
|
|
||||||
<li class="nav-item dropdown no-arrow mx-1">
|
|
||||||
<a class="nav-link dropdown-toggle" href="#" id="alertsDropdown" role="button"
|
|
||||||
data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
|
|
||||||
<i class="fas fa-bell fa-fw"></i>
|
|
||||||
<!-- Counter - Alerts -->
|
|
||||||
<span class="badge badge-danger badge-counter">3+</span>
|
|
||||||
</a>
|
|
||||||
<!-- Dropdown - Alerts -->
|
|
||||||
<div class="dropdown-list dropdown-menu dropdown-menu-right shadow animated--grow-in"
|
|
||||||
aria-labelledby="alertsDropdown">
|
|
||||||
<h6 class="dropdown-header">
|
|
||||||
Alerts Center
|
|
||||||
</h6>
|
|
||||||
<a class="dropdown-item d-flex align-items-center" href="#">
|
|
||||||
<div class="mr-3">
|
|
||||||
<div class="icon-circle bg-primary">
|
|
||||||
<i class="fas fa-file-alt text-white"></i>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<div class="small text-gray-500">December 12, 2019</div>
|
|
||||||
<span class="font-weight-bold">A new monthly report is ready to download!</span>
|
|
||||||
</div>
|
|
||||||
</a>
|
|
||||||
<a class="dropdown-item d-flex align-items-center" href="#">
|
|
||||||
<div class="mr-3">
|
|
||||||
<div class="icon-circle bg-success">
|
|
||||||
<i class="fas fa-donate text-white"></i>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<div class="small text-gray-500">December 7, 2019</div>
|
|
||||||
$290.29 has been deposited into your account!
|
|
||||||
</div>
|
|
||||||
</a>
|
|
||||||
<a class="dropdown-item d-flex align-items-center" href="#">
|
|
||||||
<div class="mr-3">
|
|
||||||
<div class="icon-circle bg-warning">
|
|
||||||
<i class="fas fa-exclamation-triangle text-white"></i>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<div class="small text-gray-500">December 2, 2019</div>
|
|
||||||
Spending Alert: We've noticed unusually high spending for your account.
|
|
||||||
</div>
|
|
||||||
</a>
|
|
||||||
<a class="dropdown-item text-center small text-gray-500" href="#">Show All Alerts</a>
|
|
||||||
</div>
|
|
||||||
</li>
|
|
||||||
|
|
||||||
<!-- Nav Item - Messages -->
|
|
||||||
<li class="nav-item dropdown no-arrow mx-1">
|
|
||||||
<a class="nav-link dropdown-toggle" href="#" id="messagesDropdown" role="button"
|
|
||||||
data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
|
|
||||||
<i class="fas fa-envelope fa-fw"></i>
|
|
||||||
<!-- Counter - Messages -->
|
|
||||||
<span class="badge badge-danger badge-counter">7</span>
|
|
||||||
</a>
|
|
||||||
<!-- Dropdown - Messages -->
|
|
||||||
<div class="dropdown-list dropdown-menu dropdown-menu-right shadow animated--grow-in"
|
|
||||||
aria-labelledby="messagesDropdown">
|
|
||||||
<h6 class="dropdown-header">
|
|
||||||
Message Center
|
|
||||||
</h6>
|
|
||||||
<a class="dropdown-item d-flex align-items-center" href="#">
|
|
||||||
<div class="dropdown-list-image mr-3">
|
|
||||||
<img class="rounded-circle" src="img/undraw_profile_1.svg"
|
|
||||||
alt="...">
|
|
||||||
<div class="status-indicator bg-success"></div>
|
|
||||||
</div>
|
|
||||||
<div class="font-weight-bold">
|
|
||||||
<div class="text-truncate">Hi there! I am wondering if you can help me with a
|
|
||||||
problem I've been having.</div>
|
|
||||||
<div class="small text-gray-500">Emily Fowler · 58m</div>
|
|
||||||
</div>
|
|
||||||
</a>
|
|
||||||
<a class="dropdown-item d-flex align-items-center" href="#">
|
|
||||||
<div class="dropdown-list-image mr-3">
|
|
||||||
<img class="rounded-circle" src="img/undraw_profile_2.svg"
|
|
||||||
alt="...">
|
|
||||||
<div class="status-indicator"></div>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<div class="text-truncate">I have the photos that you ordered last month, how
|
|
||||||
would you like them sent to you?</div>
|
|
||||||
<div class="small text-gray-500">Jae Chun · 1d</div>
|
|
||||||
</div>
|
|
||||||
</a>
|
|
||||||
<a class="dropdown-item d-flex align-items-center" href="#">
|
|
||||||
<div class="dropdown-list-image mr-3">
|
|
||||||
<img class="rounded-circle" src="img/undraw_profile_3.svg"
|
|
||||||
alt="...">
|
|
||||||
<div class="status-indicator bg-warning"></div>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<div class="text-truncate">Last month's report looks great, I am very happy with
|
|
||||||
the progress so far, keep up the good work!</div>
|
|
||||||
<div class="small text-gray-500">Morgan Alvarez · 2d</div>
|
|
||||||
</div>
|
|
||||||
</a>
|
|
||||||
<a class="dropdown-item d-flex align-items-center" href="#">
|
|
||||||
<div class="dropdown-list-image mr-3">
|
|
||||||
<img class="rounded-circle" src="https://source.unsplash.com/Mv9hjnEUHR4/60x60"
|
|
||||||
alt="...">
|
|
||||||
<div class="status-indicator bg-success"></div>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<div class="text-truncate">Am I a good boy? The reason I ask is because someone
|
|
||||||
told me that people say this to all dogs, even if they aren't good...</div>
|
|
||||||
<div class="small text-gray-500">Chicken the Dog · 2w</div>
|
|
||||||
</div>
|
|
||||||
</a>
|
|
||||||
<a class="dropdown-item text-center small text-gray-500" href="#">Read More Messages</a>
|
|
||||||
</div>
|
|
||||||
</li>
|
|
||||||
|
|
||||||
<div class="topbar-divider d-none d-sm-block"></div>
|
|
||||||
|
|
||||||
<!-- Nav Item - User Information -->
|
|
||||||
<li class="nav-item dropdown no-arrow">
|
|
||||||
<a class="nav-link dropdown-toggle" href="#" id="userDropdown" role="button"
|
|
||||||
data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
|
|
||||||
<span class="mr-2 d-none d-lg-inline text-gray-600 small">Douglas McGee</span>
|
|
||||||
<img class="img-profile rounded-circle"
|
|
||||||
src="img/undraw_profile.svg">
|
|
||||||
</a>
|
|
||||||
<!-- Dropdown - User Information -->
|
|
||||||
<div class="dropdown-menu dropdown-menu-right shadow animated--grow-in"
|
|
||||||
aria-labelledby="userDropdown">
|
|
||||||
<a class="dropdown-item" href="#">
|
|
||||||
<i class="fas fa-user fa-sm fa-fw mr-2 text-gray-400"></i>
|
|
||||||
Profile
|
|
||||||
</a>
|
|
||||||
<a class="dropdown-item" href="#">
|
|
||||||
<i class="fas fa-cogs fa-sm fa-fw mr-2 text-gray-400"></i>
|
|
||||||
Settings
|
|
||||||
</a>
|
|
||||||
<a class="dropdown-item" href="#">
|
|
||||||
<i class="fas fa-list fa-sm fa-fw mr-2 text-gray-400"></i>
|
|
||||||
Activity Log
|
|
||||||
</a>
|
|
||||||
<div class="dropdown-divider"></div>
|
|
||||||
<a class="dropdown-item" href="#" data-toggle="modal" data-target="#logoutModal">
|
|
||||||
<i class="fas fa-sign-out-alt fa-sm fa-fw mr-2 text-gray-400"></i>
|
|
||||||
Logout
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
</li>
|
|
||||||
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
</nav>
|
|
||||||
<!-- End of Topbar -->
|
|
||||||
|
|
||||||
<!-- Begin Page Content -->
|
|
||||||
<div class="container-fluid">
|
|
||||||
|
|
||||||
<!-- Page Heading -->
|
|
||||||
<h1 class="h3 mb-2 text-gray-800">Tables</h1>
|
|
||||||
<p class="mb-4">DataTables is a third party plugin that is used to generate the demo table below.
|
|
||||||
For more information about DataTables, please visit the <a target="_blank"
|
|
||||||
href="https://datatables.net">official DataTables documentation</a>.</p>
|
|
||||||
|
|
||||||
<!-- DataTales Example -->
|
|
||||||
<div class="card shadow mb-4">
|
|
||||||
<div class="card-header py-3">
|
|
||||||
<h6 class="m-0 font-weight-bold text-primary">DataTables Example</h6>
|
|
||||||
</div>
|
|
||||||
<div class="card-body">
|
|
||||||
<div class="table-responsive">
|
|
||||||
<table class="table table-bordered" id="dataTable" width="100%" cellspacing="0">
|
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<th>Name</th>
|
|
||||||
<th>Position</th>
|
|
||||||
<th>Office</th>
|
|
||||||
<th>Age</th>
|
|
||||||
<th>Start date</th>
|
|
||||||
<th>Salary</th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tfoot>
|
|
||||||
<tr>
|
|
||||||
<th>Name</th>
|
|
||||||
<th>Position</th>
|
|
||||||
<th>Office</th>
|
|
||||||
<th>Age</th>
|
|
||||||
<th>Start date</th>
|
|
||||||
<th>Salary</th>
|
|
||||||
</tr>
|
|
||||||
</tfoot>
|
|
||||||
<tbody>
|
|
||||||
<tr>
|
|
||||||
<td>Tiger Nixon</td>
|
|
||||||
<td>System Architect</td>
|
|
||||||
<td>Edinburgh</td>
|
|
||||||
<td>61</td>
|
|
||||||
<td>2011/04/25</td>
|
|
||||||
<td>$320,800</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>Garrett Winters</td>
|
|
||||||
<td>Accountant</td>
|
|
||||||
<td>Tokyo</td>
|
|
||||||
<td>63</td>
|
|
||||||
<td>2011/07/25</td>
|
|
||||||
<td>$170,750</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>Ashton Cox</td>
|
|
||||||
<td>Junior Technical Author</td>
|
|
||||||
<td>San Francisco</td>
|
|
||||||
<td>66</td>
|
|
||||||
<td>2009/01/12</td>
|
|
||||||
<td>$86,000</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>Cedric Kelly</td>
|
|
||||||
<td>Senior Javascript Developer</td>
|
|
||||||
<td>Edinburgh</td>
|
|
||||||
<td>22</td>
|
|
||||||
<td>2012/03/29</td>
|
|
||||||
<td>$433,060</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>Airi Satou</td>
|
|
||||||
<td>Accountant</td>
|
|
||||||
<td>Tokyo</td>
|
|
||||||
<td>33</td>
|
|
||||||
<td>2008/11/28</td>
|
|
||||||
<td>$162,700</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>Brielle Williamson</td>
|
|
||||||
<td>Integration Specialist</td>
|
|
||||||
<td>New York</td>
|
|
||||||
<td>61</td>
|
|
||||||
<td>2012/12/02</td>
|
|
||||||
<td>$372,000</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>Herrod Chandler</td>
|
|
||||||
<td>Sales Assistant</td>
|
|
||||||
<td>San Francisco</td>
|
|
||||||
<td>59</td>
|
|
||||||
<td>2012/08/06</td>
|
|
||||||
<td>$137,500</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>Rhona Davidson</td>
|
|
||||||
<td>Integration Specialist</td>
|
|
||||||
<td>Tokyo</td>
|
|
||||||
<td>55</td>
|
|
||||||
<td>2010/10/14</td>
|
|
||||||
<td>$327,900</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>Colleen Hurst</td>
|
|
||||||
<td>Javascript Developer</td>
|
|
||||||
<td>San Francisco</td>
|
|
||||||
<td>39</td>
|
|
||||||
<td>2009/09/15</td>
|
|
||||||
<td>$205,500</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>Sonya Frost</td>
|
|
||||||
<td>Software Engineer</td>
|
|
||||||
<td>Edinburgh</td>
|
|
||||||
<td>23</td>
|
|
||||||
<td>2008/12/13</td>
|
|
||||||
<td>$103,600</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>Jena Gaines</td>
|
|
||||||
<td>Office Manager</td>
|
|
||||||
<td>London</td>
|
|
||||||
<td>30</td>
|
|
||||||
<td>2008/12/19</td>
|
|
||||||
<td>$90,560</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>Quinn Flynn</td>
|
|
||||||
<td>Support Lead</td>
|
|
||||||
<td>Edinburgh</td>
|
|
||||||
<td>22</td>
|
|
||||||
<td>2013/03/03</td>
|
|
||||||
<td>$342,000</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>Charde Marshall</td>
|
|
||||||
<td>Regional Director</td>
|
|
||||||
<td>San Francisco</td>
|
|
||||||
<td>36</td>
|
|
||||||
<td>2008/10/16</td>
|
|
||||||
<td>$470,600</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>Haley Kennedy</td>
|
|
||||||
<td>Senior Marketing Designer</td>
|
|
||||||
<td>London</td>
|
|
||||||
<td>43</td>
|
|
||||||
<td>2012/12/18</td>
|
|
||||||
<td>$313,500</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>Tatyana Fitzpatrick</td>
|
|
||||||
<td>Regional Director</td>
|
|
||||||
<td>London</td>
|
|
||||||
<td>19</td>
|
|
||||||
<td>2010/03/17</td>
|
|
||||||
<td>$385,750</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>Michael Silva</td>
|
|
||||||
<td>Marketing Designer</td>
|
|
||||||
<td>London</td>
|
|
||||||
<td>66</td>
|
|
||||||
<td>2012/11/27</td>
|
|
||||||
<td>$198,500</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>Paul Byrd</td>
|
|
||||||
<td>Chief Financial Officer (CFO)</td>
|
|
||||||
<td>New York</td>
|
|
||||||
<td>64</td>
|
|
||||||
<td>2010/06/09</td>
|
|
||||||
<td>$725,000</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>Gloria Little</td>
|
|
||||||
<td>Systems Administrator</td>
|
|
||||||
<td>New York</td>
|
|
||||||
<td>59</td>
|
|
||||||
<td>2009/04/10</td>
|
|
||||||
<td>$237,500</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>Bradley Greer</td>
|
|
||||||
<td>Software Engineer</td>
|
|
||||||
<td>London</td>
|
|
||||||
<td>41</td>
|
|
||||||
<td>2012/10/13</td>
|
|
||||||
<td>$132,000</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>Dai Rios</td>
|
|
||||||
<td>Personnel Lead</td>
|
|
||||||
<td>Edinburgh</td>
|
|
||||||
<td>35</td>
|
|
||||||
<td>2012/09/26</td>
|
|
||||||
<td>$217,500</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>Jenette Caldwell</td>
|
|
||||||
<td>Development Lead</td>
|
|
||||||
<td>New York</td>
|
|
||||||
<td>30</td>
|
|
||||||
<td>2011/09/03</td>
|
|
||||||
<td>$345,000</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>Yuri Berry</td>
|
|
||||||
<td>Chief Marketing Officer (CMO)</td>
|
|
||||||
<td>New York</td>
|
|
||||||
<td>40</td>
|
|
||||||
<td>2009/06/25</td>
|
|
||||||
<td>$675,000</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>Caesar Vance</td>
|
|
||||||
<td>Pre-Sales Support</td>
|
|
||||||
<td>New York</td>
|
|
||||||
<td>21</td>
|
|
||||||
<td>2011/12/12</td>
|
|
||||||
<td>$106,450</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>Doris Wilder</td>
|
|
||||||
<td>Sales Assistant</td>
|
|
||||||
<td>Sidney</td>
|
|
||||||
<td>23</td>
|
|
||||||
<td>2010/09/20</td>
|
|
||||||
<td>$85,600</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>Angelica Ramos</td>
|
|
||||||
<td>Chief Executive Officer (CEO)</td>
|
|
||||||
<td>London</td>
|
|
||||||
<td>47</td>
|
|
||||||
<td>2009/10/09</td>
|
|
||||||
<td>$1,200,000</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>Gavin Joyce</td>
|
|
||||||
<td>Developer</td>
|
|
||||||
<td>Edinburgh</td>
|
|
||||||
<td>42</td>
|
|
||||||
<td>2010/12/22</td>
|
|
||||||
<td>$92,575</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>Jennifer Chang</td>
|
|
||||||
<td>Regional Director</td>
|
|
||||||
<td>Singapore</td>
|
|
||||||
<td>28</td>
|
|
||||||
<td>2010/11/14</td>
|
|
||||||
<td>$357,650</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>Brenden Wagner</td>
|
|
||||||
<td>Software Engineer</td>
|
|
||||||
<td>San Francisco</td>
|
|
||||||
<td>28</td>
|
|
||||||
<td>2011/06/07</td>
|
|
||||||
<td>$206,850</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>Fiona Green</td>
|
|
||||||
<td>Chief Operating Officer (COO)</td>
|
|
||||||
<td>San Francisco</td>
|
|
||||||
<td>48</td>
|
|
||||||
<td>2010/03/11</td>
|
|
||||||
<td>$850,000</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>Shou Itou</td>
|
|
||||||
<td>Regional Marketing</td>
|
|
||||||
<td>Tokyo</td>
|
|
||||||
<td>20</td>
|
|
||||||
<td>2011/08/14</td>
|
|
||||||
<td>$163,000</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>Michelle House</td>
|
|
||||||
<td>Integration Specialist</td>
|
|
||||||
<td>Sidney</td>
|
|
||||||
<td>37</td>
|
|
||||||
<td>2011/06/02</td>
|
|
||||||
<td>$95,400</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>Suki Burks</td>
|
|
||||||
<td>Developer</td>
|
|
||||||
<td>London</td>
|
|
||||||
<td>53</td>
|
|
||||||
<td>2009/10/22</td>
|
|
||||||
<td>$114,500</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>Prescott Bartlett</td>
|
|
||||||
<td>Technical Author</td>
|
|
||||||
<td>London</td>
|
|
||||||
<td>27</td>
|
|
||||||
<td>2011/05/07</td>
|
|
||||||
<td>$145,000</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>Gavin Cortez</td>
|
|
||||||
<td>Team Leader</td>
|
|
||||||
<td>San Francisco</td>
|
|
||||||
<td>22</td>
|
|
||||||
<td>2008/10/26</td>
|
|
||||||
<td>$235,500</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>Martena Mccray</td>
|
|
||||||
<td>Post-Sales support</td>
|
|
||||||
<td>Edinburgh</td>
|
|
||||||
<td>46</td>
|
|
||||||
<td>2011/03/09</td>
|
|
||||||
<td>$324,050</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>Unity Butler</td>
|
|
||||||
<td>Marketing Designer</td>
|
|
||||||
<td>San Francisco</td>
|
|
||||||
<td>47</td>
|
|
||||||
<td>2009/12/09</td>
|
|
||||||
<td>$85,675</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>Howard Hatfield</td>
|
|
||||||
<td>Office Manager</td>
|
|
||||||
<td>San Francisco</td>
|
|
||||||
<td>51</td>
|
|
||||||
<td>2008/12/16</td>
|
|
||||||
<td>$164,500</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>Hope Fuentes</td>
|
|
||||||
<td>Secretary</td>
|
|
||||||
<td>San Francisco</td>
|
|
||||||
<td>41</td>
|
|
||||||
<td>2010/02/12</td>
|
|
||||||
<td>$109,850</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>Vivian Harrell</td>
|
|
||||||
<td>Financial Controller</td>
|
|
||||||
<td>San Francisco</td>
|
|
||||||
<td>62</td>
|
|
||||||
<td>2009/02/14</td>
|
|
||||||
<td>$452,500</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>Timothy Mooney</td>
|
|
||||||
<td>Office Manager</td>
|
|
||||||
<td>London</td>
|
|
||||||
<td>37</td>
|
|
||||||
<td>2008/12/11</td>
|
|
||||||
<td>$136,200</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>Jackson Bradshaw</td>
|
|
||||||
<td>Director</td>
|
|
||||||
<td>New York</td>
|
|
||||||
<td>65</td>
|
|
||||||
<td>2008/09/26</td>
|
|
||||||
<td>$645,750</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>Olivia Liang</td>
|
|
||||||
<td>Support Engineer</td>
|
|
||||||
<td>Singapore</td>
|
|
||||||
<td>64</td>
|
|
||||||
<td>2011/02/03</td>
|
|
||||||
<td>$234,500</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>Bruno Nash</td>
|
|
||||||
<td>Software Engineer</td>
|
|
||||||
<td>London</td>
|
|
||||||
<td>38</td>
|
|
||||||
<td>2011/05/03</td>
|
|
||||||
<td>$163,500</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>Sakura Yamamoto</td>
|
|
||||||
<td>Support Engineer</td>
|
|
||||||
<td>Tokyo</td>
|
|
||||||
<td>37</td>
|
|
||||||
<td>2009/08/19</td>
|
|
||||||
<td>$139,575</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>Thor Walton</td>
|
|
||||||
<td>Developer</td>
|
|
||||||
<td>New York</td>
|
|
||||||
<td>61</td>
|
|
||||||
<td>2013/08/11</td>
|
|
||||||
<td>$98,540</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>Finn Camacho</td>
|
|
||||||
<td>Support Engineer</td>
|
|
||||||
<td>San Francisco</td>
|
|
||||||
<td>47</td>
|
|
||||||
<td>2009/07/07</td>
|
|
||||||
<td>$87,500</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>Serge Baldwin</td>
|
|
||||||
<td>Data Coordinator</td>
|
|
||||||
<td>Singapore</td>
|
|
||||||
<td>64</td>
|
|
||||||
<td>2012/04/09</td>
|
|
||||||
<td>$138,575</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>Zenaida Frank</td>
|
|
||||||
<td>Software Engineer</td>
|
|
||||||
<td>New York</td>
|
|
||||||
<td>63</td>
|
|
||||||
<td>2010/01/04</td>
|
|
||||||
<td>$125,250</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>Zorita Serrano</td>
|
|
||||||
<td>Software Engineer</td>
|
|
||||||
<td>San Francisco</td>
|
|
||||||
<td>56</td>
|
|
||||||
<td>2012/06/01</td>
|
|
||||||
<td>$115,000</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>Jennifer Acosta</td>
|
|
||||||
<td>Junior Javascript Developer</td>
|
|
||||||
<td>Edinburgh</td>
|
|
||||||
<td>43</td>
|
|
||||||
<td>2013/02/01</td>
|
|
||||||
<td>$75,650</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>Cara Stevens</td>
|
|
||||||
<td>Sales Assistant</td>
|
|
||||||
<td>New York</td>
|
|
||||||
<td>46</td>
|
|
||||||
<td>2011/12/06</td>
|
|
||||||
<td>$145,600</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>Hermione Butler</td>
|
|
||||||
<td>Regional Director</td>
|
|
||||||
<td>London</td>
|
|
||||||
<td>47</td>
|
|
||||||
<td>2011/03/21</td>
|
|
||||||
<td>$356,250</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>Lael Greer</td>
|
|
||||||
<td>Systems Administrator</td>
|
|
||||||
<td>London</td>
|
|
||||||
<td>21</td>
|
|
||||||
<td>2009/02/27</td>
|
|
||||||
<td>$103,500</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>Jonas Alexander</td>
|
|
||||||
<td>Developer</td>
|
|
||||||
<td>San Francisco</td>
|
|
||||||
<td>30</td>
|
|
||||||
<td>2010/07/14</td>
|
|
||||||
<td>$86,500</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>Shad Decker</td>
|
|
||||||
<td>Regional Director</td>
|
|
||||||
<td>Edinburgh</td>
|
|
||||||
<td>51</td>
|
|
||||||
<td>2008/11/13</td>
|
|
||||||
<td>$183,000</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>Michael Bruce</td>
|
|
||||||
<td>Javascript Developer</td>
|
|
||||||
<td>Singapore</td>
|
|
||||||
<td>29</td>
|
|
||||||
<td>2011/06/27</td>
|
|
||||||
<td>$183,000</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>Donna Snider</td>
|
|
||||||
<td>Customer Support</td>
|
|
||||||
<td>New York</td>
|
|
||||||
<td>27</td>
|
|
||||||
<td>2011/01/25</td>
|
|
||||||
<td>$112,000</td>
|
|
||||||
</tr>
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
<!-- /.container-fluid -->
|
|
||||||
|
|
||||||
</div>
|
|
||||||
<!-- End of Main Content -->
|
|
||||||
|
|
||||||
<!-- Footer -->
|
|
||||||
<footer class="sticky-footer bg-white">
|
|
||||||
<div class="container my-auto">
|
|
||||||
<div class="copyright text-center my-auto">
|
|
||||||
<span>Copyright © Your Website 2020</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</footer>
|
|
||||||
<!-- End of Footer -->
|
|
||||||
|
|
||||||
</div>
|
|
||||||
<!-- End of Content Wrapper -->
|
|
||||||
|
|
||||||
</div>
|
|
||||||
<!-- End of Page Wrapper -->
|
|
||||||
|
|
||||||
<!-- Scroll to Top Button-->
|
|
||||||
<a class="scroll-to-top rounded" href="#page-top">
|
|
||||||
<i class="fas fa-angle-up"></i>
|
|
||||||
</a>
|
|
||||||
|
|
||||||
<!-- Logout Modal-->
|
|
||||||
<div class="modal fade" id="logoutModal" tabindex="-1" role="dialog" aria-labelledby="exampleModalLabel"
|
|
||||||
aria-hidden="true">
|
|
||||||
<div class="modal-dialog" role="document">
|
|
||||||
<div class="modal-content">
|
|
||||||
<div class="modal-header">
|
|
||||||
<h5 class="modal-title" id="exampleModalLabel">Ready to Leave?</h5>
|
|
||||||
<button class="close" type="button" data-dismiss="modal" aria-label="Close">
|
|
||||||
<span aria-hidden="true">×</span>
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
<div class="modal-body">Select "Logout" below if you are ready to end your current session.</div>
|
|
||||||
<div class="modal-footer">
|
|
||||||
<button class="btn btn-secondary" type="button" data-dismiss="modal">Cancel</button>
|
|
||||||
<a class="btn btn-primary" href="login.html">Logout</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Bootstrap core JavaScript-->
|
|
||||||
<script src="vendor/jquery/jquery.min.js"></script>
|
|
||||||
<script src="vendor/bootstrap/js/bootstrap.bundle.min.js"></script>
|
|
||||||
|
|
||||||
<!-- Core plugin JavaScript-->
|
|
||||||
<script src="vendor/jquery-easing/jquery.easing.min.js"></script>
|
|
||||||
|
|
||||||
<!-- Custom scripts for all pages-->
|
|
||||||
<script src="js/sb-admin-2.min.js"></script>
|
|
||||||
|
|
||||||
<!-- Page level plugins -->
|
|
||||||
<script src="vendor/datatables/jquery.dataTables.min.js"></script>
|
|
||||||
<script src="vendor/datatables/dataTables.bootstrap4.min.js"></script>
|
|
||||||
|
|
||||||
<!-- Page level custom scripts -->
|
|
||||||
<script src="js/demo/datatables-demo.js"></script>
|
|
||||||
|
|
||||||
</body>
|
|
||||||
|
|
||||||
</html>
|
|
||||||
@@ -1,524 +0,0 @@
|
|||||||
<!DOCTYPE html>
|
|
||||||
<html lang="en">
|
|
||||||
|
|
||||||
<head>
|
|
||||||
|
|
||||||
<meta charset="utf-8">
|
|
||||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
|
||||||
<meta name="description" content="">
|
|
||||||
<meta name="author" content="">
|
|
||||||
|
|
||||||
<title>SB Admin 2 - Animation Utilities</title>
|
|
||||||
|
|
||||||
<!-- Custom fonts for this template-->
|
|
||||||
<link href="vendor/fontawesome-free/css/all.min.css" rel="stylesheet" type="text/css">
|
|
||||||
<link
|
|
||||||
href="https://fonts.googleapis.com/css?family=Nunito:200,200i,300,300i,400,400i,600,600i,700,700i,800,800i,900,900i"
|
|
||||||
rel="stylesheet">
|
|
||||||
|
|
||||||
<!-- Custom styles for this template-->
|
|
||||||
<link href="css/sb-admin-2.min.css" rel="stylesheet">
|
|
||||||
|
|
||||||
</head>
|
|
||||||
|
|
||||||
<body id="page-top">
|
|
||||||
|
|
||||||
<!-- Page Wrapper -->
|
|
||||||
<div id="wrapper">
|
|
||||||
|
|
||||||
<!-- Sidebar -->
|
|
||||||
<ul class="navbar-nav bg-gradient-primary sidebar sidebar-dark accordion" id="accordionSidebar">
|
|
||||||
|
|
||||||
<!-- Sidebar - Brand -->
|
|
||||||
<a class="sidebar-brand d-flex align-items-center justify-content-center" href="index.html">
|
|
||||||
<div class="sidebar-brand-icon rotate-n-15">
|
|
||||||
<i class="fas fa-laugh-wink"></i>
|
|
||||||
</div>
|
|
||||||
<div class="sidebar-brand-text mx-3">SB Admin <sup>2</sup></div>
|
|
||||||
</a>
|
|
||||||
|
|
||||||
<!-- Divider -->
|
|
||||||
<hr class="sidebar-divider my-0">
|
|
||||||
|
|
||||||
<!-- Nav Item - Dashboard -->
|
|
||||||
<li class="nav-item">
|
|
||||||
<a class="nav-link" href="index.html">
|
|
||||||
<i class="fas fa-fw fa-tachometer-alt"></i>
|
|
||||||
<span>Dashboard</span></a>
|
|
||||||
</li>
|
|
||||||
|
|
||||||
<!-- Divider -->
|
|
||||||
<hr class="sidebar-divider">
|
|
||||||
|
|
||||||
<!-- Heading -->
|
|
||||||
<div class="sidebar-heading">
|
|
||||||
Interface
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Nav Item - Pages Collapse Menu -->
|
|
||||||
<li class="nav-item">
|
|
||||||
<a class="nav-link collapsed" href="#" data-toggle="collapse" data-target="#collapseTwo"
|
|
||||||
aria-expanded="true" aria-controls="collapseTwo">
|
|
||||||
<i class="fas fa-fw fa-cog"></i>
|
|
||||||
<span>Components</span>
|
|
||||||
</a>
|
|
||||||
<div id="collapseTwo" class="collapse" aria-labelledby="headingTwo" data-parent="#accordionSidebar">
|
|
||||||
<div class="bg-white py-2 collapse-inner rounded">
|
|
||||||
<h6 class="collapse-header">Custom Components:</h6>
|
|
||||||
<a class="collapse-item" href="buttons.html">Buttons</a>
|
|
||||||
<a class="collapse-item" href="cards.html">Cards</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</li>
|
|
||||||
|
|
||||||
<!-- Nav Item - Utilities Collapse Menu -->
|
|
||||||
<li class="nav-item active">
|
|
||||||
<a class="nav-link" href="#" data-toggle="collapse" data-target="#collapseUtilities"
|
|
||||||
aria-expanded="true" aria-controls="collapseUtilities">
|
|
||||||
<i class="fas fa-fw fa-wrench"></i>
|
|
||||||
<span>Utilities</span>
|
|
||||||
</a>
|
|
||||||
<div id="collapseUtilities" class="collapse show" aria-labelledby="headingUtilities"
|
|
||||||
data-parent="#accordionSidebar">
|
|
||||||
<div class="bg-white py-2 collapse-inner rounded">
|
|
||||||
<h6 class="collapse-header">Custom Utilities:</h6>
|
|
||||||
<a class="collapse-item" href="utilities-color.html">Colors</a>
|
|
||||||
<a class="collapse-item" href="utilities-border.html">Borders</a>
|
|
||||||
<a class="collapse-item active" href="utilities-animation.html">Animations</a>
|
|
||||||
<a class="collapse-item" href="utilities-other.html">Other</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</li>
|
|
||||||
|
|
||||||
<!-- Divider -->
|
|
||||||
<hr class="sidebar-divider">
|
|
||||||
|
|
||||||
<!-- Heading -->
|
|
||||||
<div class="sidebar-heading">
|
|
||||||
Addons
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Nav Item - Pages Collapse Menu -->
|
|
||||||
<li class="nav-item">
|
|
||||||
<a class="nav-link collapsed" href="#" data-toggle="collapse" data-target="#collapsePages"
|
|
||||||
aria-expanded="true" aria-controls="collapsePages">
|
|
||||||
<i class="fas fa-fw fa-folder"></i>
|
|
||||||
<span>Pages</span>
|
|
||||||
</a>
|
|
||||||
<div id="collapsePages" class="collapse" aria-labelledby="headingPages" data-parent="#accordionSidebar">
|
|
||||||
<div class="bg-white py-2 collapse-inner rounded">
|
|
||||||
<h6 class="collapse-header">Login Screens:</h6>
|
|
||||||
<a class="collapse-item" href="login.html">Login</a>
|
|
||||||
<a class="collapse-item" href="register.html">Register</a>
|
|
||||||
<a class="collapse-item" href="forgot-password.html">Forgot Password</a>
|
|
||||||
<div class="collapse-divider"></div>
|
|
||||||
<h6 class="collapse-header">Other Pages:</h6>
|
|
||||||
<a class="collapse-item" href="404.html">404 Page</a>
|
|
||||||
<a class="collapse-item" href="blank.html">Blank Page</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</li>
|
|
||||||
|
|
||||||
<!-- Nav Item - Charts -->
|
|
||||||
<li class="nav-item">
|
|
||||||
<a class="nav-link" href="charts.html">
|
|
||||||
<i class="fas fa-fw fa-chart-area"></i>
|
|
||||||
<span>Charts</span></a>
|
|
||||||
</li>
|
|
||||||
|
|
||||||
<!-- Nav Item - Tables -->
|
|
||||||
<li class="nav-item">
|
|
||||||
<a class="nav-link" href="tables.html">
|
|
||||||
<i class="fas fa-fw fa-table"></i>
|
|
||||||
<span>Tables</span></a>
|
|
||||||
</li>
|
|
||||||
|
|
||||||
<!-- Divider -->
|
|
||||||
<hr class="sidebar-divider d-none d-md-block">
|
|
||||||
|
|
||||||
<!-- Sidebar Toggler (Sidebar) -->
|
|
||||||
<div class="text-center d-none d-md-inline">
|
|
||||||
<button class="rounded-circle border-0" id="sidebarToggle"></button>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</ul>
|
|
||||||
<!-- End of Sidebar -->
|
|
||||||
|
|
||||||
<!-- Content Wrapper -->
|
|
||||||
<div id="content-wrapper" class="d-flex flex-column">
|
|
||||||
|
|
||||||
<!-- Main Content -->
|
|
||||||
<div id="content">
|
|
||||||
|
|
||||||
<!-- Topbar -->
|
|
||||||
<nav class="navbar navbar-expand navbar-light bg-white topbar mb-4 static-top shadow">
|
|
||||||
|
|
||||||
<!-- Sidebar Toggle (Topbar) -->
|
|
||||||
<button id="sidebarToggleTop" class="btn btn-link d-md-none rounded-circle mr-3">
|
|
||||||
<i class="fa fa-bars"></i>
|
|
||||||
</button>
|
|
||||||
|
|
||||||
<!-- Topbar Search -->
|
|
||||||
<form
|
|
||||||
class="d-none d-sm-inline-block form-inline mr-auto ml-md-3 my-2 my-md-0 mw-100 navbar-search">
|
|
||||||
<div class="input-group">
|
|
||||||
<input type="text" class="form-control bg-light border-0 small" placeholder="Search for..."
|
|
||||||
aria-label="Search" aria-describedby="basic-addon2">
|
|
||||||
<div class="input-group-append">
|
|
||||||
<button class="btn btn-primary" type="button">
|
|
||||||
<i class="fas fa-search fa-sm"></i>
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
|
|
||||||
<!-- Topbar Navbar -->
|
|
||||||
<ul class="navbar-nav ml-auto">
|
|
||||||
|
|
||||||
<!-- Nav Item - Search Dropdown (Visible Only XS) -->
|
|
||||||
<li class="nav-item dropdown no-arrow d-sm-none">
|
|
||||||
<a class="nav-link dropdown-toggle" href="#" id="searchDropdown" role="button"
|
|
||||||
data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
|
|
||||||
<i class="fas fa-search fa-fw"></i>
|
|
||||||
</a>
|
|
||||||
<!-- Dropdown - Messages -->
|
|
||||||
<div class="dropdown-menu dropdown-menu-right p-3 shadow animated--grow-in"
|
|
||||||
aria-labelledby="searchDropdown">
|
|
||||||
<form class="form-inline mr-auto w-100 navbar-search">
|
|
||||||
<div class="input-group">
|
|
||||||
<input type="text" class="form-control bg-light border-0 small"
|
|
||||||
placeholder="Search for..." aria-label="Search"
|
|
||||||
aria-describedby="basic-addon2">
|
|
||||||
<div class="input-group-append">
|
|
||||||
<button class="btn btn-primary" type="button">
|
|
||||||
<i class="fas fa-search fa-sm"></i>
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
</li>
|
|
||||||
|
|
||||||
<!-- Nav Item - Alerts -->
|
|
||||||
<li class="nav-item dropdown no-arrow mx-1">
|
|
||||||
<a class="nav-link dropdown-toggle" href="#" id="alertsDropdown" role="button"
|
|
||||||
data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
|
|
||||||
<i class="fas fa-bell fa-fw"></i>
|
|
||||||
<!-- Counter - Alerts -->
|
|
||||||
<span class="badge badge-danger badge-counter">3+</span>
|
|
||||||
</a>
|
|
||||||
<!-- Dropdown - Alerts -->
|
|
||||||
<div class="dropdown-list dropdown-menu dropdown-menu-right shadow animated--grow-in"
|
|
||||||
aria-labelledby="alertsDropdown">
|
|
||||||
<h6 class="dropdown-header">
|
|
||||||
Alerts Center
|
|
||||||
</h6>
|
|
||||||
<a class="dropdown-item d-flex align-items-center" href="#">
|
|
||||||
<div class="mr-3">
|
|
||||||
<div class="icon-circle bg-primary">
|
|
||||||
<i class="fas fa-file-alt text-white"></i>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<div class="small text-gray-500">December 12, 2019</div>
|
|
||||||
<span class="font-weight-bold">A new monthly report is ready to download!</span>
|
|
||||||
</div>
|
|
||||||
</a>
|
|
||||||
<a class="dropdown-item d-flex align-items-center" href="#">
|
|
||||||
<div class="mr-3">
|
|
||||||
<div class="icon-circle bg-success">
|
|
||||||
<i class="fas fa-donate text-white"></i>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<div class="small text-gray-500">December 7, 2019</div>
|
|
||||||
$290.29 has been deposited into your account!
|
|
||||||
</div>
|
|
||||||
</a>
|
|
||||||
<a class="dropdown-item d-flex align-items-center" href="#">
|
|
||||||
<div class="mr-3">
|
|
||||||
<div class="icon-circle bg-warning">
|
|
||||||
<i class="fas fa-exclamation-triangle text-white"></i>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<div class="small text-gray-500">December 2, 2019</div>
|
|
||||||
Spending Alert: We've noticed unusually high spending for your account.
|
|
||||||
</div>
|
|
||||||
</a>
|
|
||||||
<a class="dropdown-item text-center small text-gray-500" href="#">Show All Alerts</a>
|
|
||||||
</div>
|
|
||||||
</li>
|
|
||||||
|
|
||||||
<!-- Nav Item - Messages -->
|
|
||||||
<li class="nav-item dropdown no-arrow mx-1">
|
|
||||||
<a class="nav-link dropdown-toggle" href="#" id="messagesDropdown" role="button"
|
|
||||||
data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
|
|
||||||
<i class="fas fa-envelope fa-fw"></i>
|
|
||||||
<!-- Counter - Messages -->
|
|
||||||
<span class="badge badge-danger badge-counter">7</span>
|
|
||||||
</a>
|
|
||||||
<!-- Dropdown - Messages -->
|
|
||||||
<div class="dropdown-list dropdown-menu dropdown-menu-right shadow animated--grow-in"
|
|
||||||
aria-labelledby="messagesDropdown">
|
|
||||||
<h6 class="dropdown-header">
|
|
||||||
Message Center
|
|
||||||
</h6>
|
|
||||||
<a class="dropdown-item d-flex align-items-center" href="#">
|
|
||||||
<div class="dropdown-list-image mr-3">
|
|
||||||
<img class="rounded-circle" src="img/undraw_profile_1.svg"
|
|
||||||
alt="...">
|
|
||||||
<div class="status-indicator bg-success"></div>
|
|
||||||
</div>
|
|
||||||
<div class="font-weight-bold">
|
|
||||||
<div class="text-truncate">Hi there! I am wondering if you can help me with a
|
|
||||||
problem I've been having.</div>
|
|
||||||
<div class="small text-gray-500">Emily Fowler · 58m</div>
|
|
||||||
</div>
|
|
||||||
</a>
|
|
||||||
<a class="dropdown-item d-flex align-items-center" href="#">
|
|
||||||
<div class="dropdown-list-image mr-3">
|
|
||||||
<img class="rounded-circle" src="img/undraw_profile_2.svg"
|
|
||||||
alt="...">
|
|
||||||
<div class="status-indicator"></div>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<div class="text-truncate">I have the photos that you ordered last month, how
|
|
||||||
would you like them sent to you?</div>
|
|
||||||
<div class="small text-gray-500">Jae Chun · 1d</div>
|
|
||||||
</div>
|
|
||||||
</a>
|
|
||||||
<a class="dropdown-item d-flex align-items-center" href="#">
|
|
||||||
<div class="dropdown-list-image mr-3">
|
|
||||||
<img class="rounded-circle" src="img/undraw_profile_3.svg"
|
|
||||||
alt="...">
|
|
||||||
<div class="status-indicator bg-warning"></div>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<div class="text-truncate">Last month's report looks great, I am very happy with
|
|
||||||
the progress so far, keep up the good work!</div>
|
|
||||||
<div class="small text-gray-500">Morgan Alvarez · 2d</div>
|
|
||||||
</div>
|
|
||||||
</a>
|
|
||||||
<a class="dropdown-item d-flex align-items-center" href="#">
|
|
||||||
<div class="dropdown-list-image mr-3">
|
|
||||||
<img class="rounded-circle" src="https://source.unsplash.com/Mv9hjnEUHR4/60x60"
|
|
||||||
alt="...">
|
|
||||||
<div class="status-indicator bg-success"></div>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<div class="text-truncate">Am I a good boy? The reason I ask is because someone
|
|
||||||
told me that people say this to all dogs, even if they aren't good...</div>
|
|
||||||
<div class="small text-gray-500">Chicken the Dog · 2w</div>
|
|
||||||
</div>
|
|
||||||
</a>
|
|
||||||
<a class="dropdown-item text-center small text-gray-500" href="#">Read More Messages</a>
|
|
||||||
</div>
|
|
||||||
</li>
|
|
||||||
|
|
||||||
<div class="topbar-divider d-none d-sm-block"></div>
|
|
||||||
|
|
||||||
<!-- Nav Item - User Information -->
|
|
||||||
<li class="nav-item dropdown no-arrow">
|
|
||||||
<a class="nav-link dropdown-toggle" href="#" id="userDropdown" role="button"
|
|
||||||
data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
|
|
||||||
<span class="mr-2 d-none d-lg-inline text-gray-600 small">Douglas McGee</span>
|
|
||||||
<img class="img-profile rounded-circle"
|
|
||||||
src="img/undraw_profile.svg">
|
|
||||||
</a>
|
|
||||||
<!-- Dropdown - User Information -->
|
|
||||||
<div class="dropdown-menu dropdown-menu-right shadow animated--grow-in"
|
|
||||||
aria-labelledby="userDropdown">
|
|
||||||
<a class="dropdown-item" href="#">
|
|
||||||
<i class="fas fa-user fa-sm fa-fw mr-2 text-gray-400"></i>
|
|
||||||
Profile
|
|
||||||
</a>
|
|
||||||
<a class="dropdown-item" href="#">
|
|
||||||
<i class="fas fa-cogs fa-sm fa-fw mr-2 text-gray-400"></i>
|
|
||||||
Settings
|
|
||||||
</a>
|
|
||||||
<a class="dropdown-item" href="#">
|
|
||||||
<i class="fas fa-list fa-sm fa-fw mr-2 text-gray-400"></i>
|
|
||||||
Activity Log
|
|
||||||
</a>
|
|
||||||
<div class="dropdown-divider"></div>
|
|
||||||
<a class="dropdown-item" href="#" data-toggle="modal" data-target="#logoutModal">
|
|
||||||
<i class="fas fa-sign-out-alt fa-sm fa-fw mr-2 text-gray-400"></i>
|
|
||||||
Logout
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
</li>
|
|
||||||
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
</nav>
|
|
||||||
<!-- End of Topbar -->
|
|
||||||
|
|
||||||
<!-- Begin Page Content -->
|
|
||||||
<div class="container-fluid">
|
|
||||||
|
|
||||||
<!-- Page Heading -->
|
|
||||||
<h1 class="h3 mb-1 text-gray-800">Animation Utilities</h1>
|
|
||||||
<p class="mb-4">Bootstrap's default utility classes can be found on the official <a
|
|
||||||
href="https://getbootstrap.com/docs">Bootstrap Documentation</a> page. The custom utilities
|
|
||||||
below were created to extend this theme past the default utility classes built into Bootstrap's
|
|
||||||
framework.</p>
|
|
||||||
|
|
||||||
<!-- Content Row -->
|
|
||||||
<div class="row">
|
|
||||||
|
|
||||||
<!-- Grow In Utility -->
|
|
||||||
<div class="col-lg-6">
|
|
||||||
|
|
||||||
<div class="card position-relative">
|
|
||||||
<div class="card-header py-3">
|
|
||||||
<h6 class="m-0 font-weight-bold text-primary">Grow In Animation Utilty</h6>
|
|
||||||
</div>
|
|
||||||
<div class="card-body">
|
|
||||||
<div class="mb-3">
|
|
||||||
<code>.animated--grow-in</code>
|
|
||||||
</div>
|
|
||||||
<div class="small mb-1">Navbar Dropdown Example:</div>
|
|
||||||
<nav class="navbar navbar-expand navbar-light bg-light mb-4">
|
|
||||||
<a class="navbar-brand" href="#">Navbar</a>
|
|
||||||
<ul class="navbar-nav ml-auto">
|
|
||||||
<li class="nav-item dropdown">
|
|
||||||
<a class="nav-link dropdown-toggle" href="#" id="navbarDropdown"
|
|
||||||
role="button" data-toggle="dropdown" aria-haspopup="true"
|
|
||||||
aria-expanded="false">
|
|
||||||
Dropdown
|
|
||||||
</a>
|
|
||||||
<div class="dropdown-menu dropdown-menu-right animated--grow-in"
|
|
||||||
aria-labelledby="navbarDropdown">
|
|
||||||
<a class="dropdown-item" href="#">Action</a>
|
|
||||||
<a class="dropdown-item" href="#">Another action</a>
|
|
||||||
<div class="dropdown-divider"></div>
|
|
||||||
<a class="dropdown-item" href="#">Something else here</a>
|
|
||||||
</div>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</nav>
|
|
||||||
<p class="mb-0 small">Note: This utility animates the CSS transform property,
|
|
||||||
meaning it will override any existing transforms on an element being animated!
|
|
||||||
In this theme, the grow in animation is only being used on dropdowns within the
|
|
||||||
navbar.</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Fade In Utility -->
|
|
||||||
<div class="col-lg-6">
|
|
||||||
|
|
||||||
<div class="card position-relative">
|
|
||||||
<div class="card-header py-3">
|
|
||||||
<h6 class="m-0 font-weight-bold text-primary">Fade In Animation Utilty</h6>
|
|
||||||
</div>
|
|
||||||
<div class="card-body">
|
|
||||||
<div class="mb-3">
|
|
||||||
<code>.animated--fade-in</code>
|
|
||||||
</div>
|
|
||||||
<div class="small mb-1">Navbar Dropdown Example:</div>
|
|
||||||
<nav class="navbar navbar-expand navbar-light bg-light mb-4">
|
|
||||||
<a class="navbar-brand" href="#">Navbar</a>
|
|
||||||
<ul class="navbar-nav ml-auto">
|
|
||||||
<li class="nav-item dropdown">
|
|
||||||
<a class="nav-link dropdown-toggle" href="#" id="navbarDropdown"
|
|
||||||
role="button" data-toggle="dropdown" aria-haspopup="true"
|
|
||||||
aria-expanded="false">
|
|
||||||
Dropdown
|
|
||||||
</a>
|
|
||||||
<div class="dropdown-menu dropdown-menu-right animated--fade-in"
|
|
||||||
aria-labelledby="navbarDropdown">
|
|
||||||
<a class="dropdown-item" href="#">Action</a>
|
|
||||||
<a class="dropdown-item" href="#">Another action</a>
|
|
||||||
<div class="dropdown-divider"></div>
|
|
||||||
<a class="dropdown-item" href="#">Something else here</a>
|
|
||||||
</div>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</nav>
|
|
||||||
<div class="small mb-1">Dropdown Button Example:</div>
|
|
||||||
<div class="dropdown mb-4">
|
|
||||||
<button class="btn btn-primary dropdown-toggle" type="button"
|
|
||||||
id="dropdownMenuButton" data-toggle="dropdown" aria-haspopup="true"
|
|
||||||
aria-expanded="false">
|
|
||||||
Dropdown
|
|
||||||
</button>
|
|
||||||
<div class="dropdown-menu animated--fade-in"
|
|
||||||
aria-labelledby="dropdownMenuButton">
|
|
||||||
<a class="dropdown-item" href="#">Action</a>
|
|
||||||
<a class="dropdown-item" href="#">Another action</a>
|
|
||||||
<a class="dropdown-item" href="#">Something else here</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<p class="mb-0 small">Note: This utility animates the CSS opacity property, meaning
|
|
||||||
it will override any existing opacity on an element being animated!</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
<!-- /.container-fluid -->
|
|
||||||
|
|
||||||
</div>
|
|
||||||
<!-- End of Main Content -->
|
|
||||||
|
|
||||||
<!-- Footer -->
|
|
||||||
<footer class="sticky-footer bg-white">
|
|
||||||
<div class="container my-auto">
|
|
||||||
<div class="copyright text-center my-auto">
|
|
||||||
<span>Copyright © Your Website 2020</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</footer>
|
|
||||||
<!-- End of Footer -->
|
|
||||||
|
|
||||||
</div>
|
|
||||||
<!-- End of Content Wrapper -->
|
|
||||||
|
|
||||||
</div>
|
|
||||||
<!-- End of Page Wrapper -->
|
|
||||||
|
|
||||||
<!-- Scroll to Top Button-->
|
|
||||||
<a class="scroll-to-top rounded" href="#page-top">
|
|
||||||
<i class="fas fa-angle-up"></i>
|
|
||||||
</a>
|
|
||||||
|
|
||||||
<!-- Logout Modal-->
|
|
||||||
<div class="modal fade" id="logoutModal" tabindex="-1" role="dialog" aria-labelledby="exampleModalLabel"
|
|
||||||
aria-hidden="true">
|
|
||||||
<div class="modal-dialog" role="document">
|
|
||||||
<div class="modal-content">
|
|
||||||
<div class="modal-header">
|
|
||||||
<h5 class="modal-title" id="exampleModalLabel">Ready to Leave?</h5>
|
|
||||||
<button class="close" type="button" data-dismiss="modal" aria-label="Close">
|
|
||||||
<span aria-hidden="true">×</span>
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
<div class="modal-body">Select "Logout" below if you are ready to end your current session.</div>
|
|
||||||
<div class="modal-footer">
|
|
||||||
<button class="btn btn-secondary" type="button" data-dismiss="modal">Cancel</button>
|
|
||||||
<a class="btn btn-primary" href="login.html">Logout</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Bootstrap core JavaScript-->
|
|
||||||
<script src="vendor/jquery/jquery.min.js"></script>
|
|
||||||
<script src="vendor/bootstrap/js/bootstrap.bundle.min.js"></script>
|
|
||||||
|
|
||||||
<!-- Core plugin JavaScript-->
|
|
||||||
<script src="vendor/jquery-easing/jquery.easing.min.js"></script>
|
|
||||||
|
|
||||||
<!-- Custom scripts for all pages-->
|
|
||||||
<script src="js/sb-admin-2.min.js"></script>
|
|
||||||
|
|
||||||
</body>
|
|
||||||
|
|
||||||
</html>
|
|
||||||
@@ -1,526 +0,0 @@
|
|||||||
<!DOCTYPE html>
|
|
||||||
<html lang="en">
|
|
||||||
|
|
||||||
<head>
|
|
||||||
|
|
||||||
<meta charset="utf-8">
|
|
||||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
|
||||||
<meta name="description" content="">
|
|
||||||
<meta name="author" content="">
|
|
||||||
|
|
||||||
<title>SB Admin 2 - Border Utilities</title>
|
|
||||||
|
|
||||||
<!-- Custom fonts for this template-->
|
|
||||||
<link href="vendor/fontawesome-free/css/all.min.css" rel="stylesheet" type="text/css">
|
|
||||||
<link
|
|
||||||
href="https://fonts.googleapis.com/css?family=Nunito:200,200i,300,300i,400,400i,600,600i,700,700i,800,800i,900,900i"
|
|
||||||
rel="stylesheet">
|
|
||||||
|
|
||||||
<!-- Custom styles for this template-->
|
|
||||||
<link href="css/sb-admin-2.min.css" rel="stylesheet">
|
|
||||||
|
|
||||||
</head>
|
|
||||||
|
|
||||||
<body id="page-top">
|
|
||||||
|
|
||||||
<!-- Page Wrapper -->
|
|
||||||
<div id="wrapper">
|
|
||||||
|
|
||||||
<!-- Sidebar -->
|
|
||||||
<ul class="navbar-nav bg-gradient-primary sidebar sidebar-dark accordion" id="accordionSidebar">
|
|
||||||
|
|
||||||
<!-- Sidebar - Brand -->
|
|
||||||
<a class="sidebar-brand d-flex align-items-center justify-content-center" href="index.html">
|
|
||||||
<div class="sidebar-brand-icon rotate-n-15">
|
|
||||||
<i class="fas fa-laugh-wink"></i>
|
|
||||||
</div>
|
|
||||||
<div class="sidebar-brand-text mx-3">SB Admin <sup>2</sup></div>
|
|
||||||
</a>
|
|
||||||
|
|
||||||
<!-- Divider -->
|
|
||||||
<hr class="sidebar-divider my-0">
|
|
||||||
|
|
||||||
<!-- Nav Item - Dashboard -->
|
|
||||||
<li class="nav-item">
|
|
||||||
<a class="nav-link" href="index.html">
|
|
||||||
<i class="fas fa-fw fa-tachometer-alt"></i>
|
|
||||||
<span>Dashboard</span></a>
|
|
||||||
</li>
|
|
||||||
|
|
||||||
<!-- Divider -->
|
|
||||||
<hr class="sidebar-divider">
|
|
||||||
|
|
||||||
<!-- Heading -->
|
|
||||||
<div class="sidebar-heading">
|
|
||||||
Interface
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Nav Item - Pages Collapse Menu -->
|
|
||||||
<li class="nav-item">
|
|
||||||
<a class="nav-link collapsed" href="#" data-toggle="collapse" data-target="#collapseTwo"
|
|
||||||
aria-expanded="true" aria-controls="collapseTwo">
|
|
||||||
<i class="fas fa-fw fa-cog"></i>
|
|
||||||
<span>Components</span>
|
|
||||||
</a>
|
|
||||||
<div id="collapseTwo" class="collapse" aria-labelledby="headingTwo" data-parent="#accordionSidebar">
|
|
||||||
<div class="bg-white py-2 collapse-inner rounded">
|
|
||||||
<h6 class="collapse-header">Custom Components:</h6>
|
|
||||||
<a class="collapse-item" href="buttons.html">Buttons</a>
|
|
||||||
<a class="collapse-item" href="cards.html">Cards</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</li>
|
|
||||||
|
|
||||||
<!-- Nav Item - Utilities Collapse Menu -->
|
|
||||||
<li class="nav-item active">
|
|
||||||
<a class="nav-link" href="#" data-toggle="collapse" data-target="#collapseUtilities"
|
|
||||||
aria-expanded="true" aria-controls="collapseUtilities">
|
|
||||||
<i class="fas fa-fw fa-wrench"></i>
|
|
||||||
<span>Utilities</span>
|
|
||||||
</a>
|
|
||||||
<div id="collapseUtilities" class="collapse show" aria-labelledby="headingUtilities"
|
|
||||||
data-parent="#accordionSidebar">
|
|
||||||
<div class="bg-white py-2 collapse-inner rounded">
|
|
||||||
<h6 class="collapse-header">Custom Utilities:</h6>
|
|
||||||
<a class="collapse-item" href="utilities-color.html">Colors</a>
|
|
||||||
<a class="collapse-item active" href="utilities-border.html">Borders</a>
|
|
||||||
<a class="collapse-item" href="utilities-animation.html">Animations</a>
|
|
||||||
<a class="collapse-item" href="utilities-other.html">Other</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</li>
|
|
||||||
|
|
||||||
<!-- Divider -->
|
|
||||||
<hr class="sidebar-divider">
|
|
||||||
|
|
||||||
<!-- Heading -->
|
|
||||||
<div class="sidebar-heading">
|
|
||||||
Addons
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Nav Item - Pages Collapse Menu -->
|
|
||||||
<li class="nav-item">
|
|
||||||
<a class="nav-link collapsed" href="#" data-toggle="collapse" data-target="#collapsePages"
|
|
||||||
aria-expanded="true" aria-controls="collapsePages">
|
|
||||||
<i class="fas fa-fw fa-folder"></i>
|
|
||||||
<span>Pages</span>
|
|
||||||
</a>
|
|
||||||
<div id="collapsePages" class="collapse" aria-labelledby="headingPages" data-parent="#accordionSidebar">
|
|
||||||
<div class="bg-white py-2 collapse-inner rounded">
|
|
||||||
<h6 class="collapse-header">Login Screens:</h6>
|
|
||||||
<a class="collapse-item" href="login.html">Login</a>
|
|
||||||
<a class="collapse-item" href="register.html">Register</a>
|
|
||||||
<a class="collapse-item" href="forgot-password.html">Forgot Password</a>
|
|
||||||
<div class="collapse-divider"></div>
|
|
||||||
<h6 class="collapse-header">Other Pages:</h6>
|
|
||||||
<a class="collapse-item" href="404.html">404 Page</a>
|
|
||||||
<a class="collapse-item" href="blank.html">Blank Page</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</li>
|
|
||||||
|
|
||||||
<!-- Nav Item - Charts -->
|
|
||||||
<li class="nav-item">
|
|
||||||
<a class="nav-link" href="charts.html">
|
|
||||||
<i class="fas fa-fw fa-chart-area"></i>
|
|
||||||
<span>Charts</span></a>
|
|
||||||
</li>
|
|
||||||
|
|
||||||
<!-- Nav Item - Tables -->
|
|
||||||
<li class="nav-item">
|
|
||||||
<a class="nav-link" href="tables.html">
|
|
||||||
<i class="fas fa-fw fa-table"></i>
|
|
||||||
<span>Tables</span></a>
|
|
||||||
</li>
|
|
||||||
|
|
||||||
<!-- Divider -->
|
|
||||||
<hr class="sidebar-divider d-none d-md-block">
|
|
||||||
|
|
||||||
<!-- Sidebar Toggler (Sidebar) -->
|
|
||||||
<div class="text-center d-none d-md-inline">
|
|
||||||
<button class="rounded-circle border-0" id="sidebarToggle"></button>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</ul>
|
|
||||||
<!-- End of Sidebar -->
|
|
||||||
|
|
||||||
<!-- Content Wrapper -->
|
|
||||||
<div id="content-wrapper" class="d-flex flex-column">
|
|
||||||
|
|
||||||
<!-- Main Content -->
|
|
||||||
<div id="content">
|
|
||||||
|
|
||||||
<!-- Topbar -->
|
|
||||||
<nav class="navbar navbar-expand navbar-light bg-white topbar mb-4 static-top shadow">
|
|
||||||
|
|
||||||
<!-- Sidebar Toggle (Topbar) -->
|
|
||||||
<button id="sidebarToggleTop" class="btn btn-link d-md-none rounded-circle mr-3">
|
|
||||||
<i class="fa fa-bars"></i>
|
|
||||||
</button>
|
|
||||||
|
|
||||||
<!-- Topbar Search -->
|
|
||||||
<form
|
|
||||||
class="d-none d-sm-inline-block form-inline mr-auto ml-md-3 my-2 my-md-0 mw-100 navbar-search">
|
|
||||||
<div class="input-group">
|
|
||||||
<input type="text" class="form-control bg-light border-0 small" placeholder="Search for..."
|
|
||||||
aria-label="Search" aria-describedby="basic-addon2">
|
|
||||||
<div class="input-group-append">
|
|
||||||
<button class="btn btn-primary" type="button">
|
|
||||||
<i class="fas fa-search fa-sm"></i>
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
|
|
||||||
<!-- Topbar Navbar -->
|
|
||||||
<ul class="navbar-nav ml-auto">
|
|
||||||
|
|
||||||
<!-- Nav Item - Search Dropdown (Visible Only XS) -->
|
|
||||||
<li class="nav-item dropdown no-arrow d-sm-none">
|
|
||||||
<a class="nav-link dropdown-toggle" href="#" id="searchDropdown" role="button"
|
|
||||||
data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
|
|
||||||
<i class="fas fa-search fa-fw"></i>
|
|
||||||
</a>
|
|
||||||
<!-- Dropdown - Messages -->
|
|
||||||
<div class="dropdown-menu dropdown-menu-right p-3 shadow animated--grow-in"
|
|
||||||
aria-labelledby="searchDropdown">
|
|
||||||
<form class="form-inline mr-auto w-100 navbar-search">
|
|
||||||
<div class="input-group">
|
|
||||||
<input type="text" class="form-control bg-light border-0 small"
|
|
||||||
placeholder="Search for..." aria-label="Search"
|
|
||||||
aria-describedby="basic-addon2">
|
|
||||||
<div class="input-group-append">
|
|
||||||
<button class="btn btn-primary" type="button">
|
|
||||||
<i class="fas fa-search fa-sm"></i>
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
</li>
|
|
||||||
|
|
||||||
<!-- Nav Item - Alerts -->
|
|
||||||
<li class="nav-item dropdown no-arrow mx-1">
|
|
||||||
<a class="nav-link dropdown-toggle" href="#" id="alertsDropdown" role="button"
|
|
||||||
data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
|
|
||||||
<i class="fas fa-bell fa-fw"></i>
|
|
||||||
<!-- Counter - Alerts -->
|
|
||||||
<span class="badge badge-danger badge-counter">3+</span>
|
|
||||||
</a>
|
|
||||||
<!-- Dropdown - Alerts -->
|
|
||||||
<div class="dropdown-list dropdown-menu dropdown-menu-right shadow animated--grow-in"
|
|
||||||
aria-labelledby="alertsDropdown">
|
|
||||||
<h6 class="dropdown-header">
|
|
||||||
Alerts Center
|
|
||||||
</h6>
|
|
||||||
<a class="dropdown-item d-flex align-items-center" href="#">
|
|
||||||
<div class="mr-3">
|
|
||||||
<div class="icon-circle bg-primary">
|
|
||||||
<i class="fas fa-file-alt text-white"></i>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<div class="small text-gray-500">December 12, 2019</div>
|
|
||||||
<span class="font-weight-bold">A new monthly report is ready to download!</span>
|
|
||||||
</div>
|
|
||||||
</a>
|
|
||||||
<a class="dropdown-item d-flex align-items-center" href="#">
|
|
||||||
<div class="mr-3">
|
|
||||||
<div class="icon-circle bg-success">
|
|
||||||
<i class="fas fa-donate text-white"></i>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<div class="small text-gray-500">December 7, 2019</div>
|
|
||||||
$290.29 has been deposited into your account!
|
|
||||||
</div>
|
|
||||||
</a>
|
|
||||||
<a class="dropdown-item d-flex align-items-center" href="#">
|
|
||||||
<div class="mr-3">
|
|
||||||
<div class="icon-circle bg-warning">
|
|
||||||
<i class="fas fa-exclamation-triangle text-white"></i>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<div class="small text-gray-500">December 2, 2019</div>
|
|
||||||
Spending Alert: We've noticed unusually high spending for your account.
|
|
||||||
</div>
|
|
||||||
</a>
|
|
||||||
<a class="dropdown-item text-center small text-gray-500" href="#">Show All Alerts</a>
|
|
||||||
</div>
|
|
||||||
</li>
|
|
||||||
|
|
||||||
<!-- Nav Item - Messages -->
|
|
||||||
<li class="nav-item dropdown no-arrow mx-1">
|
|
||||||
<a class="nav-link dropdown-toggle" href="#" id="messagesDropdown" role="button"
|
|
||||||
data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
|
|
||||||
<i class="fas fa-envelope fa-fw"></i>
|
|
||||||
<!-- Counter - Messages -->
|
|
||||||
<span class="badge badge-danger badge-counter">7</span>
|
|
||||||
</a>
|
|
||||||
<!-- Dropdown - Messages -->
|
|
||||||
<div class="dropdown-list dropdown-menu dropdown-menu-right shadow animated--grow-in"
|
|
||||||
aria-labelledby="messagesDropdown">
|
|
||||||
<h6 class="dropdown-header">
|
|
||||||
Message Center
|
|
||||||
</h6>
|
|
||||||
<a class="dropdown-item d-flex align-items-center" href="#">
|
|
||||||
<div class="dropdown-list-image mr-3">
|
|
||||||
<img class="rounded-circle" src="img/undraw_profile_1.svg"
|
|
||||||
alt="...">
|
|
||||||
<div class="status-indicator bg-success"></div>
|
|
||||||
</div>
|
|
||||||
<div class="font-weight-bold">
|
|
||||||
<div class="text-truncate">Hi there! I am wondering if you can help me with a
|
|
||||||
problem I've been having.</div>
|
|
||||||
<div class="small text-gray-500">Emily Fowler · 58m</div>
|
|
||||||
</div>
|
|
||||||
</a>
|
|
||||||
<a class="dropdown-item d-flex align-items-center" href="#">
|
|
||||||
<div class="dropdown-list-image mr-3">
|
|
||||||
<img class="rounded-circle" src="img/undraw_profile_2.svg"
|
|
||||||
alt="...">
|
|
||||||
<div class="status-indicator"></div>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<div class="text-truncate">I have the photos that you ordered last month, how
|
|
||||||
would you like them sent to you?</div>
|
|
||||||
<div class="small text-gray-500">Jae Chun · 1d</div>
|
|
||||||
</div>
|
|
||||||
</a>
|
|
||||||
<a class="dropdown-item d-flex align-items-center" href="#">
|
|
||||||
<div class="dropdown-list-image mr-3">
|
|
||||||
<img class="rounded-circle" src="img/undraw_profile_3.svg"
|
|
||||||
alt="...">
|
|
||||||
<div class="status-indicator bg-warning"></div>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<div class="text-truncate">Last month's report looks great, I am very happy with
|
|
||||||
the progress so far, keep up the good work!</div>
|
|
||||||
<div class="small text-gray-500">Morgan Alvarez · 2d</div>
|
|
||||||
</div>
|
|
||||||
</a>
|
|
||||||
<a class="dropdown-item d-flex align-items-center" href="#">
|
|
||||||
<div class="dropdown-list-image mr-3">
|
|
||||||
<img class="rounded-circle" src="https://source.unsplash.com/Mv9hjnEUHR4/60x60"
|
|
||||||
alt="...">
|
|
||||||
<div class="status-indicator bg-success"></div>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<div class="text-truncate">Am I a good boy? The reason I ask is because someone
|
|
||||||
told me that people say this to all dogs, even if they aren't good...</div>
|
|
||||||
<div class="small text-gray-500">Chicken the Dog · 2w</div>
|
|
||||||
</div>
|
|
||||||
</a>
|
|
||||||
<a class="dropdown-item text-center small text-gray-500" href="#">Read More Messages</a>
|
|
||||||
</div>
|
|
||||||
</li>
|
|
||||||
|
|
||||||
<div class="topbar-divider d-none d-sm-block"></div>
|
|
||||||
|
|
||||||
<!-- Nav Item - User Information -->
|
|
||||||
<li class="nav-item dropdown no-arrow">
|
|
||||||
<a class="nav-link dropdown-toggle" href="#" id="userDropdown" role="button"
|
|
||||||
data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
|
|
||||||
<span class="mr-2 d-none d-lg-inline text-gray-600 small">Douglas McGee</span>
|
|
||||||
<img class="img-profile rounded-circle"
|
|
||||||
src="img/undraw_profile.svg">
|
|
||||||
</a>
|
|
||||||
<!-- Dropdown - User Information -->
|
|
||||||
<div class="dropdown-menu dropdown-menu-right shadow animated--grow-in"
|
|
||||||
aria-labelledby="userDropdown">
|
|
||||||
<a class="dropdown-item" href="#">
|
|
||||||
<i class="fas fa-user fa-sm fa-fw mr-2 text-gray-400"></i>
|
|
||||||
Profile
|
|
||||||
</a>
|
|
||||||
<a class="dropdown-item" href="#">
|
|
||||||
<i class="fas fa-cogs fa-sm fa-fw mr-2 text-gray-400"></i>
|
|
||||||
Settings
|
|
||||||
</a>
|
|
||||||
<a class="dropdown-item" href="#">
|
|
||||||
<i class="fas fa-list fa-sm fa-fw mr-2 text-gray-400"></i>
|
|
||||||
Activity Log
|
|
||||||
</a>
|
|
||||||
<div class="dropdown-divider"></div>
|
|
||||||
<a class="dropdown-item" href="#" data-toggle="modal" data-target="#logoutModal">
|
|
||||||
<i class="fas fa-sign-out-alt fa-sm fa-fw mr-2 text-gray-400"></i>
|
|
||||||
Logout
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
</li>
|
|
||||||
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
</nav>
|
|
||||||
<!-- End of Topbar -->
|
|
||||||
|
|
||||||
<!-- Begin Page Content -->
|
|
||||||
<div class="container-fluid">
|
|
||||||
|
|
||||||
<!-- Page Heading -->
|
|
||||||
<h1 class="h3 mb-1 text-gray-800">Border Utilities</h1>
|
|
||||||
<p class="mb-4">Bootstrap's default utility classes can be found on the official <a
|
|
||||||
href="https://getbootstrap.com/docs">Bootstrap Documentation</a> page. The custom utilities
|
|
||||||
below were created to extend this theme past the default utility classes built into Bootstrap's
|
|
||||||
framework.</p>
|
|
||||||
|
|
||||||
<!-- Content Row -->
|
|
||||||
<div class="row">
|
|
||||||
|
|
||||||
<!-- Border Left Utilities -->
|
|
||||||
<div class="col-lg-6">
|
|
||||||
|
|
||||||
<div class="card mb-4 py-3 border-left-primary">
|
|
||||||
<div class="card-body">
|
|
||||||
.border-left-primary
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="card mb-4 py-3 border-left-secondary">
|
|
||||||
<div class="card-body">
|
|
||||||
.border-left-secondary
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="card mb-4 py-3 border-left-success">
|
|
||||||
<div class="card-body">
|
|
||||||
.border-left-success
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="card mb-4 py-3 border-left-info">
|
|
||||||
<div class="card-body">
|
|
||||||
.border-left-info
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="card mb-4 py-3 border-left-warning">
|
|
||||||
<div class="card-body">
|
|
||||||
.border-left-warning
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="card mb-4 py-3 border-left-danger">
|
|
||||||
<div class="card-body">
|
|
||||||
.border-left-danger
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="card mb-4 py-3 border-left-dark">
|
|
||||||
<div class="card-body">
|
|
||||||
.border-left-dark
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Border Bottom Utilities -->
|
|
||||||
<div class="col-lg-6">
|
|
||||||
|
|
||||||
<div class="card mb-4 py-3 border-bottom-primary">
|
|
||||||
<div class="card-body">
|
|
||||||
.border-bottom-primary
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="card mb-4 py-3 border-bottom-secondary">
|
|
||||||
<div class="card-body">
|
|
||||||
.border-bottom-secondary
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="card mb-4 py-3 border-bottom-success">
|
|
||||||
<div class="card-body">
|
|
||||||
.border-bottom-success
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="card mb-4 py-3 border-bottom-info">
|
|
||||||
<div class="card-body">
|
|
||||||
.border-bottom-info
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="card mb-4 py-3 border-bottom-warning">
|
|
||||||
<div class="card-body">
|
|
||||||
.border-bottom-warning
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="card mb-4 py-3 border-bottom-danger">
|
|
||||||
<div class="card-body">
|
|
||||||
.border-bottom-danger
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="card mb-4 py-3 border-bottom-dark">
|
|
||||||
<div class="card-body">
|
|
||||||
.border-bottom-dark
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
<!-- /.container-fluid -->
|
|
||||||
|
|
||||||
</div>
|
|
||||||
<!-- End of Main Content -->
|
|
||||||
|
|
||||||
<!-- Footer -->
|
|
||||||
<footer class="sticky-footer bg-white">
|
|
||||||
<div class="container my-auto">
|
|
||||||
<div class="copyright text-center my-auto">
|
|
||||||
<span>Copyright © Your Website 2020</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</footer>
|
|
||||||
<!-- End of Footer -->
|
|
||||||
|
|
||||||
</div>
|
|
||||||
<!-- End of Content Wrapper -->
|
|
||||||
|
|
||||||
</div>
|
|
||||||
<!-- End of Page Wrapper -->
|
|
||||||
|
|
||||||
<!-- Scroll to Top Button-->
|
|
||||||
<a class="scroll-to-top rounded" href="#page-top">
|
|
||||||
<i class="fas fa-angle-up"></i>
|
|
||||||
</a>
|
|
||||||
|
|
||||||
<!-- Logout Modal-->
|
|
||||||
<div class="modal fade" id="logoutModal" tabindex="-1" role="dialog" aria-labelledby="exampleModalLabel"
|
|
||||||
aria-hidden="true">
|
|
||||||
<div class="modal-dialog" role="document">
|
|
||||||
<div class="modal-content">
|
|
||||||
<div class="modal-header">
|
|
||||||
<h5 class="modal-title" id="exampleModalLabel">Ready to Leave?</h5>
|
|
||||||
<button class="close" type="button" data-dismiss="modal" aria-label="Close">
|
|
||||||
<span aria-hidden="true">×</span>
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
<div class="modal-body">Select "Logout" below if you are ready to end your current session.</div>
|
|
||||||
<div class="modal-footer">
|
|
||||||
<button class="btn btn-secondary" type="button" data-dismiss="modal">Cancel</button>
|
|
||||||
<a class="btn btn-primary" href="login.html">Logout</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Bootstrap core JavaScript-->
|
|
||||||
<script src="vendor/jquery/jquery.min.js"></script>
|
|
||||||
<script src="vendor/bootstrap/js/bootstrap.bundle.min.js"></script>
|
|
||||||
|
|
||||||
<!-- Core plugin JavaScript-->
|
|
||||||
<script src="vendor/jquery-easing/jquery.easing.min.js"></script>
|
|
||||||
|
|
||||||
<!-- Custom scripts for all pages-->
|
|
||||||
<script src="js/sb-admin-2.min.js"></script>
|
|
||||||
|
|
||||||
</body>
|
|
||||||
|
|
||||||
</html>
|
|
||||||
@@ -1,512 +0,0 @@
|
|||||||
<!DOCTYPE html>
|
|
||||||
<html lang="en">
|
|
||||||
|
|
||||||
<head>
|
|
||||||
|
|
||||||
<meta charset="utf-8">
|
|
||||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
|
||||||
<meta name="description" content="">
|
|
||||||
<meta name="author" content="">
|
|
||||||
|
|
||||||
<title>SB Admin 2 - Color Utilities</title>
|
|
||||||
|
|
||||||
<!-- Custom fonts for this template-->
|
|
||||||
<link href="vendor/fontawesome-free/css/all.min.css" rel="stylesheet" type="text/css">
|
|
||||||
<link
|
|
||||||
href="https://fonts.googleapis.com/css?family=Nunito:200,200i,300,300i,400,400i,600,600i,700,700i,800,800i,900,900i"
|
|
||||||
rel="stylesheet">
|
|
||||||
|
|
||||||
<!-- Custom styles for this template-->
|
|
||||||
<link href="css/sb-admin-2.min.css" rel="stylesheet">
|
|
||||||
|
|
||||||
</head>
|
|
||||||
|
|
||||||
<body id="page-top">
|
|
||||||
|
|
||||||
<!-- Page Wrapper -->
|
|
||||||
<div id="wrapper">
|
|
||||||
|
|
||||||
<!-- Sidebar -->
|
|
||||||
<ul class="navbar-nav bg-gradient-primary sidebar sidebar-dark accordion" id="accordionSidebar">
|
|
||||||
|
|
||||||
<!-- Sidebar - Brand -->
|
|
||||||
<a class="sidebar-brand d-flex align-items-center justify-content-center" href="index.html">
|
|
||||||
<div class="sidebar-brand-icon rotate-n-15">
|
|
||||||
<i class="fas fa-laugh-wink"></i>
|
|
||||||
</div>
|
|
||||||
<div class="sidebar-brand-text mx-3">SB Admin <sup>2</sup></div>
|
|
||||||
</a>
|
|
||||||
|
|
||||||
<!-- Divider -->
|
|
||||||
<hr class="sidebar-divider my-0">
|
|
||||||
|
|
||||||
<!-- Nav Item - Dashboard -->
|
|
||||||
<li class="nav-item">
|
|
||||||
<a class="nav-link" href="index.html">
|
|
||||||
<i class="fas fa-fw fa-tachometer-alt"></i>
|
|
||||||
<span>Dashboard</span></a>
|
|
||||||
</li>
|
|
||||||
|
|
||||||
<!-- Divider -->
|
|
||||||
<hr class="sidebar-divider">
|
|
||||||
|
|
||||||
<!-- Heading -->
|
|
||||||
<div class="sidebar-heading">
|
|
||||||
Interface
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Nav Item - Pages Collapse Menu -->
|
|
||||||
<li class="nav-item">
|
|
||||||
<a class="nav-link collapsed" href="#" data-toggle="collapse" data-target="#collapseTwo"
|
|
||||||
aria-expanded="true" aria-controls="collapseTwo">
|
|
||||||
<i class="fas fa-fw fa-cog"></i>
|
|
||||||
<span>Components</span>
|
|
||||||
</a>
|
|
||||||
<div id="collapseTwo" class="collapse" aria-labelledby="headingTwo" data-parent="#accordionSidebar">
|
|
||||||
<div class="bg-white py-2 collapse-inner rounded">
|
|
||||||
<h6 class="collapse-header">Custom Components:</h6>
|
|
||||||
<a class="collapse-item" href="buttons.html">Buttons</a>
|
|
||||||
<a class="collapse-item" href="cards.html">Cards</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</li>
|
|
||||||
|
|
||||||
<!-- Nav Item - Utilities Collapse Menu -->
|
|
||||||
<li class="nav-item active">
|
|
||||||
<a class="nav-link" href="#" data-toggle="collapse" data-target="#collapseUtilities"
|
|
||||||
aria-expanded="true" aria-controls="collapseUtilities">
|
|
||||||
<i class="fas fa-fw fa-wrench"></i>
|
|
||||||
<span>Utilities</span>
|
|
||||||
</a>
|
|
||||||
<div id="collapseUtilities" class="collapse show" aria-labelledby="headingUtilities"
|
|
||||||
data-parent="#accordionSidebar">
|
|
||||||
<div class="bg-white py-2 collapse-inner rounded">
|
|
||||||
<h6 class="collapse-header">Custom Utilities:</h6>
|
|
||||||
<a class="collapse-item active" href="utilities-color.html">Colors</a>
|
|
||||||
<a class="collapse-item" href="utilities-border.html">Borders</a>
|
|
||||||
<a class="collapse-item" href="utilities-animation.html">Animations</a>
|
|
||||||
<a class="collapse-item" href="utilities-other.html">Other</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</li>
|
|
||||||
|
|
||||||
<!-- Divider -->
|
|
||||||
<hr class="sidebar-divider">
|
|
||||||
|
|
||||||
<!-- Heading -->
|
|
||||||
<div class="sidebar-heading">
|
|
||||||
Addons
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Nav Item - Pages Collapse Menu -->
|
|
||||||
<li class="nav-item">
|
|
||||||
<a class="nav-link collapsed" href="#" data-toggle="collapse" data-target="#collapsePages"
|
|
||||||
aria-expanded="true" aria-controls="collapsePages">
|
|
||||||
<i class="fas fa-fw fa-folder"></i>
|
|
||||||
<span>Pages</span>
|
|
||||||
</a>
|
|
||||||
<div id="collapsePages" class="collapse" aria-labelledby="headingPages" data-parent="#accordionSidebar">
|
|
||||||
<div class="bg-white py-2 collapse-inner rounded">
|
|
||||||
<h6 class="collapse-header">Login Screens:</h6>
|
|
||||||
<a class="collapse-item" href="login.html">Login</a>
|
|
||||||
<a class="collapse-item" href="register.html">Register</a>
|
|
||||||
<a class="collapse-item" href="forgot-password.html">Forgot Password</a>
|
|
||||||
<div class="collapse-divider"></div>
|
|
||||||
<h6 class="collapse-header">Other Pages:</h6>
|
|
||||||
<a class="collapse-item" href="404.html">404 Page</a>
|
|
||||||
<a class="collapse-item" href="blank.html">Blank Page</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</li>
|
|
||||||
|
|
||||||
<!-- Nav Item - Charts -->
|
|
||||||
<li class="nav-item">
|
|
||||||
<a class="nav-link" href="charts.html">
|
|
||||||
<i class="fas fa-fw fa-chart-area"></i>
|
|
||||||
<span>Charts</span></a>
|
|
||||||
</li>
|
|
||||||
|
|
||||||
<!-- Nav Item - Tables -->
|
|
||||||
<li class="nav-item">
|
|
||||||
<a class="nav-link" href="tables.html">
|
|
||||||
<i class="fas fa-fw fa-table"></i>
|
|
||||||
<span>Tables</span></a>
|
|
||||||
</li>
|
|
||||||
|
|
||||||
<!-- Divider -->
|
|
||||||
<hr class="sidebar-divider d-none d-md-block">
|
|
||||||
|
|
||||||
<!-- Sidebar Toggler (Sidebar) -->
|
|
||||||
<div class="text-center d-none d-md-inline">
|
|
||||||
<button class="rounded-circle border-0" id="sidebarToggle"></button>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</ul>
|
|
||||||
<!-- End of Sidebar -->
|
|
||||||
|
|
||||||
<!-- Content Wrapper -->
|
|
||||||
<div id="content-wrapper" class="d-flex flex-column">
|
|
||||||
|
|
||||||
<!-- Main Content -->
|
|
||||||
<div id="content">
|
|
||||||
|
|
||||||
<!-- Topbar -->
|
|
||||||
<nav class="navbar navbar-expand navbar-light bg-white topbar mb-4 static-top shadow">
|
|
||||||
|
|
||||||
<!-- Sidebar Toggle (Topbar) -->
|
|
||||||
<button id="sidebarToggleTop" class="btn btn-link d-md-none rounded-circle mr-3">
|
|
||||||
<i class="fa fa-bars"></i>
|
|
||||||
</button>
|
|
||||||
|
|
||||||
<!-- Topbar Search -->
|
|
||||||
<form
|
|
||||||
class="d-none d-sm-inline-block form-inline mr-auto ml-md-3 my-2 my-md-0 mw-100 navbar-search">
|
|
||||||
<div class="input-group">
|
|
||||||
<input type="text" class="form-control bg-light border-0 small" placeholder="Search for..."
|
|
||||||
aria-label="Search" aria-describedby="basic-addon2">
|
|
||||||
<div class="input-group-append">
|
|
||||||
<button class="btn btn-primary" type="button">
|
|
||||||
<i class="fas fa-search fa-sm"></i>
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
|
|
||||||
<!-- Topbar Navbar -->
|
|
||||||
<ul class="navbar-nav ml-auto">
|
|
||||||
|
|
||||||
<!-- Nav Item - Search Dropdown (Visible Only XS) -->
|
|
||||||
<li class="nav-item dropdown no-arrow d-sm-none">
|
|
||||||
<a class="nav-link dropdown-toggle" href="#" id="searchDropdown" role="button"
|
|
||||||
data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
|
|
||||||
<i class="fas fa-search fa-fw"></i>
|
|
||||||
</a>
|
|
||||||
<!-- Dropdown - Messages -->
|
|
||||||
<div class="dropdown-menu dropdown-menu-right p-3 shadow animated--grow-in"
|
|
||||||
aria-labelledby="searchDropdown">
|
|
||||||
<form class="form-inline mr-auto w-100 navbar-search">
|
|
||||||
<div class="input-group">
|
|
||||||
<input type="text" class="form-control bg-light border-0 small"
|
|
||||||
placeholder="Search for..." aria-label="Search"
|
|
||||||
aria-describedby="basic-addon2">
|
|
||||||
<div class="input-group-append">
|
|
||||||
<button class="btn btn-primary" type="button">
|
|
||||||
<i class="fas fa-search fa-sm"></i>
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
</li>
|
|
||||||
|
|
||||||
<!-- Nav Item - Alerts -->
|
|
||||||
<li class="nav-item dropdown no-arrow mx-1">
|
|
||||||
<a class="nav-link dropdown-toggle" href="#" id="alertsDropdown" role="button"
|
|
||||||
data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
|
|
||||||
<i class="fas fa-bell fa-fw"></i>
|
|
||||||
<!-- Counter - Alerts -->
|
|
||||||
<span class="badge badge-danger badge-counter">3+</span>
|
|
||||||
</a>
|
|
||||||
<!-- Dropdown - Alerts -->
|
|
||||||
<div class="dropdown-list dropdown-menu dropdown-menu-right shadow animated--grow-in"
|
|
||||||
aria-labelledby="alertsDropdown">
|
|
||||||
<h6 class="dropdown-header">
|
|
||||||
Alerts Center
|
|
||||||
</h6>
|
|
||||||
<a class="dropdown-item d-flex align-items-center" href="#">
|
|
||||||
<div class="mr-3">
|
|
||||||
<div class="icon-circle bg-primary">
|
|
||||||
<i class="fas fa-file-alt text-white"></i>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<div class="small text-gray-500">December 12, 2019</div>
|
|
||||||
<span class="font-weight-bold">A new monthly report is ready to download!</span>
|
|
||||||
</div>
|
|
||||||
</a>
|
|
||||||
<a class="dropdown-item d-flex align-items-center" href="#">
|
|
||||||
<div class="mr-3">
|
|
||||||
<div class="icon-circle bg-success">
|
|
||||||
<i class="fas fa-donate text-white"></i>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<div class="small text-gray-500">December 7, 2019</div>
|
|
||||||
$290.29 has been deposited into your account!
|
|
||||||
</div>
|
|
||||||
</a>
|
|
||||||
<a class="dropdown-item d-flex align-items-center" href="#">
|
|
||||||
<div class="mr-3">
|
|
||||||
<div class="icon-circle bg-warning">
|
|
||||||
<i class="fas fa-exclamation-triangle text-white"></i>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<div class="small text-gray-500">December 2, 2019</div>
|
|
||||||
Spending Alert: We've noticed unusually high spending for your account.
|
|
||||||
</div>
|
|
||||||
</a>
|
|
||||||
<a class="dropdown-item text-center small text-gray-500" href="#">Show All Alerts</a>
|
|
||||||
</div>
|
|
||||||
</li>
|
|
||||||
|
|
||||||
<!-- Nav Item - Messages -->
|
|
||||||
<li class="nav-item dropdown no-arrow mx-1">
|
|
||||||
<a class="nav-link dropdown-toggle" href="#" id="messagesDropdown" role="button"
|
|
||||||
data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
|
|
||||||
<i class="fas fa-envelope fa-fw"></i>
|
|
||||||
<!-- Counter - Messages -->
|
|
||||||
<span class="badge badge-danger badge-counter">7</span>
|
|
||||||
</a>
|
|
||||||
<!-- Dropdown - Messages -->
|
|
||||||
<div class="dropdown-list dropdown-menu dropdown-menu-right shadow animated--grow-in"
|
|
||||||
aria-labelledby="messagesDropdown">
|
|
||||||
<h6 class="dropdown-header">
|
|
||||||
Message Center
|
|
||||||
</h6>
|
|
||||||
<a class="dropdown-item d-flex align-items-center" href="#">
|
|
||||||
<div class="dropdown-list-image mr-3">
|
|
||||||
<img class="rounded-circle" src="img/undraw_profile_1.svg"
|
|
||||||
alt="...">
|
|
||||||
<div class="status-indicator bg-success"></div>
|
|
||||||
</div>
|
|
||||||
<div class="font-weight-bold">
|
|
||||||
<div class="text-truncate">Hi there! I am wondering if you can help me with a
|
|
||||||
problem I've been having.</div>
|
|
||||||
<div class="small text-gray-500">Emily Fowler · 58m</div>
|
|
||||||
</div>
|
|
||||||
</a>
|
|
||||||
<a class="dropdown-item d-flex align-items-center" href="#">
|
|
||||||
<div class="dropdown-list-image mr-3">
|
|
||||||
<img class="rounded-circle" src="img/undraw_profile_2.svg"
|
|
||||||
alt="...">
|
|
||||||
<div class="status-indicator"></div>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<div class="text-truncate">I have the photos that you ordered last month, how
|
|
||||||
would you like them sent to you?</div>
|
|
||||||
<div class="small text-gray-500">Jae Chun · 1d</div>
|
|
||||||
</div>
|
|
||||||
</a>
|
|
||||||
<a class="dropdown-item d-flex align-items-center" href="#">
|
|
||||||
<div class="dropdown-list-image mr-3">
|
|
||||||
<img class="rounded-circle" src="img/undraw_profile_3.svg"
|
|
||||||
alt="...">
|
|
||||||
<div class="status-indicator bg-warning"></div>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<div class="text-truncate">Last month's report looks great, I am very happy with
|
|
||||||
the progress so far, keep up the good work!</div>
|
|
||||||
<div class="small text-gray-500">Morgan Alvarez · 2d</div>
|
|
||||||
</div>
|
|
||||||
</a>
|
|
||||||
<a class="dropdown-item d-flex align-items-center" href="#">
|
|
||||||
<div class="dropdown-list-image mr-3">
|
|
||||||
<img class="rounded-circle" src="https://source.unsplash.com/Mv9hjnEUHR4/60x60"
|
|
||||||
alt="...">
|
|
||||||
<div class="status-indicator bg-success"></div>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<div class="text-truncate">Am I a good boy? The reason I ask is because someone
|
|
||||||
told me that people say this to all dogs, even if they aren't good...</div>
|
|
||||||
<div class="small text-gray-500">Chicken the Dog · 2w</div>
|
|
||||||
</div>
|
|
||||||
</a>
|
|
||||||
<a class="dropdown-item text-center small text-gray-500" href="#">Read More Messages</a>
|
|
||||||
</div>
|
|
||||||
</li>
|
|
||||||
|
|
||||||
<div class="topbar-divider d-none d-sm-block"></div>
|
|
||||||
|
|
||||||
<!-- Nav Item - User Information -->
|
|
||||||
<li class="nav-item dropdown no-arrow">
|
|
||||||
<a class="nav-link dropdown-toggle" href="#" id="userDropdown" role="button"
|
|
||||||
data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
|
|
||||||
<span class="mr-2 d-none d-lg-inline text-gray-600 small">Douglas McGee</span>
|
|
||||||
<img class="img-profile rounded-circle"
|
|
||||||
src="img/undraw_profile.svg">
|
|
||||||
</a>
|
|
||||||
<!-- Dropdown - User Information -->
|
|
||||||
<div class="dropdown-menu dropdown-menu-right shadow animated--grow-in"
|
|
||||||
aria-labelledby="userDropdown">
|
|
||||||
<a class="dropdown-item" href="#">
|
|
||||||
<i class="fas fa-user fa-sm fa-fw mr-2 text-gray-400"></i>
|
|
||||||
Profile
|
|
||||||
</a>
|
|
||||||
<a class="dropdown-item" href="#">
|
|
||||||
<i class="fas fa-cogs fa-sm fa-fw mr-2 text-gray-400"></i>
|
|
||||||
Settings
|
|
||||||
</a>
|
|
||||||
<a class="dropdown-item" href="#">
|
|
||||||
<i class="fas fa-list fa-sm fa-fw mr-2 text-gray-400"></i>
|
|
||||||
Activity Log
|
|
||||||
</a>
|
|
||||||
<div class="dropdown-divider"></div>
|
|
||||||
<a class="dropdown-item" href="#" data-toggle="modal" data-target="#logoutModal">
|
|
||||||
<i class="fas fa-sign-out-alt fa-sm fa-fw mr-2 text-gray-400"></i>
|
|
||||||
Logout
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
</li>
|
|
||||||
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
</nav>
|
|
||||||
<!-- End of Topbar -->
|
|
||||||
|
|
||||||
<!-- Begin Page Content -->
|
|
||||||
<div class="container-fluid">
|
|
||||||
|
|
||||||
<!-- Page Heading -->
|
|
||||||
<h1 class="h3 mb-1 text-gray-800">Color Utilities</h1>
|
|
||||||
<p class="mb-4">Bootstrap's default utility classes can be found on the official <a
|
|
||||||
href="https://getbootstrap.com/docs">Bootstrap Documentation</a> page. The custom utilities
|
|
||||||
below were created to extend this theme past the default utility classes built into Bootstrap's
|
|
||||||
framework.</p>
|
|
||||||
|
|
||||||
<!-- Content Row -->
|
|
||||||
<div class="row">
|
|
||||||
|
|
||||||
<!-- First Column -->
|
|
||||||
<div class="col-lg-4">
|
|
||||||
|
|
||||||
<!-- Custom Text Color Utilities -->
|
|
||||||
<div class="card shadow mb-4">
|
|
||||||
<div class="card-header py-3">
|
|
||||||
<h6 class="m-0 font-weight-bold text-primary">Custom Text Color Utilities</h6>
|
|
||||||
</div>
|
|
||||||
<div class="card-body">
|
|
||||||
<p class="text-gray-100 p-3 bg-dark m-0">.text-gray-100</p>
|
|
||||||
<p class="text-gray-200 p-3 bg-dark m-0">.text-gray-200</p>
|
|
||||||
<p class="text-gray-300 p-3 bg-dark m-0">.text-gray-300</p>
|
|
||||||
<p class="text-gray-400 p-3 bg-dark m-0">.text-gray-400</p>
|
|
||||||
<p class="text-gray-500 p-3 m-0">.text-gray-500</p>
|
|
||||||
<p class="text-gray-600 p-3 m-0">.text-gray-600</p>
|
|
||||||
<p class="text-gray-700 p-3 m-0">.text-gray-700</p>
|
|
||||||
<p class="text-gray-800 p-3 m-0">.text-gray-800</p>
|
|
||||||
<p class="text-gray-900 p-3 m-0">.text-gray-900</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Custom Font Size Utilities -->
|
|
||||||
<div class="card shadow mb-4">
|
|
||||||
<div class="card-header py-3">
|
|
||||||
<h6 class="m-0 font-weight-bold text-primary">Custom Font Size Utilities</h6>
|
|
||||||
</div>
|
|
||||||
<div class="card-body">
|
|
||||||
<p class="text-xs">.text-xs</p>
|
|
||||||
<p class="text-lg mb-0">.text-lg</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Second Column -->
|
|
||||||
<div class="col-lg-4">
|
|
||||||
|
|
||||||
<!-- Background Gradient Utilities -->
|
|
||||||
<div class="card shadow mb-4">
|
|
||||||
<div class="card-header py-3">
|
|
||||||
<h6 class="m-0 font-weight-bold text-primary">Custom Background Gradient Utilities
|
|
||||||
</h6>
|
|
||||||
</div>
|
|
||||||
<div class="card-body">
|
|
||||||
<div class="px-3 py-5 bg-gradient-primary text-white">.bg-gradient-primary</div>
|
|
||||||
<div class="px-3 py-5 bg-gradient-secondary text-white">.bg-gradient-secondary</div>
|
|
||||||
<div class="px-3 py-5 bg-gradient-success text-white">.bg-gradient-success</div>
|
|
||||||
<div class="px-3 py-5 bg-gradient-info text-white">.bg-gradient-info</div>
|
|
||||||
<div class="px-3 py-5 bg-gradient-warning text-white">.bg-gradient-warning</div>
|
|
||||||
<div class="px-3 py-5 bg-gradient-danger text-white">.bg-gradient-danger</div>
|
|
||||||
<div class="px-3 py-5 bg-gradient-light text-white">.bg-gradient-light</div>
|
|
||||||
<div class="px-3 py-5 bg-gradient-dark text-white">.bg-gradient-dark</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Third Column -->
|
|
||||||
<div class="col-lg-4">
|
|
||||||
|
|
||||||
<!-- Grayscale Utilities -->
|
|
||||||
<div class="card shadow mb-4">
|
|
||||||
<div class="card-header py-3">
|
|
||||||
<h6 class="m-0 font-weight-bold text-primary">Custom Grayscale Background Utilities
|
|
||||||
</h6>
|
|
||||||
</div>
|
|
||||||
<div class="card-body">
|
|
||||||
<div class="p-3 bg-gray-100">.bg-gray-100</div>
|
|
||||||
<div class="p-3 bg-gray-200">.bg-gray-200</div>
|
|
||||||
<div class="p-3 bg-gray-300">.bg-gray-300</div>
|
|
||||||
<div class="p-3 bg-gray-400">.bg-gray-400</div>
|
|
||||||
<div class="p-3 bg-gray-500 text-white">.bg-gray-500</div>
|
|
||||||
<div class="p-3 bg-gray-600 text-white">.bg-gray-600</div>
|
|
||||||
<div class="p-3 bg-gray-700 text-white">.bg-gray-700</div>
|
|
||||||
<div class="p-3 bg-gray-800 text-white">.bg-gray-800</div>
|
|
||||||
<div class="p-3 bg-gray-900 text-white">.bg-gray-900</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
<!-- /.container-fluid -->
|
|
||||||
|
|
||||||
</div>
|
|
||||||
<!-- End of Main Content -->
|
|
||||||
|
|
||||||
<!-- Footer -->
|
|
||||||
<footer class="sticky-footer bg-white">
|
|
||||||
<div class="container my-auto">
|
|
||||||
<div class="copyright text-center my-auto">
|
|
||||||
<span>Copyright © Your Website 2020</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</footer>
|
|
||||||
<!-- End of Footer -->
|
|
||||||
|
|
||||||
</div>
|
|
||||||
<!-- End of Content Wrapper -->
|
|
||||||
|
|
||||||
</div>
|
|
||||||
<!-- End of Page Wrapper -->
|
|
||||||
|
|
||||||
<!-- Scroll to Top Button-->
|
|
||||||
<a class="scroll-to-top rounded" href="#page-top">
|
|
||||||
<i class="fas fa-angle-up"></i>
|
|
||||||
</a>
|
|
||||||
|
|
||||||
<!-- Logout Modal-->
|
|
||||||
<div class="modal fade" id="logoutModal" tabindex="-1" role="dialog" aria-labelledby="exampleModalLabel"
|
|
||||||
aria-hidden="true">
|
|
||||||
<div class="modal-dialog" role="document">
|
|
||||||
<div class="modal-content">
|
|
||||||
<div class="modal-header">
|
|
||||||
<h5 class="modal-title" id="exampleModalLabel">Ready to Leave?</h5>
|
|
||||||
<button class="close" type="button" data-dismiss="modal" aria-label="Close">
|
|
||||||
<span aria-hidden="true">×</span>
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
<div class="modal-body">Select "Logout" below if you are ready to end your current session.</div>
|
|
||||||
<div class="modal-footer">
|
|
||||||
<button class="btn btn-secondary" type="button" data-dismiss="modal">Cancel</button>
|
|
||||||
<a class="btn btn-primary" href="login.html">Logout</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Bootstrap core JavaScript-->
|
|
||||||
<script src="vendor/jquery/jquery.min.js"></script>
|
|
||||||
<script src="vendor/bootstrap/js/bootstrap.bundle.min.js"></script>
|
|
||||||
|
|
||||||
<!-- Core plugin JavaScript-->
|
|
||||||
<script src="vendor/jquery-easing/jquery.easing.min.js"></script>
|
|
||||||
|
|
||||||
<!-- Custom scripts for all pages-->
|
|
||||||
<script src="js/sb-admin-2.min.js"></script>
|
|
||||||
|
|
||||||
</body>
|
|
||||||
|
|
||||||
</html>
|
|
||||||
@@ -1,506 +0,0 @@
|
|||||||
<!DOCTYPE html>
|
|
||||||
<html lang="en">
|
|
||||||
|
|
||||||
<head>
|
|
||||||
|
|
||||||
<meta charset="utf-8">
|
|
||||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
|
||||||
<meta name="description" content="">
|
|
||||||
<meta name="author" content="">
|
|
||||||
|
|
||||||
<title>SB Admin 2 - Other Utilities</title>
|
|
||||||
|
|
||||||
<!-- Custom fonts for this template-->
|
|
||||||
<link href="vendor/fontawesome-free/css/all.min.css" rel="stylesheet" type="text/css">
|
|
||||||
<link
|
|
||||||
href="https://fonts.googleapis.com/css?family=Nunito:200,200i,300,300i,400,400i,600,600i,700,700i,800,800i,900,900i"
|
|
||||||
rel="stylesheet">
|
|
||||||
|
|
||||||
<!-- Custom styles for this template-->
|
|
||||||
<link href="css/sb-admin-2.min.css" rel="stylesheet">
|
|
||||||
|
|
||||||
</head>
|
|
||||||
|
|
||||||
<body id="page-top">
|
|
||||||
|
|
||||||
<!-- Page Wrapper -->
|
|
||||||
<div id="wrapper">
|
|
||||||
|
|
||||||
<!-- Sidebar -->
|
|
||||||
<ul class="navbar-nav bg-gradient-primary sidebar sidebar-dark accordion" id="accordionSidebar">
|
|
||||||
|
|
||||||
<!-- Sidebar - Brand -->
|
|
||||||
<a class="sidebar-brand d-flex align-items-center justify-content-center" href="index.html">
|
|
||||||
<div class="sidebar-brand-icon rotate-n-15">
|
|
||||||
<i class="fas fa-laugh-wink"></i>
|
|
||||||
</div>
|
|
||||||
<div class="sidebar-brand-text mx-3">SB Admin <sup>2</sup></div>
|
|
||||||
</a>
|
|
||||||
|
|
||||||
<!-- Divider -->
|
|
||||||
<hr class="sidebar-divider my-0">
|
|
||||||
|
|
||||||
<!-- Nav Item - Dashboard -->
|
|
||||||
<li class="nav-item">
|
|
||||||
<a class="nav-link" href="index.html">
|
|
||||||
<i class="fas fa-fw fa-tachometer-alt"></i>
|
|
||||||
<span>Dashboard</span></a>
|
|
||||||
</li>
|
|
||||||
|
|
||||||
<!-- Divider -->
|
|
||||||
<hr class="sidebar-divider">
|
|
||||||
|
|
||||||
<!-- Heading -->
|
|
||||||
<div class="sidebar-heading">
|
|
||||||
Interface
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Nav Item - Pages Collapse Menu -->
|
|
||||||
<li class="nav-item">
|
|
||||||
<a class="nav-link collapsed" href="#" data-toggle="collapse" data-target="#collapseTwo"
|
|
||||||
aria-expanded="true" aria-controls="collapseTwo">
|
|
||||||
<i class="fas fa-fw fa-cog"></i>
|
|
||||||
<span>Components</span>
|
|
||||||
</a>
|
|
||||||
<div id="collapseTwo" class="collapse" aria-labelledby="headingTwo" data-parent="#accordionSidebar">
|
|
||||||
<div class="bg-white py-2 collapse-inner rounded">
|
|
||||||
<h6 class="collapse-header">Custom Components:</h6>
|
|
||||||
<a class="collapse-item" href="buttons.html">Buttons</a>
|
|
||||||
<a class="collapse-item" href="cards.html">Cards</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</li>
|
|
||||||
|
|
||||||
<!-- Nav Item - Utilities Collapse Menu -->
|
|
||||||
<li class="nav-item active">
|
|
||||||
<a class="nav-link" href="#" data-toggle="collapse" data-target="#collapseUtilities"
|
|
||||||
aria-expanded="true" aria-controls="collapseUtilities">
|
|
||||||
<i class="fas fa-fw fa-wrench"></i>
|
|
||||||
<span>Utilities</span>
|
|
||||||
</a>
|
|
||||||
<div id="collapseUtilities" class="collapse show" aria-labelledby="headingUtilities"
|
|
||||||
data-parent="#accordionSidebar">
|
|
||||||
<div class="bg-white py-2 collapse-inner rounded">
|
|
||||||
<h6 class="collapse-header">Custom Utilities:</h6>
|
|
||||||
<a class="collapse-item" href="utilities-color.html">Colors</a>
|
|
||||||
<a class="collapse-item" href="utilities-border.html">Borders</a>
|
|
||||||
<a class="collapse-item" href="utilities-animation.html">Animations</a>
|
|
||||||
<a class="collapse-item active" href="utilities-other.html">Other</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</li>
|
|
||||||
|
|
||||||
<!-- Divider -->
|
|
||||||
<hr class="sidebar-divider">
|
|
||||||
|
|
||||||
<!-- Heading -->
|
|
||||||
<div class="sidebar-heading">
|
|
||||||
Addons
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Nav Item - Pages Collapse Menu -->
|
|
||||||
<li class="nav-item">
|
|
||||||
<a class="nav-link collapsed" href="#" data-toggle="collapse" data-target="#collapsePages"
|
|
||||||
aria-expanded="true" aria-controls="collapsePages">
|
|
||||||
<i class="fas fa-fw fa-folder"></i>
|
|
||||||
<span>Pages</span>
|
|
||||||
</a>
|
|
||||||
<div id="collapsePages" class="collapse" aria-labelledby="headingPages" data-parent="#accordionSidebar">
|
|
||||||
<div class="bg-white py-2 collapse-inner rounded">
|
|
||||||
<h6 class="collapse-header">Login Screens:</h6>
|
|
||||||
<a class="collapse-item" href="login.html">Login</a>
|
|
||||||
<a class="collapse-item" href="register.html">Register</a>
|
|
||||||
<a class="collapse-item" href="forgot-password.html">Forgot Password</a>
|
|
||||||
<div class="collapse-divider"></div>
|
|
||||||
<h6 class="collapse-header">Other Pages:</h6>
|
|
||||||
<a class="collapse-item" href="404.html">404 Page</a>
|
|
||||||
<a class="collapse-item" href="blank.html">Blank Page</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</li>
|
|
||||||
|
|
||||||
<!-- Nav Item - Charts -->
|
|
||||||
<li class="nav-item">
|
|
||||||
<a class="nav-link" href="charts.html">
|
|
||||||
<i class="fas fa-fw fa-chart-area"></i>
|
|
||||||
<span>Charts</span></a>
|
|
||||||
</li>
|
|
||||||
|
|
||||||
<!-- Nav Item - Tables -->
|
|
||||||
<li class="nav-item">
|
|
||||||
<a class="nav-link" href="tables.html">
|
|
||||||
<i class="fas fa-fw fa-table"></i>
|
|
||||||
<span>Tables</span></a>
|
|
||||||
</li>
|
|
||||||
|
|
||||||
<!-- Divider -->
|
|
||||||
<hr class="sidebar-divider d-none d-md-block">
|
|
||||||
|
|
||||||
<!-- Sidebar Toggler (Sidebar) -->
|
|
||||||
<div class="text-center d-none d-md-inline">
|
|
||||||
<button class="rounded-circle border-0" id="sidebarToggle"></button>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</ul>
|
|
||||||
<!-- End of Sidebar -->
|
|
||||||
|
|
||||||
<!-- Content Wrapper -->
|
|
||||||
<div id="content-wrapper" class="d-flex flex-column">
|
|
||||||
|
|
||||||
<!-- Main Content -->
|
|
||||||
<div id="content">
|
|
||||||
|
|
||||||
<!-- Topbar -->
|
|
||||||
<nav class="navbar navbar-expand navbar-light bg-white topbar mb-4 static-top shadow">
|
|
||||||
|
|
||||||
<!-- Sidebar Toggle (Topbar) -->
|
|
||||||
<button id="sidebarToggleTop" class="btn btn-link d-md-none rounded-circle mr-3">
|
|
||||||
<i class="fa fa-bars"></i>
|
|
||||||
</button>
|
|
||||||
|
|
||||||
<!-- Topbar Search -->
|
|
||||||
<form
|
|
||||||
class="d-none d-sm-inline-block form-inline mr-auto ml-md-3 my-2 my-md-0 mw-100 navbar-search">
|
|
||||||
<div class="input-group">
|
|
||||||
<input type="text" class="form-control bg-light border-0 small" placeholder="Search for..."
|
|
||||||
aria-label="Search" aria-describedby="basic-addon2">
|
|
||||||
<div class="input-group-append">
|
|
||||||
<button class="btn btn-primary" type="button">
|
|
||||||
<i class="fas fa-search fa-sm"></i>
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
|
|
||||||
<!-- Topbar Navbar -->
|
|
||||||
<ul class="navbar-nav ml-auto">
|
|
||||||
|
|
||||||
<!-- Nav Item - Search Dropdown (Visible Only XS) -->
|
|
||||||
<li class="nav-item dropdown no-arrow d-sm-none">
|
|
||||||
<a class="nav-link dropdown-toggle" href="#" id="searchDropdown" role="button"
|
|
||||||
data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
|
|
||||||
<i class="fas fa-search fa-fw"></i>
|
|
||||||
</a>
|
|
||||||
<!-- Dropdown - Messages -->
|
|
||||||
<div class="dropdown-menu dropdown-menu-right p-3 shadow animated--grow-in"
|
|
||||||
aria-labelledby="searchDropdown">
|
|
||||||
<form class="form-inline mr-auto w-100 navbar-search">
|
|
||||||
<div class="input-group">
|
|
||||||
<input type="text" class="form-control bg-light border-0 small"
|
|
||||||
placeholder="Search for..." aria-label="Search"
|
|
||||||
aria-describedby="basic-addon2">
|
|
||||||
<div class="input-group-append">
|
|
||||||
<button class="btn btn-primary" type="button">
|
|
||||||
<i class="fas fa-search fa-sm"></i>
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
</li>
|
|
||||||
|
|
||||||
<!-- Nav Item - Alerts -->
|
|
||||||
<li class="nav-item dropdown no-arrow mx-1">
|
|
||||||
<a class="nav-link dropdown-toggle" href="#" id="alertsDropdown" role="button"
|
|
||||||
data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
|
|
||||||
<i class="fas fa-bell fa-fw"></i>
|
|
||||||
<!-- Counter - Alerts -->
|
|
||||||
<span class="badge badge-danger badge-counter">3+</span>
|
|
||||||
</a>
|
|
||||||
<!-- Dropdown - Alerts -->
|
|
||||||
<div class="dropdown-list dropdown-menu dropdown-menu-right shadow animated--grow-in"
|
|
||||||
aria-labelledby="alertsDropdown">
|
|
||||||
<h6 class="dropdown-header">
|
|
||||||
Alerts Center
|
|
||||||
</h6>
|
|
||||||
<a class="dropdown-item d-flex align-items-center" href="#">
|
|
||||||
<div class="mr-3">
|
|
||||||
<div class="icon-circle bg-primary">
|
|
||||||
<i class="fas fa-file-alt text-white"></i>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<div class="small text-gray-500">December 12, 2019</div>
|
|
||||||
<span class="font-weight-bold">A new monthly report is ready to download!</span>
|
|
||||||
</div>
|
|
||||||
</a>
|
|
||||||
<a class="dropdown-item d-flex align-items-center" href="#">
|
|
||||||
<div class="mr-3">
|
|
||||||
<div class="icon-circle bg-success">
|
|
||||||
<i class="fas fa-donate text-white"></i>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<div class="small text-gray-500">December 7, 2019</div>
|
|
||||||
$290.29 has been deposited into your account!
|
|
||||||
</div>
|
|
||||||
</a>
|
|
||||||
<a class="dropdown-item d-flex align-items-center" href="#">
|
|
||||||
<div class="mr-3">
|
|
||||||
<div class="icon-circle bg-warning">
|
|
||||||
<i class="fas fa-exclamation-triangle text-white"></i>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<div class="small text-gray-500">December 2, 2019</div>
|
|
||||||
Spending Alert: We've noticed unusually high spending for your account.
|
|
||||||
</div>
|
|
||||||
</a>
|
|
||||||
<a class="dropdown-item text-center small text-gray-500" href="#">Show All Alerts</a>
|
|
||||||
</div>
|
|
||||||
</li>
|
|
||||||
|
|
||||||
<!-- Nav Item - Messages -->
|
|
||||||
<li class="nav-item dropdown no-arrow mx-1">
|
|
||||||
<a class="nav-link dropdown-toggle" href="#" id="messagesDropdown" role="button"
|
|
||||||
data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
|
|
||||||
<i class="fas fa-envelope fa-fw"></i>
|
|
||||||
<!-- Counter - Messages -->
|
|
||||||
<span class="badge badge-danger badge-counter">7</span>
|
|
||||||
</a>
|
|
||||||
<!-- Dropdown - Messages -->
|
|
||||||
<div class="dropdown-list dropdown-menu dropdown-menu-right shadow animated--grow-in"
|
|
||||||
aria-labelledby="messagesDropdown">
|
|
||||||
<h6 class="dropdown-header">
|
|
||||||
Message Center
|
|
||||||
</h6>
|
|
||||||
<a class="dropdown-item d-flex align-items-center" href="#">
|
|
||||||
<div class="dropdown-list-image mr-3">
|
|
||||||
<img class="rounded-circle" src="img/undraw_profile_1.svg"
|
|
||||||
alt="...">
|
|
||||||
<div class="status-indicator bg-success"></div>
|
|
||||||
</div>
|
|
||||||
<div class="font-weight-bold">
|
|
||||||
<div class="text-truncate">Hi there! I am wondering if you can help me with a
|
|
||||||
problem I've been having.</div>
|
|
||||||
<div class="small text-gray-500">Emily Fowler · 58m</div>
|
|
||||||
</div>
|
|
||||||
</a>
|
|
||||||
<a class="dropdown-item d-flex align-items-center" href="#">
|
|
||||||
<div class="dropdown-list-image mr-3">
|
|
||||||
<img class="rounded-circle" src="img/undraw_profile_2.svg"
|
|
||||||
alt="...">
|
|
||||||
<div class="status-indicator"></div>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<div class="text-truncate">I have the photos that you ordered last month, how
|
|
||||||
would you like them sent to you?</div>
|
|
||||||
<div class="small text-gray-500">Jae Chun · 1d</div>
|
|
||||||
</div>
|
|
||||||
</a>
|
|
||||||
<a class="dropdown-item d-flex align-items-center" href="#">
|
|
||||||
<div class="dropdown-list-image mr-3">
|
|
||||||
<img class="rounded-circle" src="img/undraw_profile_3.svg"
|
|
||||||
alt="...">
|
|
||||||
<div class="status-indicator bg-warning"></div>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<div class="text-truncate">Last month's report looks great, I am very happy with
|
|
||||||
the progress so far, keep up the good work!</div>
|
|
||||||
<div class="small text-gray-500">Morgan Alvarez · 2d</div>
|
|
||||||
</div>
|
|
||||||
</a>
|
|
||||||
<a class="dropdown-item d-flex align-items-center" href="#">
|
|
||||||
<div class="dropdown-list-image mr-3">
|
|
||||||
<img class="rounded-circle" src="https://source.unsplash.com/Mv9hjnEUHR4/60x60"
|
|
||||||
alt="...">
|
|
||||||
<div class="status-indicator bg-success"></div>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<div class="text-truncate">Am I a good boy? The reason I ask is because someone
|
|
||||||
told me that people say this to all dogs, even if they aren't good...</div>
|
|
||||||
<div class="small text-gray-500">Chicken the Dog · 2w</div>
|
|
||||||
</div>
|
|
||||||
</a>
|
|
||||||
<a class="dropdown-item text-center small text-gray-500" href="#">Read More Messages</a>
|
|
||||||
</div>
|
|
||||||
</li>
|
|
||||||
|
|
||||||
<div class="topbar-divider d-none d-sm-block"></div>
|
|
||||||
|
|
||||||
<!-- Nav Item - User Information -->
|
|
||||||
<li class="nav-item dropdown no-arrow">
|
|
||||||
<a class="nav-link dropdown-toggle" href="#" id="userDropdown" role="button"
|
|
||||||
data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
|
|
||||||
<span class="mr-2 d-none d-lg-inline text-gray-600 small">Douglas McGee</span>
|
|
||||||
<img class="img-profile rounded-circle"
|
|
||||||
src="img/undraw_profile.svg">
|
|
||||||
</a>
|
|
||||||
<!-- Dropdown - User Information -->
|
|
||||||
<div class="dropdown-menu dropdown-menu-right shadow animated--grow-in"
|
|
||||||
aria-labelledby="userDropdown">
|
|
||||||
<a class="dropdown-item" href="#">
|
|
||||||
<i class="fas fa-user fa-sm fa-fw mr-2 text-gray-400"></i>
|
|
||||||
Profile
|
|
||||||
</a>
|
|
||||||
<a class="dropdown-item" href="#">
|
|
||||||
<i class="fas fa-cogs fa-sm fa-fw mr-2 text-gray-400"></i>
|
|
||||||
Settings
|
|
||||||
</a>
|
|
||||||
<a class="dropdown-item" href="#">
|
|
||||||
<i class="fas fa-list fa-sm fa-fw mr-2 text-gray-400"></i>
|
|
||||||
Activity Log
|
|
||||||
</a>
|
|
||||||
<div class="dropdown-divider"></div>
|
|
||||||
<a class="dropdown-item" href="#" data-toggle="modal" data-target="#logoutModal">
|
|
||||||
<i class="fas fa-sign-out-alt fa-sm fa-fw mr-2 text-gray-400"></i>
|
|
||||||
Logout
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
</li>
|
|
||||||
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
</nav>
|
|
||||||
<!-- End of Topbar -->
|
|
||||||
|
|
||||||
<!-- Begin Page Content -->
|
|
||||||
<div class="container-fluid">
|
|
||||||
|
|
||||||
<!-- Page Heading -->
|
|
||||||
<h1 class="h3 mb-1 text-gray-800">Other Utilities</h1>
|
|
||||||
<p class="mb-4">Bootstrap's default utility classes can be found on the official <a
|
|
||||||
href="https://getbootstrap.com/docs">Bootstrap Documentation</a> page. The custom utilities
|
|
||||||
below were created to extend this theme past the default utility classes built into Bootstrap's
|
|
||||||
framework.</p>
|
|
||||||
|
|
||||||
<!-- Content Row -->
|
|
||||||
<div class="row">
|
|
||||||
|
|
||||||
<div class="col-lg-6">
|
|
||||||
|
|
||||||
<!-- Overflow Hidden -->
|
|
||||||
<div class="card mb-4">
|
|
||||||
<div class="card-header py-3">
|
|
||||||
<h6 class="m-0 font-weight-bold text-primary">Overflow Hidden Utilty</h6>
|
|
||||||
</div>
|
|
||||||
<div class="card-body">
|
|
||||||
Use <code>.o-hidden</code> to set the overflow property of any element to hidden.
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Progress Small -->
|
|
||||||
<div class="card mb-4">
|
|
||||||
<div class="card-header py-3">
|
|
||||||
<h6 class="m-0 font-weight-bold text-primary">Progress Small Utility</h6>
|
|
||||||
</div>
|
|
||||||
<div class="card-body">
|
|
||||||
<div class="mb-1 small">Normal Progress Bar</div>
|
|
||||||
<div class="progress mb-4">
|
|
||||||
<div class="progress-bar" role="progressbar" style="width: 75%"
|
|
||||||
aria-valuenow="75" aria-valuemin="0" aria-valuemax="100"></div>
|
|
||||||
</div>
|
|
||||||
<div class="mb-1 small">Small Progress Bar</div>
|
|
||||||
<div class="progress progress-sm mb-2">
|
|
||||||
<div class="progress-bar" role="progressbar" style="width: 75%"
|
|
||||||
aria-valuenow="75" aria-valuemin="0" aria-valuemax="100"></div>
|
|
||||||
</div>
|
|
||||||
Use the <code>.progress-sm</code> class along with <code>.progress</code>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Dropdown No Arrow -->
|
|
||||||
<div class="card mb-4">
|
|
||||||
<div class="card-header py-3">
|
|
||||||
<h6 class="m-0 font-weight-bold text-primary">Dropdown - No Arrow</h6>
|
|
||||||
</div>
|
|
||||||
<div class="card-body">
|
|
||||||
<div class="dropdown no-arrow mb-4">
|
|
||||||
<button class="btn btn-secondary dropdown-toggle" type="button"
|
|
||||||
id="dropdownMenuButton" data-toggle="dropdown" aria-haspopup="true"
|
|
||||||
aria-expanded="false">
|
|
||||||
Dropdown (no arrow)
|
|
||||||
</button>
|
|
||||||
<div class="dropdown-menu" aria-labelledby="dropdownMenuButton">
|
|
||||||
<a class="dropdown-item" href="#">Action</a>
|
|
||||||
<a class="dropdown-item" href="#">Another action</a>
|
|
||||||
<a class="dropdown-item" href="#">Something else here</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
Add the <code>.no-arrow</code> class alongside the <code>.dropdown</code>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="col-lg-6">
|
|
||||||
|
|
||||||
<!-- Roitation Utilities -->
|
|
||||||
<div class="card">
|
|
||||||
<div class="card-header py-3">
|
|
||||||
<h6 class="m-0 font-weight-bold text-primary">Rotation Utilities</h6>
|
|
||||||
</div>
|
|
||||||
<div class="card-body text-center">
|
|
||||||
<div class="bg-primary text-white p-3 rotate-15 d-inline-block my-4">.rotate-15
|
|
||||||
</div>
|
|
||||||
<hr>
|
|
||||||
<div class="bg-primary text-white p-3 rotate-n-15 d-inline-block my-4">.rotate-n-15
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
<!-- /.container-fluid -->
|
|
||||||
|
|
||||||
</div>
|
|
||||||
<!-- End of Main Content -->
|
|
||||||
|
|
||||||
<!-- Footer -->
|
|
||||||
<footer class="sticky-footer bg-white">
|
|
||||||
<div class="container my-auto">
|
|
||||||
<div class="copyright text-center my-auto">
|
|
||||||
<span>Copyright © Your Website 2020</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</footer>
|
|
||||||
<!-- End of Footer -->
|
|
||||||
|
|
||||||
</div>
|
|
||||||
<!-- End of Content Wrapper -->
|
|
||||||
|
|
||||||
</div>
|
|
||||||
<!-- End of Page Wrapper -->
|
|
||||||
|
|
||||||
<!-- Scroll to Top Button-->
|
|
||||||
<a class="scroll-to-top rounded" href="#page-top">
|
|
||||||
<i class="fas fa-angle-up"></i>
|
|
||||||
</a>
|
|
||||||
|
|
||||||
<!-- Logout Modal-->
|
|
||||||
<div class="modal fade" id="logoutModal" tabindex="-1" role="dialog" aria-labelledby="exampleModalLabel"
|
|
||||||
aria-hidden="true">
|
|
||||||
<div class="modal-dialog" role="document">
|
|
||||||
<div class="modal-content">
|
|
||||||
<div class="modal-header">
|
|
||||||
<h5 class="modal-title" id="exampleModalLabel">Ready to Leave?</h5>
|
|
||||||
<button class="close" type="button" data-dismiss="modal" aria-label="Close">
|
|
||||||
<span aria-hidden="true">×</span>
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
<div class="modal-body">Select "Logout" below if you are ready to end your current session.</div>
|
|
||||||
<div class="modal-footer">
|
|
||||||
<button class="btn btn-secondary" type="button" data-dismiss="modal">Cancel</button>
|
|
||||||
<a class="btn btn-primary" href="login.html">Logout</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Bootstrap core JavaScript-->
|
|
||||||
<script src="vendor/jquery/jquery.min.js"></script>
|
|
||||||
<script src="vendor/bootstrap/js/bootstrap.bundle.min.js"></script>
|
|
||||||
|
|
||||||
<!-- Core plugin JavaScript-->
|
|
||||||
<script src="vendor/jquery-easing/jquery.easing.min.js"></script>
|
|
||||||
|
|
||||||
<!-- Custom scripts for all pages-->
|
|
||||||
<script src="js/sb-admin-2.min.js"></script>
|
|
||||||
|
|
||||||
</body>
|
|
||||||
|
|
||||||
</html>
|
|
||||||
@@ -10,19 +10,7 @@
|
|||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Content Remove="Views\Charts\Charts.cshtml" />
|
<Compile Remove="Controllers\HelloFresh\HelloFreshScraperService.cs" />
|
||||||
<Content Remove="Views\Components\Buttons.cshtml" />
|
|
||||||
<Content Remove="Views\Components\Cards.cshtml" />
|
|
||||||
<Content Remove="Views\Connections\ForgotPassword.cshtml" />
|
|
||||||
<Content Remove="Views\Connections\Login.cshtml" />
|
|
||||||
<Content Remove="Views\Connections\Register.cshtml" />
|
|
||||||
<Content Remove="Views\Home\Tables.cshtml" />
|
|
||||||
<Content Remove="Views\Shared\Blank.cshtml" />
|
|
||||||
<Content Remove="Views\Shared\Error.cshtml" />
|
|
||||||
<Content Remove="Views\Utilities\UtilitiesAnimation.cshtml" />
|
|
||||||
<Content Remove="Views\Utilities\UtilitiesBorder.cshtml" />
|
|
||||||
<Content Remove="Views\Utilities\UtilitiesColor.cshtml" />
|
|
||||||
<Content Remove="Views\Utilities\UtilitiesOther.cshtml" />
|
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
@@ -30,22 +18,15 @@
|
|||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<None Include="Views\Charts\Charts.cshtml" />
|
|
||||||
<None Include="Views\Components\Buttons.cshtml" />
|
|
||||||
<None Include="Views\Components\Cards.cshtml" />
|
|
||||||
<None Include="Views\Connections\ForgotPassword.cshtml" />
|
<None Include="Views\Connections\ForgotPassword.cshtml" />
|
||||||
<None Include="Views\Connections\Login.cshtml" />
|
<None Include="Views\Connections\Login.cshtml" />
|
||||||
<None Include="Views\Connections\Register.cshtml" />
|
<None Include="Views\Connections\Register.cshtml" />
|
||||||
<None Include="Views\Shared\Blank.cshtml" />
|
<None Include="Views\Shared\Blank.cshtml" />
|
||||||
<None Include="Views\Shared\Error.cshtml" />
|
<None Include="Views\Shared\Error.cshtml" />
|
||||||
<None Include="Views\Tables\Tables.cshtml" />
|
|
||||||
<None Include="Views\Utilities\UtilitiesAnimation.cshtml" />
|
|
||||||
<None Include="Views\Utilities\UtilitiesBorder.cshtml" />
|
|
||||||
<None Include="Views\Utilities\UtilitiesColor.cshtml" />
|
|
||||||
<None Include="Views\Utilities\UtilitiesOther.cshtml" />
|
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<PackageReference Include="AngleSharp" Version="1.3.0" />
|
||||||
<PackageReference Include="DotNetEnv" Version="3.1.1" />
|
<PackageReference Include="DotNetEnv" Version="3.1.1" />
|
||||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="9.0.7">
|
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="9.0.7">
|
||||||
<PrivateAssets>all</PrivateAssets>
|
<PrivateAssets>all</PrivateAssets>
|
||||||
@@ -54,6 +35,7 @@
|
|||||||
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="9.0.7" />
|
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="9.0.7" />
|
||||||
<PackageReference Include="Microsoft.SqlServer.Server" Version="1.0.0" />
|
<PackageReference Include="Microsoft.SqlServer.Server" Version="1.0.0" />
|
||||||
<PackageReference Include="Microsoft.VisualStudio.Azure.Containers.Tools.Targets" Version="1.21.0" />
|
<PackageReference Include="Microsoft.VisualStudio.Azure.Containers.Tools.Targets" Version="1.21.0" />
|
||||||
|
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
|
||||||
<PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="9.0.4" />
|
<PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="9.0.4" />
|
||||||
<PackageReference Include="System.Data.SqlClient" Version="4.9.0" />
|
<PackageReference Include="System.Data.SqlClient" Version="4.9.0" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|||||||
@@ -1,8 +1,13 @@
|
|||||||
{
|
{
|
||||||
|
"Ollama": {
|
||||||
|
"Url": "https://ollama.byakurepo.online",
|
||||||
|
"Model": "qwen2.5:1.5b-instruct" // plus rapide que 3b
|
||||||
|
},
|
||||||
"Logging": {
|
"Logging": {
|
||||||
"LogLevel": {
|
"LogLevel": {
|
||||||
"Default": "Information",
|
"Default": "Information",
|
||||||
"Microsoft.AspNetCore": "Warning"
|
"Administration.Controllers.SearchController": "Debug",
|
||||||
|
"administration.Controllers.HelloFreshController": "Debug"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,12 +1,9 @@
|
|||||||
{
|
{
|
||||||
"Logging": {
|
"Ollama": {
|
||||||
"LogLevel": {
|
"Url": "http://ollama:11434",
|
||||||
"Default": "Information",
|
"Model": "qwen2.5:3b-instruct"
|
||||||
"Microsoft.AspNetCore": "Warning"
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
"AllowedHosts": "*",
|
|
||||||
"ConnectionStrings": {
|
"ConnectionStrings": {
|
||||||
"DefaultConnection": "Server=217.154.116.43,1433;Database=Finances;User Id=sa;Password=Mf33ksTRLrPKSqQ4cTXitgiSN6BPBt89;TrustServerCertificate=True;"
|
"HelloFreshConnection": "Server=217.154.116.43;Database=HelloFresh;User Id=sa;Password=Wi0a6kxXjAhtSswP22FYZW9UBxRrgght8MMncp8F;TrustServerCertificate=True;Encrypt=False"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
26
node_modules/.package-lock.json
generated
vendored
Normal file
26
node_modules/.package-lock.json
generated
vendored
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
{
|
||||||
|
"name": "administration",
|
||||||
|
"lockfileVersion": 3,
|
||||||
|
"requires": true,
|
||||||
|
"packages": {
|
||||||
|
"node_modules/@popperjs/core": {
|
||||||
|
"version": "2.11.8",
|
||||||
|
"resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.8.tgz",
|
||||||
|
"integrity": "sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A==",
|
||||||
|
"license": "MIT",
|
||||||
|
"funding": {
|
||||||
|
"type": "opencollective",
|
||||||
|
"url": "https://opencollective.com/popperjs"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/tippy.js": {
|
||||||
|
"version": "6.3.7",
|
||||||
|
"resolved": "https://registry.npmjs.org/tippy.js/-/tippy.js-6.3.7.tgz",
|
||||||
|
"integrity": "sha512-E1d3oP2emgJ9dRQZdf3Kkn0qJgI6ZLpyS5z6ZkY1DF3kaQaBsGZsndEpHwx+eC+tYM41HaSNvNtLx8tU57FzTQ==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@popperjs/core": "^2.9.0"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
20
node_modules/@popperjs/core/LICENSE.md
generated
vendored
Normal file
20
node_modules/@popperjs/core/LICENSE.md
generated
vendored
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
The MIT License (MIT)
|
||||||
|
|
||||||
|
Copyright (c) 2019 Federico Zivolo
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||||
|
this software and associated documentation files (the "Software"), to deal in
|
||||||
|
the Software without restriction, including without limitation the rights to
|
||||||
|
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||||
|
the Software, and to permit persons to whom the Software is furnished to do so,
|
||||||
|
subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||||
|
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||||
|
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||||
|
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
376
node_modules/@popperjs/core/README.md
generated
vendored
Normal file
376
node_modules/@popperjs/core/README.md
generated
vendored
Normal file
@@ -0,0 +1,376 @@
|
|||||||
|
<!-- <HEADER> // IGNORE IT -->
|
||||||
|
<p align="center">
|
||||||
|
<img src="https://rawcdn.githack.com/popperjs/popper-core/8805a5d7599e14619c9e7ac19a3713285d8e5d7f/docs/src/images/popper-logo-outlined.svg" alt="Popper" height="300px"/>
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<div align="center">
|
||||||
|
<h1>Tooltip & Popover Positioning Engine</h1>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<p align="center">
|
||||||
|
<a href="https://www.npmjs.com/package/@popperjs/core">
|
||||||
|
<img src="https://img.shields.io/npm/v/@popperjs/core?style=for-the-badge" alt="npm version" />
|
||||||
|
</a>
|
||||||
|
<a href="https://www.npmjs.com/package/@popperjs/core">
|
||||||
|
<img src="https://img.shields.io/endpoint?style=for-the-badge&url=https://runkit.io/fezvrasta/combined-npm-downloads/1.0.0?packages=popper.js,@popperjs/core" alt="npm downloads per month (popper.js + @popperjs/core)" />
|
||||||
|
</a>
|
||||||
|
<a href="https://rollingversions.com/popperjs/popper-core">
|
||||||
|
<img src="https://img.shields.io/badge/Rolling%20Versions-Enabled-brightgreen?style=for-the-badge" alt="Rolling Versions" />
|
||||||
|
</a>
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<br />
|
||||||
|
<!-- </HEADER> // NOW BEGINS THE README -->
|
||||||
|
|
||||||
|
**Positioning tooltips and popovers is difficult. Popper is here to help!**
|
||||||
|
|
||||||
|
Given an element, such as a button, and a tooltip element describing it, Popper
|
||||||
|
will automatically put the tooltip in the right place near the button.
|
||||||
|
|
||||||
|
It will position _any_ UI element that "pops out" from the flow of your document
|
||||||
|
and floats near a target element. The most common example is a tooltip, but it
|
||||||
|
also includes popovers, drop-downs, and more. All of these can be generically
|
||||||
|
described as a "popper" element.
|
||||||
|
|
||||||
|
## Demo
|
||||||
|
|
||||||
|
[](https://popper.js.org)
|
||||||
|
|
||||||
|
## Docs
|
||||||
|
|
||||||
|
- [v2.x (latest)](https://popper.js.org/docs/v2/)
|
||||||
|
- [v1.x](https://popper.js.org/docs/v1/)
|
||||||
|
|
||||||
|
We've created a
|
||||||
|
[Migration Guide](https://popper.js.org/docs/v2/migration-guide/) to help you
|
||||||
|
migrate from Popper 1 to Popper 2.
|
||||||
|
|
||||||
|
To contribute to the Popper website and documentation, please visit the
|
||||||
|
[dedicated repository](https://github.com/popperjs/website).
|
||||||
|
|
||||||
|
## Why not use pure CSS?
|
||||||
|
|
||||||
|
- **Clipping and overflow issues**: Pure CSS poppers will not be prevented from
|
||||||
|
overflowing clipping boundaries, such as the viewport. It will get partially
|
||||||
|
cut off or overflows if it's near the edge since there is no dynamic
|
||||||
|
positioning logic. When using Popper, your popper will always be positioned in
|
||||||
|
the right place without needing manual adjustments.
|
||||||
|
- **No flipping**: CSS poppers will not flip to a different placement to fit
|
||||||
|
better in view if necessary. While you can manually adjust for the main axis
|
||||||
|
overflow, this feature cannot be achieved via CSS alone. Popper automatically
|
||||||
|
flips the tooltip to make it fit in view as best as possible for the user.
|
||||||
|
- **No virtual positioning**: CSS poppers cannot follow the mouse cursor or be
|
||||||
|
used as a context menu. Popper allows you to position your tooltip relative to
|
||||||
|
any coordinates you desire.
|
||||||
|
- **Slower development cycle**: When pure CSS is used to position popper
|
||||||
|
elements, the lack of dynamic positioning means they must be carefully placed
|
||||||
|
to consider overflow on all screen sizes. In reusable component libraries,
|
||||||
|
this means a developer can't just add the component anywhere on the page,
|
||||||
|
because these issues need to be considered and adjusted for every time. With
|
||||||
|
Popper, you can place your elements anywhere and they will be positioned
|
||||||
|
correctly, without needing to consider different screen sizes, layouts, etc.
|
||||||
|
This massively speeds up development time because this work is automatically
|
||||||
|
offloaded to Popper.
|
||||||
|
- **Lack of extensibility**: CSS poppers cannot be easily extended to fit any
|
||||||
|
arbitrary use case you may need to adjust for. Popper is built with
|
||||||
|
extensibility in mind.
|
||||||
|
|
||||||
|
## Why Popper?
|
||||||
|
|
||||||
|
With the CSS drawbacks out of the way, we now move on to Popper in the
|
||||||
|
JavaScript space itself.
|
||||||
|
|
||||||
|
Naive JavaScript tooltip implementations usually have the following problems:
|
||||||
|
|
||||||
|
- **Scrolling containers**: They don't ensure the tooltip stays with the
|
||||||
|
reference element while scrolling when inside any number of scrolling
|
||||||
|
containers.
|
||||||
|
- **DOM context**: They often require the tooltip move outside of its original
|
||||||
|
DOM context because they don't handle `offsetParent` contexts.
|
||||||
|
- **Compatibility**: Popper handles an incredible number of edge cases regarding
|
||||||
|
different browsers and environments (mobile viewports, RTL, scrollbars enabled
|
||||||
|
or disabled, etc.). Popper is a popular and well-maintained library, so you
|
||||||
|
can be confident positioning will work for your users on any device.
|
||||||
|
- **Configurability**: They often lack advanced configurability to suit any
|
||||||
|
possible use case.
|
||||||
|
- **Size**: They are usually relatively large in size, or require an ancient
|
||||||
|
jQuery dependency.
|
||||||
|
- **Performance**: They often have runtime performance issues and update the
|
||||||
|
tooltip position too slowly.
|
||||||
|
|
||||||
|
**Popper solves all of these key problems in an elegant, performant manner.** It
|
||||||
|
is a lightweight ~3 kB library that aims to provide a reliable and extensible
|
||||||
|
positioning engine you can use to ensure all your popper elements are positioned
|
||||||
|
in the right place.
|
||||||
|
|
||||||
|
When you start writing your own popper implementation, you'll quickly run into
|
||||||
|
all of the problems mentioned above. These widgets are incredibly common in our
|
||||||
|
UIs; we've done the hard work figuring this out so you don't need to spend hours
|
||||||
|
fixing and handling numerous edge cases that we already ran into while building
|
||||||
|
the library!
|
||||||
|
|
||||||
|
Popper is used in popular libraries like Bootstrap, Foundation, Material UI, and
|
||||||
|
more. It's likely you've already used popper elements on the web positioned by
|
||||||
|
Popper at some point in the past few years.
|
||||||
|
|
||||||
|
Since we write UIs using powerful abstraction libraries such as React or Angular
|
||||||
|
nowadays, you'll also be glad to know Popper can fully integrate with them and
|
||||||
|
be a good citizen together with your other components. Check out `react-popper`
|
||||||
|
for the official Popper wrapper for React.
|
||||||
|
|
||||||
|
## Installation
|
||||||
|
|
||||||
|
### 1. Package Manager
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# With npm
|
||||||
|
npm i @popperjs/core
|
||||||
|
|
||||||
|
# With Yarn
|
||||||
|
yarn add @popperjs/core
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. CDN
|
||||||
|
|
||||||
|
```html
|
||||||
|
<!-- Development version -->
|
||||||
|
<script src="https://unpkg.com/@popperjs/core@2/dist/umd/popper.js"></script>
|
||||||
|
|
||||||
|
<!-- Production version -->
|
||||||
|
<script src="https://unpkg.com/@popperjs/core@2"></script>
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3. Direct Download?
|
||||||
|
|
||||||
|
Managing dependencies by "directly downloading" them and placing them into your
|
||||||
|
source code is not recommended for a variety of reasons, including missing out
|
||||||
|
on feat/fix updates easily. Please use a versioning management system like a CDN
|
||||||
|
or npm/Yarn.
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
The most straightforward way to get started is to import Popper from the `unpkg`
|
||||||
|
CDN, which includes all of its features. You can call the `Popper.createPopper`
|
||||||
|
constructor to create new popper instances.
|
||||||
|
|
||||||
|
Here is a complete example:
|
||||||
|
|
||||||
|
```html
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<title>Popper example</title>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
#tooltip {
|
||||||
|
background-color: #333;
|
||||||
|
color: white;
|
||||||
|
padding: 5px 10px;
|
||||||
|
border-radius: 4px;
|
||||||
|
font-size: 13px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<button id="button" aria-describedby="tooltip">I'm a button</button>
|
||||||
|
<div id="tooltip" role="tooltip">I'm a tooltip</div>
|
||||||
|
|
||||||
|
<script src="https://unpkg.com/@popperjs/core@^2.0.0"></script>
|
||||||
|
<script>
|
||||||
|
const button = document.querySelector('#button');
|
||||||
|
const tooltip = document.querySelector('#tooltip');
|
||||||
|
|
||||||
|
// Pass the button, the tooltip, and some options, and Popper will do the
|
||||||
|
// magic positioning for you:
|
||||||
|
Popper.createPopper(button, tooltip, {
|
||||||
|
placement: 'right',
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
```
|
||||||
|
|
||||||
|
Visit the [tutorial](https://popper.js.org/docs/v2/tutorial/) for an example of
|
||||||
|
how to build your own tooltip from scratch using Popper.
|
||||||
|
|
||||||
|
### Module bundlers
|
||||||
|
|
||||||
|
You can import the `createPopper` constructor from the fully-featured file:
|
||||||
|
|
||||||
|
```js
|
||||||
|
import { createPopper } from '@popperjs/core';
|
||||||
|
|
||||||
|
const button = document.querySelector('#button');
|
||||||
|
const tooltip = document.querySelector('#tooltip');
|
||||||
|
|
||||||
|
// Pass the button, the tooltip, and some options, and Popper will do the
|
||||||
|
// magic positioning for you:
|
||||||
|
createPopper(button, tooltip, {
|
||||||
|
placement: 'right',
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
All the modifiers listed in the docs menu will be enabled and "just work", so
|
||||||
|
you don't need to think about setting Popper up. The size of Popper including
|
||||||
|
all of its features is about 5 kB minzipped, but it may grow a bit in the
|
||||||
|
future.
|
||||||
|
|
||||||
|
#### Popper Lite (tree-shaking)
|
||||||
|
|
||||||
|
If bundle size is important, you'll want to take advantage of tree-shaking. The
|
||||||
|
library is built in a modular way to allow to import only the parts you really
|
||||||
|
need.
|
||||||
|
|
||||||
|
```js
|
||||||
|
import { createPopperLite as createPopper } from '@popperjs/core';
|
||||||
|
```
|
||||||
|
|
||||||
|
The Lite version includes the most necessary modifiers that will compute the
|
||||||
|
offsets of the popper, compute and add the positioning styles, and add event
|
||||||
|
listeners. This is close in bundle size to pure CSS tooltip libraries, and
|
||||||
|
behaves somewhat similarly.
|
||||||
|
|
||||||
|
However, this does not include the features that makes Popper truly useful.
|
||||||
|
|
||||||
|
The two most useful modifiers not included in Lite are `preventOverflow` and
|
||||||
|
`flip`:
|
||||||
|
|
||||||
|
```js
|
||||||
|
import {
|
||||||
|
createPopperLite as createPopper,
|
||||||
|
preventOverflow,
|
||||||
|
flip,
|
||||||
|
} from '@popperjs/core';
|
||||||
|
|
||||||
|
const button = document.querySelector('#button');
|
||||||
|
const tooltip = document.querySelector('#tooltip');
|
||||||
|
|
||||||
|
createPopper(button, tooltip, {
|
||||||
|
modifiers: [preventOverflow, flip],
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
As you make more poppers, you may be finding yourself needing other modifiers
|
||||||
|
provided by the library.
|
||||||
|
|
||||||
|
See [tree-shaking](https://popper.js.org/docs/v2/performance/#tree-shaking) for more
|
||||||
|
information.
|
||||||
|
|
||||||
|
## Distribution targets
|
||||||
|
|
||||||
|
Popper is distributed in 3 different versions, in 3 different file formats.
|
||||||
|
|
||||||
|
The 3 file formats are:
|
||||||
|
|
||||||
|
- `esm` (works with `import` syntax — **recommended**)
|
||||||
|
- `umd` (works with `<script>` tags or RequireJS)
|
||||||
|
- `cjs` (works with `require()` syntax)
|
||||||
|
|
||||||
|
There are two different `esm` builds, one for bundler consumers (e.g. webpack,
|
||||||
|
Rollup, etc..), which is located under `/lib`, and one for browsers with native
|
||||||
|
support for ES Modules, under `/dist/esm`. The only difference within the two,
|
||||||
|
is that the browser-compatible version doesn't make use of
|
||||||
|
`process.env.NODE_ENV` to run development checks.
|
||||||
|
|
||||||
|
The 3 versions are:
|
||||||
|
|
||||||
|
- `popper`: includes all the modifiers (features) in one file (**default**);
|
||||||
|
- `popper-lite`: includes only the minimum amount of modifiers to provide the
|
||||||
|
basic functionality;
|
||||||
|
- `popper-base`: doesn't include any modifier, you must import them separately;
|
||||||
|
|
||||||
|
Below you can find the size of each version, minified and compressed with the
|
||||||
|
[Brotli compression algorithm](https://medium.com/groww-engineering/enable-brotli-compression-in-webpack-with-fallback-to-gzip-397a57cf9fc6):
|
||||||
|
|
||||||
|
<!-- Don't change the labels to use hyphens, it breaks, even when encoded -->
|
||||||
|
|
||||||
|

|
||||||
|

|
||||||
|

|
||||||
|
|
||||||
|
## Hacking the library
|
||||||
|
|
||||||
|
If you want to play with the library, implement new features, fix a bug you
|
||||||
|
found, or simply experiment with it, this section is for you!
|
||||||
|
|
||||||
|
First of all, make sure to have
|
||||||
|
[Yarn installed](https://yarnpkg.com/lang/en/docs/install).
|
||||||
|
|
||||||
|
Install the development dependencies:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
yarn install
|
||||||
|
```
|
||||||
|
|
||||||
|
And run the development environment:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
yarn dev
|
||||||
|
```
|
||||||
|
|
||||||
|
Then, simply open one the development server web page:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# macOS and Linux
|
||||||
|
open localhost:5000
|
||||||
|
|
||||||
|
# Windows
|
||||||
|
start localhost:5000
|
||||||
|
```
|
||||||
|
|
||||||
|
From there, you can open any of the examples (`.html` files) to fiddle with
|
||||||
|
them.
|
||||||
|
|
||||||
|
Now any change you will made to the source code, will be automatically compiled,
|
||||||
|
you just need to refresh the page.
|
||||||
|
|
||||||
|
If the page is not working properly, try to go in _"Developer Tools >
|
||||||
|
Application > Clear storage"_ and click on "_Clear site data_".
|
||||||
|
To run the examples you need a browser with
|
||||||
|
[JavaScript modules via script tag support](https://caniuse.com/#feat=es6-module).
|
||||||
|
|
||||||
|
## Test Suite
|
||||||
|
|
||||||
|
Popper is currently tested with unit tests, and functional tests. Both of them
|
||||||
|
are run by Jest.
|
||||||
|
|
||||||
|
### Unit Tests
|
||||||
|
|
||||||
|
The unit tests use JSDOM to provide a primitive document object API, they are
|
||||||
|
used to ensure the utility functions behave as expected in isolation.
|
||||||
|
|
||||||
|
### Functional Tests
|
||||||
|
|
||||||
|
The functional tests run with Puppeteer, to take advantage of a complete browser
|
||||||
|
environment. They are currently running on Chromium, and Firefox.
|
||||||
|
|
||||||
|
You can run them with `yarn test:functional`. Set the `PUPPETEER_BROWSER`
|
||||||
|
environment variable to `firefox` to run them on the Mozilla browser.
|
||||||
|
|
||||||
|
The assertions are written in form of image snapshots, so that it's easy to
|
||||||
|
assert for the correct Popper behavior without having to write a lot of offsets
|
||||||
|
comparisons manually.
|
||||||
|
|
||||||
|
You can mark a `*.test.js` file to run in the Puppeteer environment by
|
||||||
|
prepending a `@jest-environment puppeteer` JSDoc comment to the interested file.
|
||||||
|
|
||||||
|
Here's an example of a basic functional test:
|
||||||
|
|
||||||
|
```js
|
||||||
|
/**
|
||||||
|
* @jest-environment puppeteer
|
||||||
|
* @flow
|
||||||
|
*/
|
||||||
|
import { screenshot } from '../utils/puppeteer.js';
|
||||||
|
|
||||||
|
it('should position the popper on the right', async () => {
|
||||||
|
const page = await browser.newPage();
|
||||||
|
await page.goto(`${TEST_URL}/basic.html`);
|
||||||
|
|
||||||
|
expect(await screenshot(page)).toMatchImageSnapshot();
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
You can find the complete
|
||||||
|
[`jest-puppeteer` documentation here](https://github.com/smooth-code/jest-puppeteer#api),
|
||||||
|
and the
|
||||||
|
[`jest-image-snapshot` documentation here](https://github.com/americanexpress/jest-image-snapshot#%EF%B8%8F-api).
|
||||||
|
|
||||||
|
## License
|
||||||
|
|
||||||
|
MIT
|
||||||
65
node_modules/@popperjs/core/dist/cjs/enums.js
generated
vendored
Normal file
65
node_modules/@popperjs/core/dist/cjs/enums.js
generated
vendored
Normal file
@@ -0,0 +1,65 @@
|
|||||||
|
/**
|
||||||
|
* @popperjs/core v2.11.8 - MIT License
|
||||||
|
*/
|
||||||
|
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
Object.defineProperty(exports, '__esModule', { value: true });
|
||||||
|
|
||||||
|
var top = 'top';
|
||||||
|
var bottom = 'bottom';
|
||||||
|
var right = 'right';
|
||||||
|
var left = 'left';
|
||||||
|
var auto = 'auto';
|
||||||
|
var basePlacements = [top, bottom, right, left];
|
||||||
|
var start = 'start';
|
||||||
|
var end = 'end';
|
||||||
|
var clippingParents = 'clippingParents';
|
||||||
|
var viewport = 'viewport';
|
||||||
|
var popper = 'popper';
|
||||||
|
var reference = 'reference';
|
||||||
|
var variationPlacements = /*#__PURE__*/basePlacements.reduce(function (acc, placement) {
|
||||||
|
return acc.concat([placement + "-" + start, placement + "-" + end]);
|
||||||
|
}, []);
|
||||||
|
var placements = /*#__PURE__*/[].concat(basePlacements, [auto]).reduce(function (acc, placement) {
|
||||||
|
return acc.concat([placement, placement + "-" + start, placement + "-" + end]);
|
||||||
|
}, []); // modifiers that need to read the DOM
|
||||||
|
|
||||||
|
var beforeRead = 'beforeRead';
|
||||||
|
var read = 'read';
|
||||||
|
var afterRead = 'afterRead'; // pure-logic modifiers
|
||||||
|
|
||||||
|
var beforeMain = 'beforeMain';
|
||||||
|
var main = 'main';
|
||||||
|
var afterMain = 'afterMain'; // modifier with the purpose to write to the DOM (or write into a framework state)
|
||||||
|
|
||||||
|
var beforeWrite = 'beforeWrite';
|
||||||
|
var write = 'write';
|
||||||
|
var afterWrite = 'afterWrite';
|
||||||
|
var modifierPhases = [beforeRead, read, afterRead, beforeMain, main, afterMain, beforeWrite, write, afterWrite];
|
||||||
|
|
||||||
|
exports.afterMain = afterMain;
|
||||||
|
exports.afterRead = afterRead;
|
||||||
|
exports.afterWrite = afterWrite;
|
||||||
|
exports.auto = auto;
|
||||||
|
exports.basePlacements = basePlacements;
|
||||||
|
exports.beforeMain = beforeMain;
|
||||||
|
exports.beforeRead = beforeRead;
|
||||||
|
exports.beforeWrite = beforeWrite;
|
||||||
|
exports.bottom = bottom;
|
||||||
|
exports.clippingParents = clippingParents;
|
||||||
|
exports.end = end;
|
||||||
|
exports.left = left;
|
||||||
|
exports.main = main;
|
||||||
|
exports.modifierPhases = modifierPhases;
|
||||||
|
exports.placements = placements;
|
||||||
|
exports.popper = popper;
|
||||||
|
exports.read = read;
|
||||||
|
exports.reference = reference;
|
||||||
|
exports.right = right;
|
||||||
|
exports.start = start;
|
||||||
|
exports.top = top;
|
||||||
|
exports.variationPlacements = variationPlacements;
|
||||||
|
exports.viewport = viewport;
|
||||||
|
exports.write = write;
|
||||||
|
//# sourceMappingURL=enums.js.map
|
||||||
3
node_modules/@popperjs/core/dist/cjs/enums.js.flow
generated
vendored
Normal file
3
node_modules/@popperjs/core/dist/cjs/enums.js.flow
generated
vendored
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
// @flow
|
||||||
|
|
||||||
|
export * from '../../lib/enums.js'
|
||||||
1
node_modules/@popperjs/core/dist/cjs/enums.js.map
generated
vendored
Normal file
1
node_modules/@popperjs/core/dist/cjs/enums.js.map
generated
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
{"version":3,"file":"enums.js","sources":["../../src/enums.js"],"sourcesContent":["// @flow\nexport const top: 'top' = 'top';\nexport const bottom: 'bottom' = 'bottom';\nexport const right: 'right' = 'right';\nexport const left: 'left' = 'left';\nexport const auto: 'auto' = 'auto';\nexport type BasePlacement =\n | typeof top\n | typeof bottom\n | typeof right\n | typeof left;\nexport const basePlacements: Array<BasePlacement> = [top, bottom, right, left];\n\nexport const start: 'start' = 'start';\nexport const end: 'end' = 'end';\nexport type Variation = typeof start | typeof end;\n\nexport const clippingParents: 'clippingParents' = 'clippingParents';\nexport const viewport: 'viewport' = 'viewport';\nexport type Boundary = Element | Array<Element> | typeof clippingParents;\nexport type RootBoundary = typeof viewport | 'document';\n\nexport const popper: 'popper' = 'popper';\nexport const reference: 'reference' = 'reference';\nexport type Context = typeof popper | typeof reference;\n\nexport type VariationPlacement =\n | 'top-start'\n | 'top-end'\n | 'bottom-start'\n | 'bottom-end'\n | 'right-start'\n | 'right-end'\n | 'left-start'\n | 'left-end';\nexport type AutoPlacement = 'auto' | 'auto-start' | 'auto-end';\nexport type ComputedPlacement = VariationPlacement | BasePlacement;\nexport type Placement = AutoPlacement | BasePlacement | VariationPlacement;\n\nexport const variationPlacements: Array<VariationPlacement> = basePlacements.reduce(\n (acc: Array<VariationPlacement>, placement: BasePlacement) =>\n acc.concat([(`${placement}-${start}`: any), (`${placement}-${end}`: any)]),\n []\n);\nexport const placements: Array<Placement> = [...basePlacements, auto].reduce(\n (\n acc: Array<Placement>,\n placement: BasePlacement | typeof auto\n ): Array<Placement> =>\n acc.concat([\n placement,\n (`${placement}-${start}`: any),\n (`${placement}-${end}`: any),\n ]),\n []\n);\n\n// modifiers that need to read the DOM\nexport const beforeRead: 'beforeRead' = 'beforeRead';\nexport const read: 'read' = 'read';\nexport const afterRead: 'afterRead' = 'afterRead';\n// pure-logic modifiers\nexport const beforeMain: 'beforeMain' = 'beforeMain';\nexport const main: 'main' = 'main';\nexport const afterMain: 'afterMain' = 'afterMain';\n// modifier with the purpose to write to the DOM (or write into a framework state)\nexport const beforeWrite: 'beforeWrite' = 'beforeWrite';\nexport const write: 'write' = 'write';\nexport const afterWrite: 'afterWrite' = 'afterWrite';\nexport const modifierPhases: Array<ModifierPhases> = [\n beforeRead,\n read,\n afterRead,\n beforeMain,\n main,\n afterMain,\n beforeWrite,\n write,\n afterWrite,\n];\n\nexport type ModifierPhases =\n | typeof beforeRead\n | typeof read\n | typeof afterRead\n | typeof beforeMain\n | typeof main\n | typeof afterMain\n | typeof beforeWrite\n | typeof write\n | typeof afterWrite;\n"],"names":["top","bottom","right","left","auto","basePlacements","start","end","clippingParents","viewport","popper","reference","variationPlacements","reduce","acc","placement","concat","placements","beforeRead","read","afterRead","beforeMain","main","afterMain","beforeWrite","write","afterWrite","modifierPhases"],"mappings":";;;;;;;;IACaA,GAAU,GAAG;IACbC,MAAgB,GAAG;IACnBC,KAAc,GAAG;IACjBC,IAAY,GAAG;IACfC,IAAY,GAAG;IAMfC,cAAoC,GAAG,CAACL,GAAD,EAAMC,MAAN,EAAcC,KAAd,EAAqBC,IAArB;IAEvCG,KAAc,GAAG;IACjBC,GAAU,GAAG;IAGbC,eAAkC,GAAG;IACrCC,QAAoB,GAAG;IAIvBC,MAAgB,GAAG;IACnBC,SAAsB,GAAG;IAgBzBC,mBAA8C,gBAAGP,cAAc,CAACQ,MAAf,CAC5D,UAACC,GAAD,EAAiCC,SAAjC;AAAA,SACED,GAAG,CAACE,MAAJ,CAAW,CAAKD,SAAL,SAAkBT,KAAlB,EAAqCS,SAArC,SAAkDR,GAAlD,CAAX,CADF;AAAA,CAD4D,EAG5D,EAH4D;IAKjDU,UAA4B,gBAAG,UAAIZ,cAAJ,GAAoBD,IAApB,GAA0BS,MAA1B,CAC1C,UACEC,GADF,EAEEC,SAFF;AAAA,SAIED,GAAG,CAACE,MAAJ,CAAW,CACTD,SADS,EAELA,SAFK,SAEQT,KAFR,EAGLS,SAHK,SAGQR,GAHR,CAAX,CAJF;AAAA,CAD0C,EAU1C,EAV0C;;IAc/BW,UAAwB,GAAG;IAC3BC,IAAY,GAAG;IACfC,SAAsB,GAAG;;IAEzBC,UAAwB,GAAG;IAC3BC,IAAY,GAAG;IACfC,SAAsB,GAAG;;IAEzBC,WAA0B,GAAG;IAC7BC,KAAc,GAAG;IACjBC,UAAwB,GAAG;IAC3BC,cAAqC,GAAG,CACnDT,UADmD,EAEnDC,IAFmD,EAGnDC,SAHmD,EAInDC,UAJmD,EAKnDC,IALmD,EAMnDC,SANmD,EAOnDC,WAPmD,EAQnDC,KARmD,EASnDC,UATmD;;;;;;;;;;;;;;;;;;;;;;;;;"}
|
||||||
939
node_modules/@popperjs/core/dist/cjs/popper-base.js
generated
vendored
Normal file
939
node_modules/@popperjs/core/dist/cjs/popper-base.js
generated
vendored
Normal file
@@ -0,0 +1,939 @@
|
|||||||
|
/**
|
||||||
|
* @popperjs/core v2.11.8 - MIT License
|
||||||
|
*/
|
||||||
|
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
Object.defineProperty(exports, '__esModule', { value: true });
|
||||||
|
|
||||||
|
function getWindow(node) {
|
||||||
|
if (node == null) {
|
||||||
|
return window;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (node.toString() !== '[object Window]') {
|
||||||
|
var ownerDocument = node.ownerDocument;
|
||||||
|
return ownerDocument ? ownerDocument.defaultView || window : window;
|
||||||
|
}
|
||||||
|
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
|
||||||
|
function isElement(node) {
|
||||||
|
var OwnElement = getWindow(node).Element;
|
||||||
|
return node instanceof OwnElement || node instanceof Element;
|
||||||
|
}
|
||||||
|
|
||||||
|
function isHTMLElement(node) {
|
||||||
|
var OwnElement = getWindow(node).HTMLElement;
|
||||||
|
return node instanceof OwnElement || node instanceof HTMLElement;
|
||||||
|
}
|
||||||
|
|
||||||
|
function isShadowRoot(node) {
|
||||||
|
// IE 11 has no ShadowRoot
|
||||||
|
if (typeof ShadowRoot === 'undefined') {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
var OwnElement = getWindow(node).ShadowRoot;
|
||||||
|
return node instanceof OwnElement || node instanceof ShadowRoot;
|
||||||
|
}
|
||||||
|
|
||||||
|
var max = Math.max;
|
||||||
|
var min = Math.min;
|
||||||
|
var round = Math.round;
|
||||||
|
|
||||||
|
function getUAString() {
|
||||||
|
var uaData = navigator.userAgentData;
|
||||||
|
|
||||||
|
if (uaData != null && uaData.brands && Array.isArray(uaData.brands)) {
|
||||||
|
return uaData.brands.map(function (item) {
|
||||||
|
return item.brand + "/" + item.version;
|
||||||
|
}).join(' ');
|
||||||
|
}
|
||||||
|
|
||||||
|
return navigator.userAgent;
|
||||||
|
}
|
||||||
|
|
||||||
|
function isLayoutViewport() {
|
||||||
|
return !/^((?!chrome|android).)*safari/i.test(getUAString());
|
||||||
|
}
|
||||||
|
|
||||||
|
function getBoundingClientRect(element, includeScale, isFixedStrategy) {
|
||||||
|
if (includeScale === void 0) {
|
||||||
|
includeScale = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isFixedStrategy === void 0) {
|
||||||
|
isFixedStrategy = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
var clientRect = element.getBoundingClientRect();
|
||||||
|
var scaleX = 1;
|
||||||
|
var scaleY = 1;
|
||||||
|
|
||||||
|
if (includeScale && isHTMLElement(element)) {
|
||||||
|
scaleX = element.offsetWidth > 0 ? round(clientRect.width) / element.offsetWidth || 1 : 1;
|
||||||
|
scaleY = element.offsetHeight > 0 ? round(clientRect.height) / element.offsetHeight || 1 : 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
var _ref = isElement(element) ? getWindow(element) : window,
|
||||||
|
visualViewport = _ref.visualViewport;
|
||||||
|
|
||||||
|
var addVisualOffsets = !isLayoutViewport() && isFixedStrategy;
|
||||||
|
var x = (clientRect.left + (addVisualOffsets && visualViewport ? visualViewport.offsetLeft : 0)) / scaleX;
|
||||||
|
var y = (clientRect.top + (addVisualOffsets && visualViewport ? visualViewport.offsetTop : 0)) / scaleY;
|
||||||
|
var width = clientRect.width / scaleX;
|
||||||
|
var height = clientRect.height / scaleY;
|
||||||
|
return {
|
||||||
|
width: width,
|
||||||
|
height: height,
|
||||||
|
top: y,
|
||||||
|
right: x + width,
|
||||||
|
bottom: y + height,
|
||||||
|
left: x,
|
||||||
|
x: x,
|
||||||
|
y: y
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function getWindowScroll(node) {
|
||||||
|
var win = getWindow(node);
|
||||||
|
var scrollLeft = win.pageXOffset;
|
||||||
|
var scrollTop = win.pageYOffset;
|
||||||
|
return {
|
||||||
|
scrollLeft: scrollLeft,
|
||||||
|
scrollTop: scrollTop
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function getHTMLElementScroll(element) {
|
||||||
|
return {
|
||||||
|
scrollLeft: element.scrollLeft,
|
||||||
|
scrollTop: element.scrollTop
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function getNodeScroll(node) {
|
||||||
|
if (node === getWindow(node) || !isHTMLElement(node)) {
|
||||||
|
return getWindowScroll(node);
|
||||||
|
} else {
|
||||||
|
return getHTMLElementScroll(node);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function getNodeName(element) {
|
||||||
|
return element ? (element.nodeName || '').toLowerCase() : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getDocumentElement(element) {
|
||||||
|
// $FlowFixMe[incompatible-return]: assume body is always available
|
||||||
|
return ((isElement(element) ? element.ownerDocument : // $FlowFixMe[prop-missing]
|
||||||
|
element.document) || window.document).documentElement;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getWindowScrollBarX(element) {
|
||||||
|
// If <html> has a CSS width greater than the viewport, then this will be
|
||||||
|
// incorrect for RTL.
|
||||||
|
// Popper 1 is broken in this case and never had a bug report so let's assume
|
||||||
|
// it's not an issue. I don't think anyone ever specifies width on <html>
|
||||||
|
// anyway.
|
||||||
|
// Browsers where the left scrollbar doesn't cause an issue report `0` for
|
||||||
|
// this (e.g. Edge 2019, IE11, Safari)
|
||||||
|
return getBoundingClientRect(getDocumentElement(element)).left + getWindowScroll(element).scrollLeft;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getComputedStyle(element) {
|
||||||
|
return getWindow(element).getComputedStyle(element);
|
||||||
|
}
|
||||||
|
|
||||||
|
function isScrollParent(element) {
|
||||||
|
// Firefox wants us to check `-x` and `-y` variations as well
|
||||||
|
var _getComputedStyle = getComputedStyle(element),
|
||||||
|
overflow = _getComputedStyle.overflow,
|
||||||
|
overflowX = _getComputedStyle.overflowX,
|
||||||
|
overflowY = _getComputedStyle.overflowY;
|
||||||
|
|
||||||
|
return /auto|scroll|overlay|hidden/.test(overflow + overflowY + overflowX);
|
||||||
|
}
|
||||||
|
|
||||||
|
function isElementScaled(element) {
|
||||||
|
var rect = element.getBoundingClientRect();
|
||||||
|
var scaleX = round(rect.width) / element.offsetWidth || 1;
|
||||||
|
var scaleY = round(rect.height) / element.offsetHeight || 1;
|
||||||
|
return scaleX !== 1 || scaleY !== 1;
|
||||||
|
} // Returns the composite rect of an element relative to its offsetParent.
|
||||||
|
// Composite means it takes into account transforms as well as layout.
|
||||||
|
|
||||||
|
|
||||||
|
function getCompositeRect(elementOrVirtualElement, offsetParent, isFixed) {
|
||||||
|
if (isFixed === void 0) {
|
||||||
|
isFixed = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
var isOffsetParentAnElement = isHTMLElement(offsetParent);
|
||||||
|
var offsetParentIsScaled = isHTMLElement(offsetParent) && isElementScaled(offsetParent);
|
||||||
|
var documentElement = getDocumentElement(offsetParent);
|
||||||
|
var rect = getBoundingClientRect(elementOrVirtualElement, offsetParentIsScaled, isFixed);
|
||||||
|
var scroll = {
|
||||||
|
scrollLeft: 0,
|
||||||
|
scrollTop: 0
|
||||||
|
};
|
||||||
|
var offsets = {
|
||||||
|
x: 0,
|
||||||
|
y: 0
|
||||||
|
};
|
||||||
|
|
||||||
|
if (isOffsetParentAnElement || !isOffsetParentAnElement && !isFixed) {
|
||||||
|
if (getNodeName(offsetParent) !== 'body' || // https://github.com/popperjs/popper-core/issues/1078
|
||||||
|
isScrollParent(documentElement)) {
|
||||||
|
scroll = getNodeScroll(offsetParent);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isHTMLElement(offsetParent)) {
|
||||||
|
offsets = getBoundingClientRect(offsetParent, true);
|
||||||
|
offsets.x += offsetParent.clientLeft;
|
||||||
|
offsets.y += offsetParent.clientTop;
|
||||||
|
} else if (documentElement) {
|
||||||
|
offsets.x = getWindowScrollBarX(documentElement);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
x: rect.left + scroll.scrollLeft - offsets.x,
|
||||||
|
y: rect.top + scroll.scrollTop - offsets.y,
|
||||||
|
width: rect.width,
|
||||||
|
height: rect.height
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// means it doesn't take into account transforms.
|
||||||
|
|
||||||
|
function getLayoutRect(element) {
|
||||||
|
var clientRect = getBoundingClientRect(element); // Use the clientRect sizes if it's not been transformed.
|
||||||
|
// Fixes https://github.com/popperjs/popper-core/issues/1223
|
||||||
|
|
||||||
|
var width = element.offsetWidth;
|
||||||
|
var height = element.offsetHeight;
|
||||||
|
|
||||||
|
if (Math.abs(clientRect.width - width) <= 1) {
|
||||||
|
width = clientRect.width;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Math.abs(clientRect.height - height) <= 1) {
|
||||||
|
height = clientRect.height;
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
x: element.offsetLeft,
|
||||||
|
y: element.offsetTop,
|
||||||
|
width: width,
|
||||||
|
height: height
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function getParentNode(element) {
|
||||||
|
if (getNodeName(element) === 'html') {
|
||||||
|
return element;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (// this is a quicker (but less type safe) way to save quite some bytes from the bundle
|
||||||
|
// $FlowFixMe[incompatible-return]
|
||||||
|
// $FlowFixMe[prop-missing]
|
||||||
|
element.assignedSlot || // step into the shadow DOM of the parent of a slotted node
|
||||||
|
element.parentNode || ( // DOM Element detected
|
||||||
|
isShadowRoot(element) ? element.host : null) || // ShadowRoot detected
|
||||||
|
// $FlowFixMe[incompatible-call]: HTMLElement is a Node
|
||||||
|
getDocumentElement(element) // fallback
|
||||||
|
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function getScrollParent(node) {
|
||||||
|
if (['html', 'body', '#document'].indexOf(getNodeName(node)) >= 0) {
|
||||||
|
// $FlowFixMe[incompatible-return]: assume body is always available
|
||||||
|
return node.ownerDocument.body;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isHTMLElement(node) && isScrollParent(node)) {
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
|
||||||
|
return getScrollParent(getParentNode(node));
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
given a DOM element, return the list of all scroll parents, up the list of ancesors
|
||||||
|
until we get to the top window object. This list is what we attach scroll listeners
|
||||||
|
to, because if any of these parent elements scroll, we'll need to re-calculate the
|
||||||
|
reference element's position.
|
||||||
|
*/
|
||||||
|
|
||||||
|
function listScrollParents(element, list) {
|
||||||
|
var _element$ownerDocumen;
|
||||||
|
|
||||||
|
if (list === void 0) {
|
||||||
|
list = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
var scrollParent = getScrollParent(element);
|
||||||
|
var isBody = scrollParent === ((_element$ownerDocumen = element.ownerDocument) == null ? void 0 : _element$ownerDocumen.body);
|
||||||
|
var win = getWindow(scrollParent);
|
||||||
|
var target = isBody ? [win].concat(win.visualViewport || [], isScrollParent(scrollParent) ? scrollParent : []) : scrollParent;
|
||||||
|
var updatedList = list.concat(target);
|
||||||
|
return isBody ? updatedList : // $FlowFixMe[incompatible-call]: isBody tells us target will be an HTMLElement here
|
||||||
|
updatedList.concat(listScrollParents(getParentNode(target)));
|
||||||
|
}
|
||||||
|
|
||||||
|
function isTableElement(element) {
|
||||||
|
return ['table', 'td', 'th'].indexOf(getNodeName(element)) >= 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getTrueOffsetParent(element) {
|
||||||
|
if (!isHTMLElement(element) || // https://github.com/popperjs/popper-core/issues/837
|
||||||
|
getComputedStyle(element).position === 'fixed') {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return element.offsetParent;
|
||||||
|
} // `.offsetParent` reports `null` for fixed elements, while absolute elements
|
||||||
|
// return the containing block
|
||||||
|
|
||||||
|
|
||||||
|
function getContainingBlock(element) {
|
||||||
|
var isFirefox = /firefox/i.test(getUAString());
|
||||||
|
var isIE = /Trident/i.test(getUAString());
|
||||||
|
|
||||||
|
if (isIE && isHTMLElement(element)) {
|
||||||
|
// In IE 9, 10 and 11 fixed elements containing block is always established by the viewport
|
||||||
|
var elementCss = getComputedStyle(element);
|
||||||
|
|
||||||
|
if (elementCss.position === 'fixed') {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var currentNode = getParentNode(element);
|
||||||
|
|
||||||
|
if (isShadowRoot(currentNode)) {
|
||||||
|
currentNode = currentNode.host;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (isHTMLElement(currentNode) && ['html', 'body'].indexOf(getNodeName(currentNode)) < 0) {
|
||||||
|
var css = getComputedStyle(currentNode); // This is non-exhaustive but covers the most common CSS properties that
|
||||||
|
// create a containing block.
|
||||||
|
// https://developer.mozilla.org/en-US/docs/Web/CSS/Containing_block#identifying_the_containing_block
|
||||||
|
|
||||||
|
if (css.transform !== 'none' || css.perspective !== 'none' || css.contain === 'paint' || ['transform', 'perspective'].indexOf(css.willChange) !== -1 || isFirefox && css.willChange === 'filter' || isFirefox && css.filter && css.filter !== 'none') {
|
||||||
|
return currentNode;
|
||||||
|
} else {
|
||||||
|
currentNode = currentNode.parentNode;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
} // Gets the closest ancestor positioned element. Handles some edge cases,
|
||||||
|
// such as table ancestors and cross browser bugs.
|
||||||
|
|
||||||
|
|
||||||
|
function getOffsetParent(element) {
|
||||||
|
var window = getWindow(element);
|
||||||
|
var offsetParent = getTrueOffsetParent(element);
|
||||||
|
|
||||||
|
while (offsetParent && isTableElement(offsetParent) && getComputedStyle(offsetParent).position === 'static') {
|
||||||
|
offsetParent = getTrueOffsetParent(offsetParent);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (offsetParent && (getNodeName(offsetParent) === 'html' || getNodeName(offsetParent) === 'body' && getComputedStyle(offsetParent).position === 'static')) {
|
||||||
|
return window;
|
||||||
|
}
|
||||||
|
|
||||||
|
return offsetParent || getContainingBlock(element) || window;
|
||||||
|
}
|
||||||
|
|
||||||
|
var top = 'top';
|
||||||
|
var bottom = 'bottom';
|
||||||
|
var right = 'right';
|
||||||
|
var left = 'left';
|
||||||
|
var basePlacements = [top, bottom, right, left];
|
||||||
|
var start = 'start';
|
||||||
|
var end = 'end';
|
||||||
|
var clippingParents = 'clippingParents';
|
||||||
|
var viewport = 'viewport';
|
||||||
|
var popper = 'popper';
|
||||||
|
var reference = 'reference';
|
||||||
|
|
||||||
|
var beforeRead = 'beforeRead';
|
||||||
|
var read = 'read';
|
||||||
|
var afterRead = 'afterRead'; // pure-logic modifiers
|
||||||
|
|
||||||
|
var beforeMain = 'beforeMain';
|
||||||
|
var main = 'main';
|
||||||
|
var afterMain = 'afterMain'; // modifier with the purpose to write to the DOM (or write into a framework state)
|
||||||
|
|
||||||
|
var beforeWrite = 'beforeWrite';
|
||||||
|
var write = 'write';
|
||||||
|
var afterWrite = 'afterWrite';
|
||||||
|
var modifierPhases = [beforeRead, read, afterRead, beforeMain, main, afterMain, beforeWrite, write, afterWrite];
|
||||||
|
|
||||||
|
function order(modifiers) {
|
||||||
|
var map = new Map();
|
||||||
|
var visited = new Set();
|
||||||
|
var result = [];
|
||||||
|
modifiers.forEach(function (modifier) {
|
||||||
|
map.set(modifier.name, modifier);
|
||||||
|
}); // On visiting object, check for its dependencies and visit them recursively
|
||||||
|
|
||||||
|
function sort(modifier) {
|
||||||
|
visited.add(modifier.name);
|
||||||
|
var requires = [].concat(modifier.requires || [], modifier.requiresIfExists || []);
|
||||||
|
requires.forEach(function (dep) {
|
||||||
|
if (!visited.has(dep)) {
|
||||||
|
var depModifier = map.get(dep);
|
||||||
|
|
||||||
|
if (depModifier) {
|
||||||
|
sort(depModifier);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
result.push(modifier);
|
||||||
|
}
|
||||||
|
|
||||||
|
modifiers.forEach(function (modifier) {
|
||||||
|
if (!visited.has(modifier.name)) {
|
||||||
|
// check for visited object
|
||||||
|
sort(modifier);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
function orderModifiers(modifiers) {
|
||||||
|
// order based on dependencies
|
||||||
|
var orderedModifiers = order(modifiers); // order based on phase
|
||||||
|
|
||||||
|
return modifierPhases.reduce(function (acc, phase) {
|
||||||
|
return acc.concat(orderedModifiers.filter(function (modifier) {
|
||||||
|
return modifier.phase === phase;
|
||||||
|
}));
|
||||||
|
}, []);
|
||||||
|
}
|
||||||
|
|
||||||
|
function debounce(fn) {
|
||||||
|
var pending;
|
||||||
|
return function () {
|
||||||
|
if (!pending) {
|
||||||
|
pending = new Promise(function (resolve) {
|
||||||
|
Promise.resolve().then(function () {
|
||||||
|
pending = undefined;
|
||||||
|
resolve(fn());
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return pending;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function mergeByName(modifiers) {
|
||||||
|
var merged = modifiers.reduce(function (merged, current) {
|
||||||
|
var existing = merged[current.name];
|
||||||
|
merged[current.name] = existing ? Object.assign({}, existing, current, {
|
||||||
|
options: Object.assign({}, existing.options, current.options),
|
||||||
|
data: Object.assign({}, existing.data, current.data)
|
||||||
|
}) : current;
|
||||||
|
return merged;
|
||||||
|
}, {}); // IE11 does not support Object.values
|
||||||
|
|
||||||
|
return Object.keys(merged).map(function (key) {
|
||||||
|
return merged[key];
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function getViewportRect(element, strategy) {
|
||||||
|
var win = getWindow(element);
|
||||||
|
var html = getDocumentElement(element);
|
||||||
|
var visualViewport = win.visualViewport;
|
||||||
|
var width = html.clientWidth;
|
||||||
|
var height = html.clientHeight;
|
||||||
|
var x = 0;
|
||||||
|
var y = 0;
|
||||||
|
|
||||||
|
if (visualViewport) {
|
||||||
|
width = visualViewport.width;
|
||||||
|
height = visualViewport.height;
|
||||||
|
var layoutViewport = isLayoutViewport();
|
||||||
|
|
||||||
|
if (layoutViewport || !layoutViewport && strategy === 'fixed') {
|
||||||
|
x = visualViewport.offsetLeft;
|
||||||
|
y = visualViewport.offsetTop;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
width: width,
|
||||||
|
height: height,
|
||||||
|
x: x + getWindowScrollBarX(element),
|
||||||
|
y: y
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// of the `<html>` and `<body>` rect bounds if horizontally scrollable
|
||||||
|
|
||||||
|
function getDocumentRect(element) {
|
||||||
|
var _element$ownerDocumen;
|
||||||
|
|
||||||
|
var html = getDocumentElement(element);
|
||||||
|
var winScroll = getWindowScroll(element);
|
||||||
|
var body = (_element$ownerDocumen = element.ownerDocument) == null ? void 0 : _element$ownerDocumen.body;
|
||||||
|
var width = max(html.scrollWidth, html.clientWidth, body ? body.scrollWidth : 0, body ? body.clientWidth : 0);
|
||||||
|
var height = max(html.scrollHeight, html.clientHeight, body ? body.scrollHeight : 0, body ? body.clientHeight : 0);
|
||||||
|
var x = -winScroll.scrollLeft + getWindowScrollBarX(element);
|
||||||
|
var y = -winScroll.scrollTop;
|
||||||
|
|
||||||
|
if (getComputedStyle(body || html).direction === 'rtl') {
|
||||||
|
x += max(html.clientWidth, body ? body.clientWidth : 0) - width;
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
width: width,
|
||||||
|
height: height,
|
||||||
|
x: x,
|
||||||
|
y: y
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function contains(parent, child) {
|
||||||
|
var rootNode = child.getRootNode && child.getRootNode(); // First, attempt with faster native method
|
||||||
|
|
||||||
|
if (parent.contains(child)) {
|
||||||
|
return true;
|
||||||
|
} // then fallback to custom implementation with Shadow DOM support
|
||||||
|
else if (rootNode && isShadowRoot(rootNode)) {
|
||||||
|
var next = child;
|
||||||
|
|
||||||
|
do {
|
||||||
|
if (next && parent.isSameNode(next)) {
|
||||||
|
return true;
|
||||||
|
} // $FlowFixMe[prop-missing]: need a better way to handle this...
|
||||||
|
|
||||||
|
|
||||||
|
next = next.parentNode || next.host;
|
||||||
|
} while (next);
|
||||||
|
} // Give up, the result is false
|
||||||
|
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
function rectToClientRect(rect) {
|
||||||
|
return Object.assign({}, rect, {
|
||||||
|
left: rect.x,
|
||||||
|
top: rect.y,
|
||||||
|
right: rect.x + rect.width,
|
||||||
|
bottom: rect.y + rect.height
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function getInnerBoundingClientRect(element, strategy) {
|
||||||
|
var rect = getBoundingClientRect(element, false, strategy === 'fixed');
|
||||||
|
rect.top = rect.top + element.clientTop;
|
||||||
|
rect.left = rect.left + element.clientLeft;
|
||||||
|
rect.bottom = rect.top + element.clientHeight;
|
||||||
|
rect.right = rect.left + element.clientWidth;
|
||||||
|
rect.width = element.clientWidth;
|
||||||
|
rect.height = element.clientHeight;
|
||||||
|
rect.x = rect.left;
|
||||||
|
rect.y = rect.top;
|
||||||
|
return rect;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getClientRectFromMixedType(element, clippingParent, strategy) {
|
||||||
|
return clippingParent === viewport ? rectToClientRect(getViewportRect(element, strategy)) : isElement(clippingParent) ? getInnerBoundingClientRect(clippingParent, strategy) : rectToClientRect(getDocumentRect(getDocumentElement(element)));
|
||||||
|
} // A "clipping parent" is an overflowable container with the characteristic of
|
||||||
|
// clipping (or hiding) overflowing elements with a position different from
|
||||||
|
// `initial`
|
||||||
|
|
||||||
|
|
||||||
|
function getClippingParents(element) {
|
||||||
|
var clippingParents = listScrollParents(getParentNode(element));
|
||||||
|
var canEscapeClipping = ['absolute', 'fixed'].indexOf(getComputedStyle(element).position) >= 0;
|
||||||
|
var clipperElement = canEscapeClipping && isHTMLElement(element) ? getOffsetParent(element) : element;
|
||||||
|
|
||||||
|
if (!isElement(clipperElement)) {
|
||||||
|
return [];
|
||||||
|
} // $FlowFixMe[incompatible-return]: https://github.com/facebook/flow/issues/1414
|
||||||
|
|
||||||
|
|
||||||
|
return clippingParents.filter(function (clippingParent) {
|
||||||
|
return isElement(clippingParent) && contains(clippingParent, clipperElement) && getNodeName(clippingParent) !== 'body';
|
||||||
|
});
|
||||||
|
} // Gets the maximum area that the element is visible in due to any number of
|
||||||
|
// clipping parents
|
||||||
|
|
||||||
|
|
||||||
|
function getClippingRect(element, boundary, rootBoundary, strategy) {
|
||||||
|
var mainClippingParents = boundary === 'clippingParents' ? getClippingParents(element) : [].concat(boundary);
|
||||||
|
var clippingParents = [].concat(mainClippingParents, [rootBoundary]);
|
||||||
|
var firstClippingParent = clippingParents[0];
|
||||||
|
var clippingRect = clippingParents.reduce(function (accRect, clippingParent) {
|
||||||
|
var rect = getClientRectFromMixedType(element, clippingParent, strategy);
|
||||||
|
accRect.top = max(rect.top, accRect.top);
|
||||||
|
accRect.right = min(rect.right, accRect.right);
|
||||||
|
accRect.bottom = min(rect.bottom, accRect.bottom);
|
||||||
|
accRect.left = max(rect.left, accRect.left);
|
||||||
|
return accRect;
|
||||||
|
}, getClientRectFromMixedType(element, firstClippingParent, strategy));
|
||||||
|
clippingRect.width = clippingRect.right - clippingRect.left;
|
||||||
|
clippingRect.height = clippingRect.bottom - clippingRect.top;
|
||||||
|
clippingRect.x = clippingRect.left;
|
||||||
|
clippingRect.y = clippingRect.top;
|
||||||
|
return clippingRect;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getBasePlacement(placement) {
|
||||||
|
return placement.split('-')[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
function getVariation(placement) {
|
||||||
|
return placement.split('-')[1];
|
||||||
|
}
|
||||||
|
|
||||||
|
function getMainAxisFromPlacement(placement) {
|
||||||
|
return ['top', 'bottom'].indexOf(placement) >= 0 ? 'x' : 'y';
|
||||||
|
}
|
||||||
|
|
||||||
|
function computeOffsets(_ref) {
|
||||||
|
var reference = _ref.reference,
|
||||||
|
element = _ref.element,
|
||||||
|
placement = _ref.placement;
|
||||||
|
var basePlacement = placement ? getBasePlacement(placement) : null;
|
||||||
|
var variation = placement ? getVariation(placement) : null;
|
||||||
|
var commonX = reference.x + reference.width / 2 - element.width / 2;
|
||||||
|
var commonY = reference.y + reference.height / 2 - element.height / 2;
|
||||||
|
var offsets;
|
||||||
|
|
||||||
|
switch (basePlacement) {
|
||||||
|
case top:
|
||||||
|
offsets = {
|
||||||
|
x: commonX,
|
||||||
|
y: reference.y - element.height
|
||||||
|
};
|
||||||
|
break;
|
||||||
|
|
||||||
|
case bottom:
|
||||||
|
offsets = {
|
||||||
|
x: commonX,
|
||||||
|
y: reference.y + reference.height
|
||||||
|
};
|
||||||
|
break;
|
||||||
|
|
||||||
|
case right:
|
||||||
|
offsets = {
|
||||||
|
x: reference.x + reference.width,
|
||||||
|
y: commonY
|
||||||
|
};
|
||||||
|
break;
|
||||||
|
|
||||||
|
case left:
|
||||||
|
offsets = {
|
||||||
|
x: reference.x - element.width,
|
||||||
|
y: commonY
|
||||||
|
};
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
offsets = {
|
||||||
|
x: reference.x,
|
||||||
|
y: reference.y
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
var mainAxis = basePlacement ? getMainAxisFromPlacement(basePlacement) : null;
|
||||||
|
|
||||||
|
if (mainAxis != null) {
|
||||||
|
var len = mainAxis === 'y' ? 'height' : 'width';
|
||||||
|
|
||||||
|
switch (variation) {
|
||||||
|
case start:
|
||||||
|
offsets[mainAxis] = offsets[mainAxis] - (reference[len] / 2 - element[len] / 2);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case end:
|
||||||
|
offsets[mainAxis] = offsets[mainAxis] + (reference[len] / 2 - element[len] / 2);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return offsets;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getFreshSideObject() {
|
||||||
|
return {
|
||||||
|
top: 0,
|
||||||
|
right: 0,
|
||||||
|
bottom: 0,
|
||||||
|
left: 0
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function mergePaddingObject(paddingObject) {
|
||||||
|
return Object.assign({}, getFreshSideObject(), paddingObject);
|
||||||
|
}
|
||||||
|
|
||||||
|
function expandToHashMap(value, keys) {
|
||||||
|
return keys.reduce(function (hashMap, key) {
|
||||||
|
hashMap[key] = value;
|
||||||
|
return hashMap;
|
||||||
|
}, {});
|
||||||
|
}
|
||||||
|
|
||||||
|
function detectOverflow(state, options) {
|
||||||
|
if (options === void 0) {
|
||||||
|
options = {};
|
||||||
|
}
|
||||||
|
|
||||||
|
var _options = options,
|
||||||
|
_options$placement = _options.placement,
|
||||||
|
placement = _options$placement === void 0 ? state.placement : _options$placement,
|
||||||
|
_options$strategy = _options.strategy,
|
||||||
|
strategy = _options$strategy === void 0 ? state.strategy : _options$strategy,
|
||||||
|
_options$boundary = _options.boundary,
|
||||||
|
boundary = _options$boundary === void 0 ? clippingParents : _options$boundary,
|
||||||
|
_options$rootBoundary = _options.rootBoundary,
|
||||||
|
rootBoundary = _options$rootBoundary === void 0 ? viewport : _options$rootBoundary,
|
||||||
|
_options$elementConte = _options.elementContext,
|
||||||
|
elementContext = _options$elementConte === void 0 ? popper : _options$elementConte,
|
||||||
|
_options$altBoundary = _options.altBoundary,
|
||||||
|
altBoundary = _options$altBoundary === void 0 ? false : _options$altBoundary,
|
||||||
|
_options$padding = _options.padding,
|
||||||
|
padding = _options$padding === void 0 ? 0 : _options$padding;
|
||||||
|
var paddingObject = mergePaddingObject(typeof padding !== 'number' ? padding : expandToHashMap(padding, basePlacements));
|
||||||
|
var altContext = elementContext === popper ? reference : popper;
|
||||||
|
var popperRect = state.rects.popper;
|
||||||
|
var element = state.elements[altBoundary ? altContext : elementContext];
|
||||||
|
var clippingClientRect = getClippingRect(isElement(element) ? element : element.contextElement || getDocumentElement(state.elements.popper), boundary, rootBoundary, strategy);
|
||||||
|
var referenceClientRect = getBoundingClientRect(state.elements.reference);
|
||||||
|
var popperOffsets = computeOffsets({
|
||||||
|
reference: referenceClientRect,
|
||||||
|
element: popperRect,
|
||||||
|
strategy: 'absolute',
|
||||||
|
placement: placement
|
||||||
|
});
|
||||||
|
var popperClientRect = rectToClientRect(Object.assign({}, popperRect, popperOffsets));
|
||||||
|
var elementClientRect = elementContext === popper ? popperClientRect : referenceClientRect; // positive = overflowing the clipping rect
|
||||||
|
// 0 or negative = within the clipping rect
|
||||||
|
|
||||||
|
var overflowOffsets = {
|
||||||
|
top: clippingClientRect.top - elementClientRect.top + paddingObject.top,
|
||||||
|
bottom: elementClientRect.bottom - clippingClientRect.bottom + paddingObject.bottom,
|
||||||
|
left: clippingClientRect.left - elementClientRect.left + paddingObject.left,
|
||||||
|
right: elementClientRect.right - clippingClientRect.right + paddingObject.right
|
||||||
|
};
|
||||||
|
var offsetData = state.modifiersData.offset; // Offsets can be applied only to the popper element
|
||||||
|
|
||||||
|
if (elementContext === popper && offsetData) {
|
||||||
|
var offset = offsetData[placement];
|
||||||
|
Object.keys(overflowOffsets).forEach(function (key) {
|
||||||
|
var multiply = [right, bottom].indexOf(key) >= 0 ? 1 : -1;
|
||||||
|
var axis = [top, bottom].indexOf(key) >= 0 ? 'y' : 'x';
|
||||||
|
overflowOffsets[key] += offset[axis] * multiply;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return overflowOffsets;
|
||||||
|
}
|
||||||
|
|
||||||
|
var DEFAULT_OPTIONS = {
|
||||||
|
placement: 'bottom',
|
||||||
|
modifiers: [],
|
||||||
|
strategy: 'absolute'
|
||||||
|
};
|
||||||
|
|
||||||
|
function areValidElements() {
|
||||||
|
for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
|
||||||
|
args[_key] = arguments[_key];
|
||||||
|
}
|
||||||
|
|
||||||
|
return !args.some(function (element) {
|
||||||
|
return !(element && typeof element.getBoundingClientRect === 'function');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function popperGenerator(generatorOptions) {
|
||||||
|
if (generatorOptions === void 0) {
|
||||||
|
generatorOptions = {};
|
||||||
|
}
|
||||||
|
|
||||||
|
var _generatorOptions = generatorOptions,
|
||||||
|
_generatorOptions$def = _generatorOptions.defaultModifiers,
|
||||||
|
defaultModifiers = _generatorOptions$def === void 0 ? [] : _generatorOptions$def,
|
||||||
|
_generatorOptions$def2 = _generatorOptions.defaultOptions,
|
||||||
|
defaultOptions = _generatorOptions$def2 === void 0 ? DEFAULT_OPTIONS : _generatorOptions$def2;
|
||||||
|
return function createPopper(reference, popper, options) {
|
||||||
|
if (options === void 0) {
|
||||||
|
options = defaultOptions;
|
||||||
|
}
|
||||||
|
|
||||||
|
var state = {
|
||||||
|
placement: 'bottom',
|
||||||
|
orderedModifiers: [],
|
||||||
|
options: Object.assign({}, DEFAULT_OPTIONS, defaultOptions),
|
||||||
|
modifiersData: {},
|
||||||
|
elements: {
|
||||||
|
reference: reference,
|
||||||
|
popper: popper
|
||||||
|
},
|
||||||
|
attributes: {},
|
||||||
|
styles: {}
|
||||||
|
};
|
||||||
|
var effectCleanupFns = [];
|
||||||
|
var isDestroyed = false;
|
||||||
|
var instance = {
|
||||||
|
state: state,
|
||||||
|
setOptions: function setOptions(setOptionsAction) {
|
||||||
|
var options = typeof setOptionsAction === 'function' ? setOptionsAction(state.options) : setOptionsAction;
|
||||||
|
cleanupModifierEffects();
|
||||||
|
state.options = Object.assign({}, defaultOptions, state.options, options);
|
||||||
|
state.scrollParents = {
|
||||||
|
reference: isElement(reference) ? listScrollParents(reference) : reference.contextElement ? listScrollParents(reference.contextElement) : [],
|
||||||
|
popper: listScrollParents(popper)
|
||||||
|
}; // Orders the modifiers based on their dependencies and `phase`
|
||||||
|
// properties
|
||||||
|
|
||||||
|
var orderedModifiers = orderModifiers(mergeByName([].concat(defaultModifiers, state.options.modifiers))); // Strip out disabled modifiers
|
||||||
|
|
||||||
|
state.orderedModifiers = orderedModifiers.filter(function (m) {
|
||||||
|
return m.enabled;
|
||||||
|
});
|
||||||
|
runModifierEffects();
|
||||||
|
return instance.update();
|
||||||
|
},
|
||||||
|
// Sync update – it will always be executed, even if not necessary. This
|
||||||
|
// is useful for low frequency updates where sync behavior simplifies the
|
||||||
|
// logic.
|
||||||
|
// For high frequency updates (e.g. `resize` and `scroll` events), always
|
||||||
|
// prefer the async Popper#update method
|
||||||
|
forceUpdate: function forceUpdate() {
|
||||||
|
if (isDestroyed) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var _state$elements = state.elements,
|
||||||
|
reference = _state$elements.reference,
|
||||||
|
popper = _state$elements.popper; // Don't proceed if `reference` or `popper` are not valid elements
|
||||||
|
// anymore
|
||||||
|
|
||||||
|
if (!areValidElements(reference, popper)) {
|
||||||
|
return;
|
||||||
|
} // Store the reference and popper rects to be read by modifiers
|
||||||
|
|
||||||
|
|
||||||
|
state.rects = {
|
||||||
|
reference: getCompositeRect(reference, getOffsetParent(popper), state.options.strategy === 'fixed'),
|
||||||
|
popper: getLayoutRect(popper)
|
||||||
|
}; // Modifiers have the ability to reset the current update cycle. The
|
||||||
|
// most common use case for this is the `flip` modifier changing the
|
||||||
|
// placement, which then needs to re-run all the modifiers, because the
|
||||||
|
// logic was previously ran for the previous placement and is therefore
|
||||||
|
// stale/incorrect
|
||||||
|
|
||||||
|
state.reset = false;
|
||||||
|
state.placement = state.options.placement; // On each update cycle, the `modifiersData` property for each modifier
|
||||||
|
// is filled with the initial data specified by the modifier. This means
|
||||||
|
// it doesn't persist and is fresh on each update.
|
||||||
|
// To ensure persistent data, use `${name}#persistent`
|
||||||
|
|
||||||
|
state.orderedModifiers.forEach(function (modifier) {
|
||||||
|
return state.modifiersData[modifier.name] = Object.assign({}, modifier.data);
|
||||||
|
});
|
||||||
|
|
||||||
|
for (var index = 0; index < state.orderedModifiers.length; index++) {
|
||||||
|
if (state.reset === true) {
|
||||||
|
state.reset = false;
|
||||||
|
index = -1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
var _state$orderedModifie = state.orderedModifiers[index],
|
||||||
|
fn = _state$orderedModifie.fn,
|
||||||
|
_state$orderedModifie2 = _state$orderedModifie.options,
|
||||||
|
_options = _state$orderedModifie2 === void 0 ? {} : _state$orderedModifie2,
|
||||||
|
name = _state$orderedModifie.name;
|
||||||
|
|
||||||
|
if (typeof fn === 'function') {
|
||||||
|
state = fn({
|
||||||
|
state: state,
|
||||||
|
options: _options,
|
||||||
|
name: name,
|
||||||
|
instance: instance
|
||||||
|
}) || state;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// Async and optimistically optimized update – it will not be executed if
|
||||||
|
// not necessary (debounced to run at most once-per-tick)
|
||||||
|
update: debounce(function () {
|
||||||
|
return new Promise(function (resolve) {
|
||||||
|
instance.forceUpdate();
|
||||||
|
resolve(state);
|
||||||
|
});
|
||||||
|
}),
|
||||||
|
destroy: function destroy() {
|
||||||
|
cleanupModifierEffects();
|
||||||
|
isDestroyed = true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
if (!areValidElements(reference, popper)) {
|
||||||
|
return instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
instance.setOptions(options).then(function (state) {
|
||||||
|
if (!isDestroyed && options.onFirstUpdate) {
|
||||||
|
options.onFirstUpdate(state);
|
||||||
|
}
|
||||||
|
}); // Modifiers have the ability to execute arbitrary code before the first
|
||||||
|
// update cycle runs. They will be executed in the same order as the update
|
||||||
|
// cycle. This is useful when a modifier adds some persistent data that
|
||||||
|
// other modifiers need to use, but the modifier is run after the dependent
|
||||||
|
// one.
|
||||||
|
|
||||||
|
function runModifierEffects() {
|
||||||
|
state.orderedModifiers.forEach(function (_ref) {
|
||||||
|
var name = _ref.name,
|
||||||
|
_ref$options = _ref.options,
|
||||||
|
options = _ref$options === void 0 ? {} : _ref$options,
|
||||||
|
effect = _ref.effect;
|
||||||
|
|
||||||
|
if (typeof effect === 'function') {
|
||||||
|
var cleanupFn = effect({
|
||||||
|
state: state,
|
||||||
|
name: name,
|
||||||
|
instance: instance,
|
||||||
|
options: options
|
||||||
|
});
|
||||||
|
|
||||||
|
var noopFn = function noopFn() {};
|
||||||
|
|
||||||
|
effectCleanupFns.push(cleanupFn || noopFn);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function cleanupModifierEffects() {
|
||||||
|
effectCleanupFns.forEach(function (fn) {
|
||||||
|
return fn();
|
||||||
|
});
|
||||||
|
effectCleanupFns = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
return instance;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
var createPopper = /*#__PURE__*/popperGenerator(); // eslint-disable-next-line import/no-unused-modules
|
||||||
|
|
||||||
|
exports.createPopper = createPopper;
|
||||||
|
exports.detectOverflow = detectOverflow;
|
||||||
|
exports.popperGenerator = popperGenerator;
|
||||||
|
//# sourceMappingURL=popper-base.js.map
|
||||||
3
node_modules/@popperjs/core/dist/cjs/popper-base.js.flow
generated
vendored
Normal file
3
node_modules/@popperjs/core/dist/cjs/popper-base.js.flow
generated
vendored
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
// @flow
|
||||||
|
|
||||||
|
export * from '../../lib/popper-base.js'
|
||||||
1
node_modules/@popperjs/core/dist/cjs/popper-base.js.map
generated
vendored
Normal file
1
node_modules/@popperjs/core/dist/cjs/popper-base.js.map
generated
vendored
Normal file
File diff suppressed because one or more lines are too long
1260
node_modules/@popperjs/core/dist/cjs/popper-lite.js
generated
vendored
Normal file
1260
node_modules/@popperjs/core/dist/cjs/popper-lite.js
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
3
node_modules/@popperjs/core/dist/cjs/popper-lite.js.flow
generated
vendored
Normal file
3
node_modules/@popperjs/core/dist/cjs/popper-lite.js.flow
generated
vendored
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
// @flow
|
||||||
|
|
||||||
|
export * from '../../lib/popper-lite.js'
|
||||||
1
node_modules/@popperjs/core/dist/cjs/popper-lite.js.map
generated
vendored
Normal file
1
node_modules/@popperjs/core/dist/cjs/popper-lite.js.map
generated
vendored
Normal file
File diff suppressed because one or more lines are too long
1819
node_modules/@popperjs/core/dist/cjs/popper.js
generated
vendored
Normal file
1819
node_modules/@popperjs/core/dist/cjs/popper.js
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
3
node_modules/@popperjs/core/dist/cjs/popper.js.flow
generated
vendored
Normal file
3
node_modules/@popperjs/core/dist/cjs/popper.js.flow
generated
vendored
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
// @flow
|
||||||
|
|
||||||
|
export * from '../../lib/popper.js'
|
||||||
1
node_modules/@popperjs/core/dist/cjs/popper.js.map
generated
vendored
Normal file
1
node_modules/@popperjs/core/dist/cjs/popper.js.map
generated
vendored
Normal file
File diff suppressed because one or more lines are too long
199
node_modules/@popperjs/core/dist/esm/createPopper.js
generated
vendored
Normal file
199
node_modules/@popperjs/core/dist/esm/createPopper.js
generated
vendored
Normal file
@@ -0,0 +1,199 @@
|
|||||||
|
import getCompositeRect from "./dom-utils/getCompositeRect.js";
|
||||||
|
import getLayoutRect from "./dom-utils/getLayoutRect.js";
|
||||||
|
import listScrollParents from "./dom-utils/listScrollParents.js";
|
||||||
|
import getOffsetParent from "./dom-utils/getOffsetParent.js";
|
||||||
|
import orderModifiers from "./utils/orderModifiers.js";
|
||||||
|
import debounce from "./utils/debounce.js";
|
||||||
|
import mergeByName from "./utils/mergeByName.js";
|
||||||
|
import detectOverflow from "./utils/detectOverflow.js";
|
||||||
|
import { isElement } from "./dom-utils/instanceOf.js";
|
||||||
|
var DEFAULT_OPTIONS = {
|
||||||
|
placement: 'bottom',
|
||||||
|
modifiers: [],
|
||||||
|
strategy: 'absolute'
|
||||||
|
};
|
||||||
|
|
||||||
|
function areValidElements() {
|
||||||
|
for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
|
||||||
|
args[_key] = arguments[_key];
|
||||||
|
}
|
||||||
|
|
||||||
|
return !args.some(function (element) {
|
||||||
|
return !(element && typeof element.getBoundingClientRect === 'function');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export function popperGenerator(generatorOptions) {
|
||||||
|
if (generatorOptions === void 0) {
|
||||||
|
generatorOptions = {};
|
||||||
|
}
|
||||||
|
|
||||||
|
var _generatorOptions = generatorOptions,
|
||||||
|
_generatorOptions$def = _generatorOptions.defaultModifiers,
|
||||||
|
defaultModifiers = _generatorOptions$def === void 0 ? [] : _generatorOptions$def,
|
||||||
|
_generatorOptions$def2 = _generatorOptions.defaultOptions,
|
||||||
|
defaultOptions = _generatorOptions$def2 === void 0 ? DEFAULT_OPTIONS : _generatorOptions$def2;
|
||||||
|
return function createPopper(reference, popper, options) {
|
||||||
|
if (options === void 0) {
|
||||||
|
options = defaultOptions;
|
||||||
|
}
|
||||||
|
|
||||||
|
var state = {
|
||||||
|
placement: 'bottom',
|
||||||
|
orderedModifiers: [],
|
||||||
|
options: Object.assign({}, DEFAULT_OPTIONS, defaultOptions),
|
||||||
|
modifiersData: {},
|
||||||
|
elements: {
|
||||||
|
reference: reference,
|
||||||
|
popper: popper
|
||||||
|
},
|
||||||
|
attributes: {},
|
||||||
|
styles: {}
|
||||||
|
};
|
||||||
|
var effectCleanupFns = [];
|
||||||
|
var isDestroyed = false;
|
||||||
|
var instance = {
|
||||||
|
state: state,
|
||||||
|
setOptions: function setOptions(setOptionsAction) {
|
||||||
|
var options = typeof setOptionsAction === 'function' ? setOptionsAction(state.options) : setOptionsAction;
|
||||||
|
cleanupModifierEffects();
|
||||||
|
state.options = Object.assign({}, defaultOptions, state.options, options);
|
||||||
|
state.scrollParents = {
|
||||||
|
reference: isElement(reference) ? listScrollParents(reference) : reference.contextElement ? listScrollParents(reference.contextElement) : [],
|
||||||
|
popper: listScrollParents(popper)
|
||||||
|
}; // Orders the modifiers based on their dependencies and `phase`
|
||||||
|
// properties
|
||||||
|
|
||||||
|
var orderedModifiers = orderModifiers(mergeByName([].concat(defaultModifiers, state.options.modifiers))); // Strip out disabled modifiers
|
||||||
|
|
||||||
|
state.orderedModifiers = orderedModifiers.filter(function (m) {
|
||||||
|
return m.enabled;
|
||||||
|
});
|
||||||
|
runModifierEffects();
|
||||||
|
return instance.update();
|
||||||
|
},
|
||||||
|
// Sync update – it will always be executed, even if not necessary. This
|
||||||
|
// is useful for low frequency updates where sync behavior simplifies the
|
||||||
|
// logic.
|
||||||
|
// For high frequency updates (e.g. `resize` and `scroll` events), always
|
||||||
|
// prefer the async Popper#update method
|
||||||
|
forceUpdate: function forceUpdate() {
|
||||||
|
if (isDestroyed) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var _state$elements = state.elements,
|
||||||
|
reference = _state$elements.reference,
|
||||||
|
popper = _state$elements.popper; // Don't proceed if `reference` or `popper` are not valid elements
|
||||||
|
// anymore
|
||||||
|
|
||||||
|
if (!areValidElements(reference, popper)) {
|
||||||
|
return;
|
||||||
|
} // Store the reference and popper rects to be read by modifiers
|
||||||
|
|
||||||
|
|
||||||
|
state.rects = {
|
||||||
|
reference: getCompositeRect(reference, getOffsetParent(popper), state.options.strategy === 'fixed'),
|
||||||
|
popper: getLayoutRect(popper)
|
||||||
|
}; // Modifiers have the ability to reset the current update cycle. The
|
||||||
|
// most common use case for this is the `flip` modifier changing the
|
||||||
|
// placement, which then needs to re-run all the modifiers, because the
|
||||||
|
// logic was previously ran for the previous placement and is therefore
|
||||||
|
// stale/incorrect
|
||||||
|
|
||||||
|
state.reset = false;
|
||||||
|
state.placement = state.options.placement; // On each update cycle, the `modifiersData` property for each modifier
|
||||||
|
// is filled with the initial data specified by the modifier. This means
|
||||||
|
// it doesn't persist and is fresh on each update.
|
||||||
|
// To ensure persistent data, use `${name}#persistent`
|
||||||
|
|
||||||
|
state.orderedModifiers.forEach(function (modifier) {
|
||||||
|
return state.modifiersData[modifier.name] = Object.assign({}, modifier.data);
|
||||||
|
});
|
||||||
|
|
||||||
|
for (var index = 0; index < state.orderedModifiers.length; index++) {
|
||||||
|
if (state.reset === true) {
|
||||||
|
state.reset = false;
|
||||||
|
index = -1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
var _state$orderedModifie = state.orderedModifiers[index],
|
||||||
|
fn = _state$orderedModifie.fn,
|
||||||
|
_state$orderedModifie2 = _state$orderedModifie.options,
|
||||||
|
_options = _state$orderedModifie2 === void 0 ? {} : _state$orderedModifie2,
|
||||||
|
name = _state$orderedModifie.name;
|
||||||
|
|
||||||
|
if (typeof fn === 'function') {
|
||||||
|
state = fn({
|
||||||
|
state: state,
|
||||||
|
options: _options,
|
||||||
|
name: name,
|
||||||
|
instance: instance
|
||||||
|
}) || state;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// Async and optimistically optimized update – it will not be executed if
|
||||||
|
// not necessary (debounced to run at most once-per-tick)
|
||||||
|
update: debounce(function () {
|
||||||
|
return new Promise(function (resolve) {
|
||||||
|
instance.forceUpdate();
|
||||||
|
resolve(state);
|
||||||
|
});
|
||||||
|
}),
|
||||||
|
destroy: function destroy() {
|
||||||
|
cleanupModifierEffects();
|
||||||
|
isDestroyed = true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
if (!areValidElements(reference, popper)) {
|
||||||
|
return instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
instance.setOptions(options).then(function (state) {
|
||||||
|
if (!isDestroyed && options.onFirstUpdate) {
|
||||||
|
options.onFirstUpdate(state);
|
||||||
|
}
|
||||||
|
}); // Modifiers have the ability to execute arbitrary code before the first
|
||||||
|
// update cycle runs. They will be executed in the same order as the update
|
||||||
|
// cycle. This is useful when a modifier adds some persistent data that
|
||||||
|
// other modifiers need to use, but the modifier is run after the dependent
|
||||||
|
// one.
|
||||||
|
|
||||||
|
function runModifierEffects() {
|
||||||
|
state.orderedModifiers.forEach(function (_ref) {
|
||||||
|
var name = _ref.name,
|
||||||
|
_ref$options = _ref.options,
|
||||||
|
options = _ref$options === void 0 ? {} : _ref$options,
|
||||||
|
effect = _ref.effect;
|
||||||
|
|
||||||
|
if (typeof effect === 'function') {
|
||||||
|
var cleanupFn = effect({
|
||||||
|
state: state,
|
||||||
|
name: name,
|
||||||
|
instance: instance,
|
||||||
|
options: options
|
||||||
|
});
|
||||||
|
|
||||||
|
var noopFn = function noopFn() {};
|
||||||
|
|
||||||
|
effectCleanupFns.push(cleanupFn || noopFn);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function cleanupModifierEffects() {
|
||||||
|
effectCleanupFns.forEach(function (fn) {
|
||||||
|
return fn();
|
||||||
|
});
|
||||||
|
effectCleanupFns = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
return instance;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
export var createPopper = /*#__PURE__*/popperGenerator(); // eslint-disable-next-line import/no-unused-modules
|
||||||
|
|
||||||
|
export { detectOverflow };
|
||||||
23
node_modules/@popperjs/core/dist/esm/dom-utils/contains.js
generated
vendored
Normal file
23
node_modules/@popperjs/core/dist/esm/dom-utils/contains.js
generated
vendored
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
import { isShadowRoot } from "./instanceOf.js";
|
||||||
|
export default function contains(parent, child) {
|
||||||
|
var rootNode = child.getRootNode && child.getRootNode(); // First, attempt with faster native method
|
||||||
|
|
||||||
|
if (parent.contains(child)) {
|
||||||
|
return true;
|
||||||
|
} // then fallback to custom implementation with Shadow DOM support
|
||||||
|
else if (rootNode && isShadowRoot(rootNode)) {
|
||||||
|
var next = child;
|
||||||
|
|
||||||
|
do {
|
||||||
|
if (next && parent.isSameNode(next)) {
|
||||||
|
return true;
|
||||||
|
} // $FlowFixMe[prop-missing]: need a better way to handle this...
|
||||||
|
|
||||||
|
|
||||||
|
next = next.parentNode || next.host;
|
||||||
|
} while (next);
|
||||||
|
} // Give up, the result is false
|
||||||
|
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
41
node_modules/@popperjs/core/dist/esm/dom-utils/getBoundingClientRect.js
generated
vendored
Normal file
41
node_modules/@popperjs/core/dist/esm/dom-utils/getBoundingClientRect.js
generated
vendored
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
import { isElement, isHTMLElement } from "./instanceOf.js";
|
||||||
|
import { round } from "../utils/math.js";
|
||||||
|
import getWindow from "./getWindow.js";
|
||||||
|
import isLayoutViewport from "./isLayoutViewport.js";
|
||||||
|
export default function getBoundingClientRect(element, includeScale, isFixedStrategy) {
|
||||||
|
if (includeScale === void 0) {
|
||||||
|
includeScale = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isFixedStrategy === void 0) {
|
||||||
|
isFixedStrategy = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
var clientRect = element.getBoundingClientRect();
|
||||||
|
var scaleX = 1;
|
||||||
|
var scaleY = 1;
|
||||||
|
|
||||||
|
if (includeScale && isHTMLElement(element)) {
|
||||||
|
scaleX = element.offsetWidth > 0 ? round(clientRect.width) / element.offsetWidth || 1 : 1;
|
||||||
|
scaleY = element.offsetHeight > 0 ? round(clientRect.height) / element.offsetHeight || 1 : 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
var _ref = isElement(element) ? getWindow(element) : window,
|
||||||
|
visualViewport = _ref.visualViewport;
|
||||||
|
|
||||||
|
var addVisualOffsets = !isLayoutViewport() && isFixedStrategy;
|
||||||
|
var x = (clientRect.left + (addVisualOffsets && visualViewport ? visualViewport.offsetLeft : 0)) / scaleX;
|
||||||
|
var y = (clientRect.top + (addVisualOffsets && visualViewport ? visualViewport.offsetTop : 0)) / scaleY;
|
||||||
|
var width = clientRect.width / scaleX;
|
||||||
|
var height = clientRect.height / scaleY;
|
||||||
|
return {
|
||||||
|
width: width,
|
||||||
|
height: height,
|
||||||
|
top: y,
|
||||||
|
right: x + width,
|
||||||
|
bottom: y + height,
|
||||||
|
left: x,
|
||||||
|
x: x,
|
||||||
|
y: y
|
||||||
|
};
|
||||||
|
}
|
||||||
70
node_modules/@popperjs/core/dist/esm/dom-utils/getClippingRect.js
generated
vendored
Normal file
70
node_modules/@popperjs/core/dist/esm/dom-utils/getClippingRect.js
generated
vendored
Normal file
@@ -0,0 +1,70 @@
|
|||||||
|
import { viewport } from "../enums.js";
|
||||||
|
import getViewportRect from "./getViewportRect.js";
|
||||||
|
import getDocumentRect from "./getDocumentRect.js";
|
||||||
|
import listScrollParents from "./listScrollParents.js";
|
||||||
|
import getOffsetParent from "./getOffsetParent.js";
|
||||||
|
import getDocumentElement from "./getDocumentElement.js";
|
||||||
|
import getComputedStyle from "./getComputedStyle.js";
|
||||||
|
import { isElement, isHTMLElement } from "./instanceOf.js";
|
||||||
|
import getBoundingClientRect from "./getBoundingClientRect.js";
|
||||||
|
import getParentNode from "./getParentNode.js";
|
||||||
|
import contains from "./contains.js";
|
||||||
|
import getNodeName from "./getNodeName.js";
|
||||||
|
import rectToClientRect from "../utils/rectToClientRect.js";
|
||||||
|
import { max, min } from "../utils/math.js";
|
||||||
|
|
||||||
|
function getInnerBoundingClientRect(element, strategy) {
|
||||||
|
var rect = getBoundingClientRect(element, false, strategy === 'fixed');
|
||||||
|
rect.top = rect.top + element.clientTop;
|
||||||
|
rect.left = rect.left + element.clientLeft;
|
||||||
|
rect.bottom = rect.top + element.clientHeight;
|
||||||
|
rect.right = rect.left + element.clientWidth;
|
||||||
|
rect.width = element.clientWidth;
|
||||||
|
rect.height = element.clientHeight;
|
||||||
|
rect.x = rect.left;
|
||||||
|
rect.y = rect.top;
|
||||||
|
return rect;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getClientRectFromMixedType(element, clippingParent, strategy) {
|
||||||
|
return clippingParent === viewport ? rectToClientRect(getViewportRect(element, strategy)) : isElement(clippingParent) ? getInnerBoundingClientRect(clippingParent, strategy) : rectToClientRect(getDocumentRect(getDocumentElement(element)));
|
||||||
|
} // A "clipping parent" is an overflowable container with the characteristic of
|
||||||
|
// clipping (or hiding) overflowing elements with a position different from
|
||||||
|
// `initial`
|
||||||
|
|
||||||
|
|
||||||
|
function getClippingParents(element) {
|
||||||
|
var clippingParents = listScrollParents(getParentNode(element));
|
||||||
|
var canEscapeClipping = ['absolute', 'fixed'].indexOf(getComputedStyle(element).position) >= 0;
|
||||||
|
var clipperElement = canEscapeClipping && isHTMLElement(element) ? getOffsetParent(element) : element;
|
||||||
|
|
||||||
|
if (!isElement(clipperElement)) {
|
||||||
|
return [];
|
||||||
|
} // $FlowFixMe[incompatible-return]: https://github.com/facebook/flow/issues/1414
|
||||||
|
|
||||||
|
|
||||||
|
return clippingParents.filter(function (clippingParent) {
|
||||||
|
return isElement(clippingParent) && contains(clippingParent, clipperElement) && getNodeName(clippingParent) !== 'body';
|
||||||
|
});
|
||||||
|
} // Gets the maximum area that the element is visible in due to any number of
|
||||||
|
// clipping parents
|
||||||
|
|
||||||
|
|
||||||
|
export default function getClippingRect(element, boundary, rootBoundary, strategy) {
|
||||||
|
var mainClippingParents = boundary === 'clippingParents' ? getClippingParents(element) : [].concat(boundary);
|
||||||
|
var clippingParents = [].concat(mainClippingParents, [rootBoundary]);
|
||||||
|
var firstClippingParent = clippingParents[0];
|
||||||
|
var clippingRect = clippingParents.reduce(function (accRect, clippingParent) {
|
||||||
|
var rect = getClientRectFromMixedType(element, clippingParent, strategy);
|
||||||
|
accRect.top = max(rect.top, accRect.top);
|
||||||
|
accRect.right = min(rect.right, accRect.right);
|
||||||
|
accRect.bottom = min(rect.bottom, accRect.bottom);
|
||||||
|
accRect.left = max(rect.left, accRect.left);
|
||||||
|
return accRect;
|
||||||
|
}, getClientRectFromMixedType(element, firstClippingParent, strategy));
|
||||||
|
clippingRect.width = clippingRect.right - clippingRect.left;
|
||||||
|
clippingRect.height = clippingRect.bottom - clippingRect.top;
|
||||||
|
clippingRect.x = clippingRect.left;
|
||||||
|
clippingRect.y = clippingRect.top;
|
||||||
|
return clippingRect;
|
||||||
|
}
|
||||||
58
node_modules/@popperjs/core/dist/esm/dom-utils/getCompositeRect.js
generated
vendored
Normal file
58
node_modules/@popperjs/core/dist/esm/dom-utils/getCompositeRect.js
generated
vendored
Normal file
@@ -0,0 +1,58 @@
|
|||||||
|
import getBoundingClientRect from "./getBoundingClientRect.js";
|
||||||
|
import getNodeScroll from "./getNodeScroll.js";
|
||||||
|
import getNodeName from "./getNodeName.js";
|
||||||
|
import { isHTMLElement } from "./instanceOf.js";
|
||||||
|
import getWindowScrollBarX from "./getWindowScrollBarX.js";
|
||||||
|
import getDocumentElement from "./getDocumentElement.js";
|
||||||
|
import isScrollParent from "./isScrollParent.js";
|
||||||
|
import { round } from "../utils/math.js";
|
||||||
|
|
||||||
|
function isElementScaled(element) {
|
||||||
|
var rect = element.getBoundingClientRect();
|
||||||
|
var scaleX = round(rect.width) / element.offsetWidth || 1;
|
||||||
|
var scaleY = round(rect.height) / element.offsetHeight || 1;
|
||||||
|
return scaleX !== 1 || scaleY !== 1;
|
||||||
|
} // Returns the composite rect of an element relative to its offsetParent.
|
||||||
|
// Composite means it takes into account transforms as well as layout.
|
||||||
|
|
||||||
|
|
||||||
|
export default function getCompositeRect(elementOrVirtualElement, offsetParent, isFixed) {
|
||||||
|
if (isFixed === void 0) {
|
||||||
|
isFixed = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
var isOffsetParentAnElement = isHTMLElement(offsetParent);
|
||||||
|
var offsetParentIsScaled = isHTMLElement(offsetParent) && isElementScaled(offsetParent);
|
||||||
|
var documentElement = getDocumentElement(offsetParent);
|
||||||
|
var rect = getBoundingClientRect(elementOrVirtualElement, offsetParentIsScaled, isFixed);
|
||||||
|
var scroll = {
|
||||||
|
scrollLeft: 0,
|
||||||
|
scrollTop: 0
|
||||||
|
};
|
||||||
|
var offsets = {
|
||||||
|
x: 0,
|
||||||
|
y: 0
|
||||||
|
};
|
||||||
|
|
||||||
|
if (isOffsetParentAnElement || !isOffsetParentAnElement && !isFixed) {
|
||||||
|
if (getNodeName(offsetParent) !== 'body' || // https://github.com/popperjs/popper-core/issues/1078
|
||||||
|
isScrollParent(documentElement)) {
|
||||||
|
scroll = getNodeScroll(offsetParent);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isHTMLElement(offsetParent)) {
|
||||||
|
offsets = getBoundingClientRect(offsetParent, true);
|
||||||
|
offsets.x += offsetParent.clientLeft;
|
||||||
|
offsets.y += offsetParent.clientTop;
|
||||||
|
} else if (documentElement) {
|
||||||
|
offsets.x = getWindowScrollBarX(documentElement);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
x: rect.left + scroll.scrollLeft - offsets.x,
|
||||||
|
y: rect.top + scroll.scrollTop - offsets.y,
|
||||||
|
width: rect.width,
|
||||||
|
height: rect.height
|
||||||
|
};
|
||||||
|
}
|
||||||
4
node_modules/@popperjs/core/dist/esm/dom-utils/getComputedStyle.js
generated
vendored
Normal file
4
node_modules/@popperjs/core/dist/esm/dom-utils/getComputedStyle.js
generated
vendored
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
import getWindow from "./getWindow.js";
|
||||||
|
export default function getComputedStyle(element) {
|
||||||
|
return getWindow(element).getComputedStyle(element);
|
||||||
|
}
|
||||||
6
node_modules/@popperjs/core/dist/esm/dom-utils/getDocumentElement.js
generated
vendored
Normal file
6
node_modules/@popperjs/core/dist/esm/dom-utils/getDocumentElement.js
generated
vendored
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
import { isElement } from "./instanceOf.js";
|
||||||
|
export default function getDocumentElement(element) {
|
||||||
|
// $FlowFixMe[incompatible-return]: assume body is always available
|
||||||
|
return ((isElement(element) ? element.ownerDocument : // $FlowFixMe[prop-missing]
|
||||||
|
element.document) || window.document).documentElement;
|
||||||
|
}
|
||||||
29
node_modules/@popperjs/core/dist/esm/dom-utils/getDocumentRect.js
generated
vendored
Normal file
29
node_modules/@popperjs/core/dist/esm/dom-utils/getDocumentRect.js
generated
vendored
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
import getDocumentElement from "./getDocumentElement.js";
|
||||||
|
import getComputedStyle from "./getComputedStyle.js";
|
||||||
|
import getWindowScrollBarX from "./getWindowScrollBarX.js";
|
||||||
|
import getWindowScroll from "./getWindowScroll.js";
|
||||||
|
import { max } from "../utils/math.js"; // Gets the entire size of the scrollable document area, even extending outside
|
||||||
|
// of the `<html>` and `<body>` rect bounds if horizontally scrollable
|
||||||
|
|
||||||
|
export default function getDocumentRect(element) {
|
||||||
|
var _element$ownerDocumen;
|
||||||
|
|
||||||
|
var html = getDocumentElement(element);
|
||||||
|
var winScroll = getWindowScroll(element);
|
||||||
|
var body = (_element$ownerDocumen = element.ownerDocument) == null ? void 0 : _element$ownerDocumen.body;
|
||||||
|
var width = max(html.scrollWidth, html.clientWidth, body ? body.scrollWidth : 0, body ? body.clientWidth : 0);
|
||||||
|
var height = max(html.scrollHeight, html.clientHeight, body ? body.scrollHeight : 0, body ? body.clientHeight : 0);
|
||||||
|
var x = -winScroll.scrollLeft + getWindowScrollBarX(element);
|
||||||
|
var y = -winScroll.scrollTop;
|
||||||
|
|
||||||
|
if (getComputedStyle(body || html).direction === 'rtl') {
|
||||||
|
x += max(html.clientWidth, body ? body.clientWidth : 0) - width;
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
width: width,
|
||||||
|
height: height,
|
||||||
|
x: x,
|
||||||
|
y: y
|
||||||
|
};
|
||||||
|
}
|
||||||
6
node_modules/@popperjs/core/dist/esm/dom-utils/getHTMLElementScroll.js
generated
vendored
Normal file
6
node_modules/@popperjs/core/dist/esm/dom-utils/getHTMLElementScroll.js
generated
vendored
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
export default function getHTMLElementScroll(element) {
|
||||||
|
return {
|
||||||
|
scrollLeft: element.scrollLeft,
|
||||||
|
scrollTop: element.scrollTop
|
||||||
|
};
|
||||||
|
}
|
||||||
25
node_modules/@popperjs/core/dist/esm/dom-utils/getLayoutRect.js
generated
vendored
Normal file
25
node_modules/@popperjs/core/dist/esm/dom-utils/getLayoutRect.js
generated
vendored
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
import getBoundingClientRect from "./getBoundingClientRect.js"; // Returns the layout rect of an element relative to its offsetParent. Layout
|
||||||
|
// means it doesn't take into account transforms.
|
||||||
|
|
||||||
|
export default function getLayoutRect(element) {
|
||||||
|
var clientRect = getBoundingClientRect(element); // Use the clientRect sizes if it's not been transformed.
|
||||||
|
// Fixes https://github.com/popperjs/popper-core/issues/1223
|
||||||
|
|
||||||
|
var width = element.offsetWidth;
|
||||||
|
var height = element.offsetHeight;
|
||||||
|
|
||||||
|
if (Math.abs(clientRect.width - width) <= 1) {
|
||||||
|
width = clientRect.width;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Math.abs(clientRect.height - height) <= 1) {
|
||||||
|
height = clientRect.height;
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
x: element.offsetLeft,
|
||||||
|
y: element.offsetTop,
|
||||||
|
width: width,
|
||||||
|
height: height
|
||||||
|
};
|
||||||
|
}
|
||||||
3
node_modules/@popperjs/core/dist/esm/dom-utils/getNodeName.js
generated
vendored
Normal file
3
node_modules/@popperjs/core/dist/esm/dom-utils/getNodeName.js
generated
vendored
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
export default function getNodeName(element) {
|
||||||
|
return element ? (element.nodeName || '').toLowerCase() : null;
|
||||||
|
}
|
||||||
11
node_modules/@popperjs/core/dist/esm/dom-utils/getNodeScroll.js
generated
vendored
Normal file
11
node_modules/@popperjs/core/dist/esm/dom-utils/getNodeScroll.js
generated
vendored
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
import getWindowScroll from "./getWindowScroll.js";
|
||||||
|
import getWindow from "./getWindow.js";
|
||||||
|
import { isHTMLElement } from "./instanceOf.js";
|
||||||
|
import getHTMLElementScroll from "./getHTMLElementScroll.js";
|
||||||
|
export default function getNodeScroll(node) {
|
||||||
|
if (node === getWindow(node) || !isHTMLElement(node)) {
|
||||||
|
return getWindowScroll(node);
|
||||||
|
} else {
|
||||||
|
return getHTMLElementScroll(node);
|
||||||
|
}
|
||||||
|
}
|
||||||
69
node_modules/@popperjs/core/dist/esm/dom-utils/getOffsetParent.js
generated
vendored
Normal file
69
node_modules/@popperjs/core/dist/esm/dom-utils/getOffsetParent.js
generated
vendored
Normal file
@@ -0,0 +1,69 @@
|
|||||||
|
import getWindow from "./getWindow.js";
|
||||||
|
import getNodeName from "./getNodeName.js";
|
||||||
|
import getComputedStyle from "./getComputedStyle.js";
|
||||||
|
import { isHTMLElement, isShadowRoot } from "./instanceOf.js";
|
||||||
|
import isTableElement from "./isTableElement.js";
|
||||||
|
import getParentNode from "./getParentNode.js";
|
||||||
|
import getUAString from "../utils/userAgent.js";
|
||||||
|
|
||||||
|
function getTrueOffsetParent(element) {
|
||||||
|
if (!isHTMLElement(element) || // https://github.com/popperjs/popper-core/issues/837
|
||||||
|
getComputedStyle(element).position === 'fixed') {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return element.offsetParent;
|
||||||
|
} // `.offsetParent` reports `null` for fixed elements, while absolute elements
|
||||||
|
// return the containing block
|
||||||
|
|
||||||
|
|
||||||
|
function getContainingBlock(element) {
|
||||||
|
var isFirefox = /firefox/i.test(getUAString());
|
||||||
|
var isIE = /Trident/i.test(getUAString());
|
||||||
|
|
||||||
|
if (isIE && isHTMLElement(element)) {
|
||||||
|
// In IE 9, 10 and 11 fixed elements containing block is always established by the viewport
|
||||||
|
var elementCss = getComputedStyle(element);
|
||||||
|
|
||||||
|
if (elementCss.position === 'fixed') {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var currentNode = getParentNode(element);
|
||||||
|
|
||||||
|
if (isShadowRoot(currentNode)) {
|
||||||
|
currentNode = currentNode.host;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (isHTMLElement(currentNode) && ['html', 'body'].indexOf(getNodeName(currentNode)) < 0) {
|
||||||
|
var css = getComputedStyle(currentNode); // This is non-exhaustive but covers the most common CSS properties that
|
||||||
|
// create a containing block.
|
||||||
|
// https://developer.mozilla.org/en-US/docs/Web/CSS/Containing_block#identifying_the_containing_block
|
||||||
|
|
||||||
|
if (css.transform !== 'none' || css.perspective !== 'none' || css.contain === 'paint' || ['transform', 'perspective'].indexOf(css.willChange) !== -1 || isFirefox && css.willChange === 'filter' || isFirefox && css.filter && css.filter !== 'none') {
|
||||||
|
return currentNode;
|
||||||
|
} else {
|
||||||
|
currentNode = currentNode.parentNode;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
} // Gets the closest ancestor positioned element. Handles some edge cases,
|
||||||
|
// such as table ancestors and cross browser bugs.
|
||||||
|
|
||||||
|
|
||||||
|
export default function getOffsetParent(element) {
|
||||||
|
var window = getWindow(element);
|
||||||
|
var offsetParent = getTrueOffsetParent(element);
|
||||||
|
|
||||||
|
while (offsetParent && isTableElement(offsetParent) && getComputedStyle(offsetParent).position === 'static') {
|
||||||
|
offsetParent = getTrueOffsetParent(offsetParent);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (offsetParent && (getNodeName(offsetParent) === 'html' || getNodeName(offsetParent) === 'body' && getComputedStyle(offsetParent).position === 'static')) {
|
||||||
|
return window;
|
||||||
|
}
|
||||||
|
|
||||||
|
return offsetParent || getContainingBlock(element) || window;
|
||||||
|
}
|
||||||
19
node_modules/@popperjs/core/dist/esm/dom-utils/getParentNode.js
generated
vendored
Normal file
19
node_modules/@popperjs/core/dist/esm/dom-utils/getParentNode.js
generated
vendored
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
import getNodeName from "./getNodeName.js";
|
||||||
|
import getDocumentElement from "./getDocumentElement.js";
|
||||||
|
import { isShadowRoot } from "./instanceOf.js";
|
||||||
|
export default function getParentNode(element) {
|
||||||
|
if (getNodeName(element) === 'html') {
|
||||||
|
return element;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (// this is a quicker (but less type safe) way to save quite some bytes from the bundle
|
||||||
|
// $FlowFixMe[incompatible-return]
|
||||||
|
// $FlowFixMe[prop-missing]
|
||||||
|
element.assignedSlot || // step into the shadow DOM of the parent of a slotted node
|
||||||
|
element.parentNode || ( // DOM Element detected
|
||||||
|
isShadowRoot(element) ? element.host : null) || // ShadowRoot detected
|
||||||
|
// $FlowFixMe[incompatible-call]: HTMLElement is a Node
|
||||||
|
getDocumentElement(element) // fallback
|
||||||
|
|
||||||
|
);
|
||||||
|
}
|
||||||
16
node_modules/@popperjs/core/dist/esm/dom-utils/getScrollParent.js
generated
vendored
Normal file
16
node_modules/@popperjs/core/dist/esm/dom-utils/getScrollParent.js
generated
vendored
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
import getParentNode from "./getParentNode.js";
|
||||||
|
import isScrollParent from "./isScrollParent.js";
|
||||||
|
import getNodeName from "./getNodeName.js";
|
||||||
|
import { isHTMLElement } from "./instanceOf.js";
|
||||||
|
export default function getScrollParent(node) {
|
||||||
|
if (['html', 'body', '#document'].indexOf(getNodeName(node)) >= 0) {
|
||||||
|
// $FlowFixMe[incompatible-return]: assume body is always available
|
||||||
|
return node.ownerDocument.body;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isHTMLElement(node) && isScrollParent(node)) {
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
|
||||||
|
return getScrollParent(getParentNode(node));
|
||||||
|
}
|
||||||
31
node_modules/@popperjs/core/dist/esm/dom-utils/getViewportRect.js
generated
vendored
Normal file
31
node_modules/@popperjs/core/dist/esm/dom-utils/getViewportRect.js
generated
vendored
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
import getWindow from "./getWindow.js";
|
||||||
|
import getDocumentElement from "./getDocumentElement.js";
|
||||||
|
import getWindowScrollBarX from "./getWindowScrollBarX.js";
|
||||||
|
import isLayoutViewport from "./isLayoutViewport.js";
|
||||||
|
export default function getViewportRect(element, strategy) {
|
||||||
|
var win = getWindow(element);
|
||||||
|
var html = getDocumentElement(element);
|
||||||
|
var visualViewport = win.visualViewport;
|
||||||
|
var width = html.clientWidth;
|
||||||
|
var height = html.clientHeight;
|
||||||
|
var x = 0;
|
||||||
|
var y = 0;
|
||||||
|
|
||||||
|
if (visualViewport) {
|
||||||
|
width = visualViewport.width;
|
||||||
|
height = visualViewport.height;
|
||||||
|
var layoutViewport = isLayoutViewport();
|
||||||
|
|
||||||
|
if (layoutViewport || !layoutViewport && strategy === 'fixed') {
|
||||||
|
x = visualViewport.offsetLeft;
|
||||||
|
y = visualViewport.offsetTop;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
width: width,
|
||||||
|
height: height,
|
||||||
|
x: x + getWindowScrollBarX(element),
|
||||||
|
y: y
|
||||||
|
};
|
||||||
|
}
|
||||||
12
node_modules/@popperjs/core/dist/esm/dom-utils/getWindow.js
generated
vendored
Normal file
12
node_modules/@popperjs/core/dist/esm/dom-utils/getWindow.js
generated
vendored
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
export default function getWindow(node) {
|
||||||
|
if (node == null) {
|
||||||
|
return window;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (node.toString() !== '[object Window]') {
|
||||||
|
var ownerDocument = node.ownerDocument;
|
||||||
|
return ownerDocument ? ownerDocument.defaultView || window : window;
|
||||||
|
}
|
||||||
|
|
||||||
|
return node;
|
||||||
|
}
|
||||||
10
node_modules/@popperjs/core/dist/esm/dom-utils/getWindowScroll.js
generated
vendored
Normal file
10
node_modules/@popperjs/core/dist/esm/dom-utils/getWindowScroll.js
generated
vendored
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
import getWindow from "./getWindow.js";
|
||||||
|
export default function getWindowScroll(node) {
|
||||||
|
var win = getWindow(node);
|
||||||
|
var scrollLeft = win.pageXOffset;
|
||||||
|
var scrollTop = win.pageYOffset;
|
||||||
|
return {
|
||||||
|
scrollLeft: scrollLeft,
|
||||||
|
scrollTop: scrollTop
|
||||||
|
};
|
||||||
|
}
|
||||||
13
node_modules/@popperjs/core/dist/esm/dom-utils/getWindowScrollBarX.js
generated
vendored
Normal file
13
node_modules/@popperjs/core/dist/esm/dom-utils/getWindowScrollBarX.js
generated
vendored
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
import getBoundingClientRect from "./getBoundingClientRect.js";
|
||||||
|
import getDocumentElement from "./getDocumentElement.js";
|
||||||
|
import getWindowScroll from "./getWindowScroll.js";
|
||||||
|
export default function getWindowScrollBarX(element) {
|
||||||
|
// If <html> has a CSS width greater than the viewport, then this will be
|
||||||
|
// incorrect for RTL.
|
||||||
|
// Popper 1 is broken in this case and never had a bug report so let's assume
|
||||||
|
// it's not an issue. I don't think anyone ever specifies width on <html>
|
||||||
|
// anyway.
|
||||||
|
// Browsers where the left scrollbar doesn't cause an issue report `0` for
|
||||||
|
// this (e.g. Edge 2019, IE11, Safari)
|
||||||
|
return getBoundingClientRect(getDocumentElement(element)).left + getWindowScroll(element).scrollLeft;
|
||||||
|
}
|
||||||
23
node_modules/@popperjs/core/dist/esm/dom-utils/instanceOf.js
generated
vendored
Normal file
23
node_modules/@popperjs/core/dist/esm/dom-utils/instanceOf.js
generated
vendored
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
import getWindow from "./getWindow.js";
|
||||||
|
|
||||||
|
function isElement(node) {
|
||||||
|
var OwnElement = getWindow(node).Element;
|
||||||
|
return node instanceof OwnElement || node instanceof Element;
|
||||||
|
}
|
||||||
|
|
||||||
|
function isHTMLElement(node) {
|
||||||
|
var OwnElement = getWindow(node).HTMLElement;
|
||||||
|
return node instanceof OwnElement || node instanceof HTMLElement;
|
||||||
|
}
|
||||||
|
|
||||||
|
function isShadowRoot(node) {
|
||||||
|
// IE 11 has no ShadowRoot
|
||||||
|
if (typeof ShadowRoot === 'undefined') {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
var OwnElement = getWindow(node).ShadowRoot;
|
||||||
|
return node instanceof OwnElement || node instanceof ShadowRoot;
|
||||||
|
}
|
||||||
|
|
||||||
|
export { isElement, isHTMLElement, isShadowRoot };
|
||||||
4
node_modules/@popperjs/core/dist/esm/dom-utils/isLayoutViewport.js
generated
vendored
Normal file
4
node_modules/@popperjs/core/dist/esm/dom-utils/isLayoutViewport.js
generated
vendored
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
import getUAString from "../utils/userAgent.js";
|
||||||
|
export default function isLayoutViewport() {
|
||||||
|
return !/^((?!chrome|android).)*safari/i.test(getUAString());
|
||||||
|
}
|
||||||
10
node_modules/@popperjs/core/dist/esm/dom-utils/isScrollParent.js
generated
vendored
Normal file
10
node_modules/@popperjs/core/dist/esm/dom-utils/isScrollParent.js
generated
vendored
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
import getComputedStyle from "./getComputedStyle.js";
|
||||||
|
export default function isScrollParent(element) {
|
||||||
|
// Firefox wants us to check `-x` and `-y` variations as well
|
||||||
|
var _getComputedStyle = getComputedStyle(element),
|
||||||
|
overflow = _getComputedStyle.overflow,
|
||||||
|
overflowX = _getComputedStyle.overflowX,
|
||||||
|
overflowY = _getComputedStyle.overflowY;
|
||||||
|
|
||||||
|
return /auto|scroll|overlay|hidden/.test(overflow + overflowY + overflowX);
|
||||||
|
}
|
||||||
4
node_modules/@popperjs/core/dist/esm/dom-utils/isTableElement.js
generated
vendored
Normal file
4
node_modules/@popperjs/core/dist/esm/dom-utils/isTableElement.js
generated
vendored
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
import getNodeName from "./getNodeName.js";
|
||||||
|
export default function isTableElement(element) {
|
||||||
|
return ['table', 'td', 'th'].indexOf(getNodeName(element)) >= 0;
|
||||||
|
}
|
||||||
26
node_modules/@popperjs/core/dist/esm/dom-utils/listScrollParents.js
generated
vendored
Normal file
26
node_modules/@popperjs/core/dist/esm/dom-utils/listScrollParents.js
generated
vendored
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
import getScrollParent from "./getScrollParent.js";
|
||||||
|
import getParentNode from "./getParentNode.js";
|
||||||
|
import getWindow from "./getWindow.js";
|
||||||
|
import isScrollParent from "./isScrollParent.js";
|
||||||
|
/*
|
||||||
|
given a DOM element, return the list of all scroll parents, up the list of ancesors
|
||||||
|
until we get to the top window object. This list is what we attach scroll listeners
|
||||||
|
to, because if any of these parent elements scroll, we'll need to re-calculate the
|
||||||
|
reference element's position.
|
||||||
|
*/
|
||||||
|
|
||||||
|
export default function listScrollParents(element, list) {
|
||||||
|
var _element$ownerDocumen;
|
||||||
|
|
||||||
|
if (list === void 0) {
|
||||||
|
list = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
var scrollParent = getScrollParent(element);
|
||||||
|
var isBody = scrollParent === ((_element$ownerDocumen = element.ownerDocument) == null ? void 0 : _element$ownerDocumen.body);
|
||||||
|
var win = getWindow(scrollParent);
|
||||||
|
var target = isBody ? [win].concat(win.visualViewport || [], isScrollParent(scrollParent) ? scrollParent : []) : scrollParent;
|
||||||
|
var updatedList = list.concat(target);
|
||||||
|
return isBody ? updatedList : // $FlowFixMe[incompatible-call]: isBody tells us target will be an HTMLElement here
|
||||||
|
updatedList.concat(listScrollParents(getParentNode(target)));
|
||||||
|
}
|
||||||
31
node_modules/@popperjs/core/dist/esm/enums.js
generated
vendored
Normal file
31
node_modules/@popperjs/core/dist/esm/enums.js
generated
vendored
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
export var top = 'top';
|
||||||
|
export var bottom = 'bottom';
|
||||||
|
export var right = 'right';
|
||||||
|
export var left = 'left';
|
||||||
|
export var auto = 'auto';
|
||||||
|
export var basePlacements = [top, bottom, right, left];
|
||||||
|
export var start = 'start';
|
||||||
|
export var end = 'end';
|
||||||
|
export var clippingParents = 'clippingParents';
|
||||||
|
export var viewport = 'viewport';
|
||||||
|
export var popper = 'popper';
|
||||||
|
export var reference = 'reference';
|
||||||
|
export var variationPlacements = /*#__PURE__*/basePlacements.reduce(function (acc, placement) {
|
||||||
|
return acc.concat([placement + "-" + start, placement + "-" + end]);
|
||||||
|
}, []);
|
||||||
|
export var placements = /*#__PURE__*/[].concat(basePlacements, [auto]).reduce(function (acc, placement) {
|
||||||
|
return acc.concat([placement, placement + "-" + start, placement + "-" + end]);
|
||||||
|
}, []); // modifiers that need to read the DOM
|
||||||
|
|
||||||
|
export var beforeRead = 'beforeRead';
|
||||||
|
export var read = 'read';
|
||||||
|
export var afterRead = 'afterRead'; // pure-logic modifiers
|
||||||
|
|
||||||
|
export var beforeMain = 'beforeMain';
|
||||||
|
export var main = 'main';
|
||||||
|
export var afterMain = 'afterMain'; // modifier with the purpose to write to the DOM (or write into a framework state)
|
||||||
|
|
||||||
|
export var beforeWrite = 'beforeWrite';
|
||||||
|
export var write = 'write';
|
||||||
|
export var afterWrite = 'afterWrite';
|
||||||
|
export var modifierPhases = [beforeRead, read, afterRead, beforeMain, main, afterMain, beforeWrite, write, afterWrite];
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user