加入專案檔案。

This commit is contained in:
威勝 張 2024-02-01 11:37:15 +08:00
parent a992c6b5b6
commit 4a4c9dd601
1983 changed files with 271359 additions and 0 deletions

25
.dockerignore Normal file
View File

@ -0,0 +1,25 @@
**/.classpath
**/.dockerignore
**/.env
**/.git
**/.gitignore
**/.project
**/.settings
**/.toolstarget
**/.vs
**/.vscode
**/*.*proj.user
**/*.dbmdl
**/*.jfm
**/azds.yaml
**/bin
**/charts
**/docker-compose*
**/Dockerfile*
**/node_modules
**/npm-debug.log
**/obj
**/secrets.dev.yaml
**/values.dev.yaml
LICENSE
README.md

25
Parking_spaces.sln Normal file
View File

@ -0,0 +1,25 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.5.33414.496
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Parking_spaces", "Parking_spaces\Parking_spaces.csproj", "{5DC9EFC6-6A98-4AF7-9B2E-2FB0FAE549C7}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{5DC9EFC6-6A98-4AF7-9B2E-2FB0FAE549C7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{5DC9EFC6-6A98-4AF7-9B2E-2FB0FAE549C7}.Debug|Any CPU.Build.0 = Debug|Any CPU
{5DC9EFC6-6A98-4AF7-9B2E-2FB0FAE549C7}.Release|Any CPU.ActiveCfg = Release|Any CPU
{5DC9EFC6-6A98-4AF7-9B2E-2FB0FAE549C7}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {652EF671-B1BF-47CB-89BB-FA32724C7CC4}
EndGlobalSection
EndGlobal

View File

@ -0,0 +1,12 @@
{
"version": 1,
"isRoot": true,
"tools": {
"dotnet-ef": {
"version": "8.0.1",
"commands": [
"dotnet-ef"
]
}
}
}

View File

@ -0,0 +1,5 @@
namespace Parking_spaces.Authorization;
[AttributeUsage(AttributeTargets.Method)]
public class AllowAnonymousAttribute : Attribute
{ }

View File

@ -0,0 +1,25 @@
namespace Parking_spaces.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;
using Parking_spaces.Entities;
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
public class AuthorizeAttribute : Attribute, IAuthorizationFilter
{
public void OnAuthorization(AuthorizationFilterContext context)
{
// skip authorization if action is decorated with [AllowAnonymous] attribute
var allowAnonymous = context.ActionDescriptor.EndpointMetadata.OfType<AllowAnonymousAttribute>().Any();
if (allowAnonymous)
return;
// authorization
var user = (User?)context.HttpContext.Items["User"];
if (user == null)
{
// not logged in or role not authorized
context.Result = new JsonResult(new { message = "Unauthorized" }) { StatusCode = StatusCodes.Status401Unauthorized };
}
}
}

View File

@ -0,0 +1,26 @@
namespace Parking_spaces.Authorization;
using Parking_spaces.Services;
public class JwtMiddleware
{
private readonly RequestDelegate _next;
public JwtMiddleware(RequestDelegate next)
{
_next = next;
}
public async Task Invoke(HttpContext context, IUserService userService, IJwtUtils jwtUtils)
{
var token = context.Request.Headers["Authorization"].FirstOrDefault()?.Split(" ").Last();
var userId = jwtUtils.ValidateJwtToken(token);
if (userId != null)
{
// attach user to context on successful jwt validation
context.Items["User"] = userService.GetById(userId.Value);
}
var stop = "1";
await _next(context);
}
}

View File

@ -0,0 +1,105 @@
namespace Parking_spaces.Authorization;
using Microsoft.Extensions.Options;
using Microsoft.IdentityModel.Tokens;
using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims;
using System.Text;
using Parking_spaces.Entities;
using Parking_spaces.Helpers;
public interface IJwtUtils
{
public string GenerateJwtToken(User user);
public int? ValidateJwtToken(string? token);
}
public class JwtUtils : IJwtUtils
{
private readonly AppSettings _appSettings;
public JwtUtils(IOptions<AppSettings> appSettings)
{
_appSettings = appSettings.Value;
if (string.IsNullOrEmpty(_appSettings.Secret))
throw new Exception("JWT secret not configured");
}
public string GenerateJwtToken(User user)
{
// generate token that is valid for 7 days
var tokenHandler = new JwtSecurityTokenHandler();
var key = Encoding.ASCII.GetBytes(_appSettings.Secret!);
var tokenDescriptor = new SecurityTokenDescriptor
{
Subject = new ClaimsIdentity(new[] { new Claim("id", user.Id.ToString()) }),
Expires = DateTime.UtcNow.AddDays(7),
SigningCredentials = new SigningCredentials(new SymmetricSecurityKey(key), SecurityAlgorithms.HmacSha256Signature)
};
var token = tokenHandler.CreateToken(tokenDescriptor);
return tokenHandler.WriteToken(token);
}
public int? ValidateJwtToken(string? token)
{
if (token == null)
return null;
var tokenHandler = new JwtSecurityTokenHandler();
var key = Encoding.ASCII.GetBytes(_appSettings.Secret!);
try
{
tokenHandler.ValidateToken(token, new TokenValidationParameters
{
ValidateIssuerSigningKey = true,
IssuerSigningKey = new SymmetricSecurityKey(key),
ValidateIssuer = false,
ValidateAudience = false,
// set clockskew to zero so tokens expire exactly at token expiration time (instead of 5 minutes later)
ClockSkew = TimeSpan.Zero
}, out SecurityToken validatedToken);
var jwtToken = (JwtSecurityToken)validatedToken;
var userId = int.Parse(jwtToken.Claims.First(x => x.Type == "id").Value);
// return user id from JWT token if validation successful
return userId;
}
catch
{
// return null if validation fails
return null;
}
}
//0523
public bool ValidateToken(string token)
{
var tokenHandler = new JwtSecurityTokenHandler();
var jwtSecret = "your_jwt_secret"; // JWT 密钥,应与生成令牌时使用的密钥相匹配
var validationParameters = new TokenValidationParameters
{
ValidateIssuerSigningKey = true,
IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(jwtSecret)),
ValidateIssuer = false,
ValidateAudience = false,
ValidateLifetime = true,
ClockSkew = TimeSpan.Zero // 设置为零以确保令牌过期时立即失效
};
try
{
SecurityToken validatedToken;
tokenHandler.ValidateToken(token, validationParameters, out validatedToken);
return true;
}
catch
{
return false;
}
}
}

View File

@ -0,0 +1,72 @@
using Microsoft.AspNetCore.Mvc;
using System.Text.RegularExpressions;
using Emgu.CV;
using Emgu.CV.CvEnum;
using Emgu.CV.Structure;
namespace Parking_spaces.Controllers
{
public class EngineeringController : Controller
{
private VideoCapture _capture;
public IActionResult Engineering_total_table()
{
return View();
}
public IActionResult Engineering_Index()
{
return View();
}
public IActionResult Engineering_CAM()
{
return View();
}
public IActionResult Engineering_LED()
{
return View();
}
public IActionResult Engineering_LED_detail(string id)
{
ViewBag.parking_spaces_name = id;
return View();
}
public IActionResult Engineering_CAM_detail(string id)
{
ViewBag.parking_spaces_name = "";
ViewBag.ip = "";
ViewBag.port = "";
string[] str_list = Regex.Split(id, ":");
if (str_list.Length >= 2)
{
ViewBag.parking_spaces_name = str_list[0];
ViewBag.ip = str_list[1];
ViewBag.port = str_list[2];
}
else
{
ViewBag.ip = str_list[0];
}
//ViewBag.parking_spaces_name = id;
return View();
}
public IActionResult Engineering_Violation()
{
return View();
}
public IActionResult Single_violation_detail(string id)
{
ViewBag.parking_spaces_name = id;
return View();
}
public IActionResult Bootstrap_test(string id)
{
return View();
}
}
}

View File

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

View File

@ -0,0 +1,80 @@
using Microsoft.AspNetCore.Mvc;
using Parking_spaces.Authorization;
using Parking_spaces.Helpers;
using System.Net.Http.Headers;
namespace Parking_spaces.Controllers
{
public class Park_spacesController : Controller
{
private readonly HttpClient _httpClient;
public Park_spacesController(HttpClient httpClient, IConfiguration configuration)
{
_httpClient = httpClient;
}
//[Authorize]
/*
public async Task<IActionResult> Parking_spaces_total_table(string id)
{
if (id != null)
{
// 获取身份验证令牌
string token = id;
// 设置 HttpClient 的默认请求头
_httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue(token);
// 构建 API 请求的 URL
string apiUrl = "http://140.125.20.183:7710/Users/token";
// 调用需要身份验证的 API
HttpResponseMessage response = await _httpClient.GetAsync(apiUrl);
if (response.ReasonPhrase == "OK")
{
ViewBag.token_check = "true";
ViewBag.token = token;
return View();
}
else
{
ViewBag.token_check = "false";
return View();
}
}
else {
ViewBag.token_check = "false";
return View();
//return RedirectToAction("Login", "Home");
}
}*/
public IActionResult Parking_spaces_total_table()
{
return View();
}
//[Authorize]
public IActionResult Single_parking_spaces_detail(string id)
{
ViewBag.name = id;
return View();
}
public IActionResult Single_parking_spaces_map(string id)
{
ViewBag.name = id;
return View();
}
public IActionResult Parking_spaces_history(string id)
{
return View();
}
}
}

View File

@ -0,0 +1,56 @@
namespace WebApi.Controllers;
using Microsoft.AspNetCore.Mvc;
using Newtonsoft.Json.Linq;
using NuGet.Common;
using Parking_spaces.Authorization;
using Parking_spaces.Models;
using Parking_spaces.Services;
[ApiController]
[Authorize]
[Route("[controller]")]
public class UsersController : ControllerBase
{
private IUserService _userService;
public UsersController(IUserService userService)
{
_userService = userService;
}
[AllowAnonymous]
[HttpPost("authenticate")]
public IActionResult Authenticate(AuthenticateRequest model)
{
var response = _userService.Authenticate(model);
if (response == null)
return BadRequest(new { message = "Username or password is incorrect" });
// 将令牌添加到响应头中
Response.Headers.Add("Authorization", "Bearer " + response.Token);
// 将令牌保存在Cookie或其他适当的位置
Response.Cookies.Append("token", response.Token);
return Ok(response);
// 重定向到另一个页面
//return RedirectToAction("/Park_spaces/Parking_spaces_total_table");
//return RedirectToAction("Parking_spaces_total_table", "Park_spaces");
}
[HttpGet]
public IActionResult GetAll()
{
var users = _userService.GetAll();
return Ok(users);
}
[HttpGet("token")]
public IActionResult Token()
{
return Ok();
}
}

25
Parking_spaces/Dockerfile Normal file
View File

@ -0,0 +1,25 @@
#See https://aka.ms/customizecontainer to learn how to customize your debug container and how Visual Studio uses this Dockerfile to build your images for faster debugging.
#Depending on the operating system of the host machines(s) that will build or run the containers, the image specified in the FROM statement may need to be changed.
#For more information, please see https://aka.ms/containercompat
FROM mcr.microsoft.com/dotnet/aspnet:6.0 AS base
WORKDIR /app
EXPOSE 80
EXPOSE 443
FROM mcr.microsoft.com/dotnet/sdk:6.0 AS build
WORKDIR /src
COPY ["Parking_spaces/Parking_spaces.csproj", "Parking_spaces/"]
RUN dotnet restore "Parking_spaces/Parking_spaces.csproj"
COPY . .
WORKDIR "/src/Parking_spaces"
RUN dotnet build "Parking_spaces.csproj" -c Release -o /app/build
FROM build AS publish
RUN dotnet publish "Parking_spaces.csproj" -c Release -o /app/publish /p:UseAppHost=false
FROM base AS final
WORKDIR /app
COPY --from=publish /app/publish .
ENTRYPOINT ["dotnet", "Parking_spaces.dll"]

View File

@ -0,0 +1,14 @@
namespace Parking_spaces.Entities;
using System.Text.Json.Serialization;
public class User
{
public int Id { get; set; }
public string? FirstName { get; set; }
public string? LastName { get; set; }
public string? Username { get; set; }
[JsonIgnore]
public string? Password { get; set; }
}

View File

@ -0,0 +1,6 @@
namespace Parking_spaces.Helpers;
public class AppSettings
{
public string? Secret { get; set; }
}

View File

@ -0,0 +1,12 @@
namespace Parking_spaces.Models;
using System.ComponentModel.DataAnnotations;
public class AuthenticateRequest
{
[Required]
public string? Username { get; set; }
[Required]
public string? Password { get; set; }
}

View File

@ -0,0 +1,22 @@
namespace Parking_spaces.Models;
using Parking_spaces.Entities;
public class AuthenticateResponse
{
public int Id { get; set; }
public string? FirstName { get; set; }
public string? LastName { get; set; }
public string? Username { get; set; }
public string Token { get; set; }
public AuthenticateResponse(User user, string token)
{
Id = user.Id;
FirstName = user.FirstName;
LastName = user.LastName;
Username = user.Username;
Token = token;
}
}

View File

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

View File

@ -0,0 +1,23 @@
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
<UserSecretsId>b56499d2-e1e5-4e84-ba47-3922aa2d2479</UserSecretsId>
<DockerDefaultTargetOS>Windows</DockerDefaultTargetOS>
<EnableSdkContainerSupport>true</EnableSdkContainerSupport>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Emgu.CV" Version="4.7.0.5276" />
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="6.0.16" />
<PackageReference Include="Microsoft.VisualStudio.Azure.Containers.Tools.Targets" Version="1.17.2" />
<PackageReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Design" Version="6.0.16" />
<PackageReference Include="OpenCvSharp4" Version="4.7.0.20230115" />
<PackageReference Include="OpenCvSharp4.runtime.win" Version="4.7.0.20230115" />
<PackageReference Include="OpenCvSharp4.Windows" Version="4.7.0.20230115" />
<PackageReference Include="System.IdentityModel.Tokens.Jwt" Version="6.30.1" />
</ItemGroup>
</Project>

130
Parking_spaces/Program.cs Normal file
View File

@ -0,0 +1,130 @@

using Microsoft.AspNetCore.Authentication.JwtBearer;
using Parking_spaces.Authorization;
using Parking_spaces.Helpers;
using Parking_spaces.Services;
/*
var builder = WebApplication.CreateBuilder(args);
// add services to DI container
{
var services = builder.Services;
services.AddCors();
services.AddControllers();
// configure strongly typed settings object
services.Configure<AppSettings>(builder.Configuration.GetSection("AppSettings"));
// configure DI for application services
services.AddScoped<IJwtUtils, JwtUtils>();
services.AddScoped<IUserService, UserService>();
}
var app = builder.Build();
// configure HTTP request pipeline
{
// global cors policy
app.UseCors(x => x
.AllowAnyOrigin()
.AllowAnyMethod()
.AllowAnyHeader());
// custom jwt auth middleware
app.UseMiddleware<JwtMiddleware>();
app.MapControllers();
}
app.Run();
*/
var builder = WebApplication.CreateBuilder(args);
//身分驗證
//add services to DI container
{
var services = builder.Services;
services.AddCors();
services.AddControllers();
// configure strongly typed settings object
services.Configure<AppSettings>(builder.Configuration.GetSection("AppSettings"));
// 添加身份验证服务
services.AddAuthentication(options =>
{
options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
});
// configure DI for application services
services.AddScoped<IJwtUtils, JwtUtils>();
services.AddScoped<IUserService, UserService>();
// 注册 HttpClient 服务
services.AddHttpClient();
}
//在 ASP.NET Core 中啟用 CORS (跨原始來源要求)
builder.Services.AddCors();
// Add services to the container.
builder.Services.AddControllersWithViews();
var app = builder.Build();
//身分驗證
// configure HTTP request pipeline
{
// global cors policy
app.UseCors(x => x
.AllowAnyOrigin()
.AllowAnyMethod()
.AllowAnyHeader());
// custom jwt auth middleware
app.UseMiddleware<JwtMiddleware>();
app.MapControllers();
}
// Configure the HTTP request pipeline.
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Home/Error");
// The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
app.UseHsts();
}
//在 ASP.NET Core 中啟用 CORS (跨原始來源要求)
// Shows UseCors with CorsPolicyBuilder.
app.UseCors(builder =>
{
builder.AllowAnyOrigin()
.AllowAnyMethod()
.AllowAnyHeader();
});
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseAuthorization();
app.MapControllerRoute(
name: "default",
// pattern: "{controller=Home}/{action=Index}/{id?}");
pattern: "{controller=Home}/{action=Login}/{id?}");
app.Run();

View File

@ -0,0 +1,36 @@
{
"iisSettings": {
"windowsAuthentication": false,
"anonymousAuthentication": true,
"iisExpress": {
"applicationUrl": "http://localhost:2361",
"sslPort": 44352
}
},
"profiles": {
"Parking_spaces": {
"commandName": "Project",
"launchBrowser": true,
"applicationUrl": "http://localhost:5173",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
},
"dotnetRunMessages": true
},
"IIS Express": {
"commandName": "IISExpress",
"launchBrowser": true,
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
},
"Docker": {
"commandName": "Docker",
"launchBrowser": true,
"launchUrl": "{Scheme}://{ServiceHost}:{ServicePort}",
"environmentVariables": {},
"publishAllPorts": true,
"useSSL": true
}
}
}

View File

@ -0,0 +1,53 @@
namespace Parking_spaces.Services;
using Parking_spaces.Authorization;
using Parking_spaces.Entities;
using Parking_spaces.Models;
public interface IUserService
{
AuthenticateResponse? Authenticate(AuthenticateRequest model);
IEnumerable<User> GetAll();
User? GetById(int id);
}
public class UserService : IUserService
{
// users hardcoded for simplicity, store in a db with hashed passwords in production applications
private List<User> _users = new List<User>
{
new User { Id = 1, FirstName = "Developer", LastName = "Manager", Username = "test", Password = "test" },
new User { Id = 2, FirstName = "Developer", LastName = "Engineer", Username = "admin", Password = "admin" }
};
private readonly IJwtUtils _jwtUtils;
public UserService(IJwtUtils jwtUtils)
{
_jwtUtils = jwtUtils;
}
public AuthenticateResponse? Authenticate(AuthenticateRequest model)
{
var user = _users.SingleOrDefault(x => x.Username == model.Username && x.Password == model.Password);
// return null if user not found
if (user == null) return null;
// authentication successful so generate jwt token
var token = _jwtUtils.GenerateJwtToken(user);
return new AuthenticateResponse(user, token);
}
public IEnumerable<User> GetAll()
{
return _users;
}
public User? GetById(int id)
{
return _users.FirstOrDefault(x => x.Id == id);
}
}

View File

@ -0,0 +1,8 @@

@{
ViewData["Title"] = "Bootstrap_test";
Layout = "~/Views/Shared/_Layout_Engineering.cshtml";
}
<h1>Bootstrap_test</h1>

View File

@ -0,0 +1,488 @@
@{
string script = "@";
Layout = "~/Views/Shared/_Layout_Engineering.cshtml";
}
<h1>WEBCAM參數</h1>
<div>
<button class="btn btn-primary" onclick="add_webcam_view.showModal()" id="add_webcam_id">新增攝像頭</button>
<table class="table">
<thead>
<tr>
<th>
停車場位置
</th>
<th>
攝像頭帳號
</th>
<th>
攝像頭密碼
</th>
<th>
IP位置
</th>
<th>
使用Port
</th>
<th>
攝像頭使用模式
</th>
<th>
</th>
</tr>
</thead>
<tbody id="demo">
</tbody>
</table>
</div>
<!--彈跳視窗-->
<div>
<dialog id="add_webcam_view" style="width:80%;">
<div>
<button class="btn btn-danger" style="float:right" onclick="add_webcam_view.close();"> 關閉</button>
停車場位置 :
<select style="width:30%;" id="select_parking_spaces_name_id">
</select></br></br>
攝像頭帳號 : <input type="text" id="add_user_name_text_id" /></br></br>
攝像頭密碼 : <input type="text" id="add_password_text_id" /></br></br>
IP位置 : <input type="text" id="add_ip_text_id" /></br></br>
RTSP使用Port(串流) : <input type="text" id="add_rtsp_port_text_id" /></br></br>
HTTP使用Port(控制) : <input type="text" id="add_http_port_text_id" /></br></br>
攝像頭使用模式 :
<select size="1" id="select_mode_id">
<option value="pass">停車場進出</option>
<option value="violation">判斷違規左右轉 </option>
<option value="car_num_check">數量確認 </option>
</select></br></br>
<button class="btn btn-success" onclick="add_webcam()">上傳</button>
</div>
</dialog>
</div>
<!--獲取資料-->
<script>
var token = localStorage.getItem('token_park_space');
var token_ckeck //= document.getElementById("token_ckeck_id").value
var position //職位
function get_data() {
//token_check = document.getElementById("token_check_id").value
console.log(token_check)
$.ajax({
type: "GET",
url: "http://140.125.20.183:7700/api/Parking_spaces_cam",
data: {},
headers: {
'Authorization': token
},
contentType: "application/json",
success: function (Model) {
console.log(Model)
set_data(Model)
get_data_2()
}
});
}
function get_data_2() {
//token_check = document.getElementById("token_check_id").value
console.log(token_check)
$.ajax({
type: "GET",
url: "http://140.125.20.183:7700/api/Parking_spaces_total_table",
data: {},
headers: {
'Authorization': token
},
contentType: "application/json",
success: function (Model) {
console.log(Model)
set_data_2(Model)
get_data_3()
}
});
}
function get_data_3() {
//token_check = document.getElementById("token_check_id").value
console.log(token_check)
$.ajax({
type: "GET",
url: "http://140.125.20.183:7700/api/Parking_spaces_violation_total_table",
data: {},
headers: {
'Authorization': token
},
contentType: "application/json",
success: function (Model) {
console.log(Model)
set_data_3(Model)
}
});
}
</script>
<!--放置資料-->
<script>
function set_data(Model) {
table = "<tr>";
console.log(Model.length)
if (Model.length > 0) {
for (var i = 0; i < Model.length; i++) {
if (Model[i].parking_spaces_name != null) {
if (parseInt(Model[i].port) > 400) {
table += "<td>" + Model[i].parking_spaces_name + "</td>"
table += "<td>" + Model[i].user_name + "</td>"
table += "<td>" + Model[i].password + "</td>"
table += "<td>" + Model[i].ip + "</td>"
table += "<td>" + Model[i].port + "</td>"
if (Model[i].mode == "pass") { mode = "停車場進出" }
if (Model[i].mode == "violation") { mode = "判斷違規左右轉" }
if (Model[i].mode == "car_num_check") { mode = "數量確認" }
table += "<td>" +mode + "</td>"
table += "<td>" + '<button class="btn btn-outline-success " onclick="CAM_detail(' + "'" + Model[i].parking_spaces_name + ":" + Model[i].ip + ":" + Model[i].port + "'" + ')">詳細</button>'
}
table += "</tr>"
table += "<tr>"
}
}
}
document.getElementById("demo").innerHTML = table
}
function set_data_2(Model) {
var obj = document.getElementById("select_parking_spaces_name_id");
if (Model.length > 0) {
for (var i = 0; i < Model.length; i++) {
if (Model[i].parking_spaces_name != null) {
obj.options.add(new Option(Model[i].parking_spaces_name));
}
}
}
}
function set_data_3(Model) {
var obj = document.getElementById("select_parking_spaces_name_id");
if (Model.length > 0) {
for (var i = 0; i < Model.length; i++) {
if (Model[i].parking_spaces_violation_name != null) {
obj.options.add(new Option(Model[i].parking_spaces_violation_name));
}
}
}
}
</script>
<!--上傳資料-->
<script>
function add_webcam() {
var parking_spaces_name = document.getElementById("select_parking_spaces_name_id").value
var user_name = document.getElementById("add_user_name_text_id").value
var password = document.getElementById("add_password_text_id").value
var ip = document.getElementById("add_ip_text_id").value
var port = document.getElementById("add_rtsp_port_text_id").value
var http_port = document.getElementById("add_http_port_text_id").value
var mode = document.getElementById("select_mode_id").value
if (parseInt(port) > 400) {
var url = `rtsp://${user_name}:${password}@script${ip}:${port}/stream1`
console.log(url)
}
else {
var url = `http://${user_name}:${password}@script${ip}:${port}`
console.log(url)
}
var obj = {
parking_spaces_name: parking_spaces_name,
user_name: user_name,
password: password,
ip: ip,
port: port,
http_port: http_port,
mode: mode,
url: url,
}
var stringify_obj = JSON.stringify(obj);
$.ajax({
type: "Post",
url: "http://140.125.20.183:7700/api/Parking_spaces_cam",
//data: {test_id: test_id, test_date: test_date, test_time: test_time, test_analyst: test_analyst, img: img, data_creat_time: "2022-10-04T18:47:40.887014" },
data: stringify_obj,
contentType: "application/json",
headers: {
'Authorization': token
},
success: function (msg) {
console.log(msg)
add_roi()
add_webcam_view.close()
get_data()
}
});
}
</script>
<!--上傳ROI資料-->
<script>
function add_roi(){
var parking_spaces_name = document.getElementById("select_parking_spaces_name_id").value
var user_name = document.getElementById("add_user_name_text_id").value
var password = document.getElementById("add_password_text_id").value
var ip = document.getElementById("add_ip_text_id").value
var port = document.getElementById("add_rtsp_port_text_id").value
var http_port = document.getElementById("add_http_port_text_id").value
var mode = document.getElementById("select_mode_id").value
if (parseInt(port) > 400) {
var url = `rtsp://${user_name}:${password}@script${ip}:${port}/stream1`
console.log(url)
}
else {
var url = `http://${user_name}:${password}@script${ip}:${port}`
console.log(url)
}
if (mode == "pass") {
var obj = {
parking_spaces_name: parking_spaces_name,
cam_ip: url,
roi_x1: "0",
roi_x2: "100",
roi_y1: "0",
roi_y2: "100",
roi_function: "CAR_ROI_license_plate",
mode: mode,
}
var stringify_obj = JSON.stringify(obj);
$.ajax({
type: "Post",
url: "http://140.125.20.183:7700/api/Parking_spaces_roi_pass",
//data: {test_id: test_id, test_date: test_date, test_time: test_time, test_analyst: test_analyst, img: img, data_creat_time: "2022-10-04T18:47:40.887014" },
data: stringify_obj,
contentType: "application/json",
headers: {
'Authorization': token
},
success: function (msg) {
console.log(msg)
add_ptz()
add_webcam_view.close()
get_data()
}
});
}
if (mode == "violation") {
add_ptz()
}
}
</script>
<!--上傳PTZ資料-->
<script>
function add_ptz() {
var parking_spaces_name = document.getElementById("select_parking_spaces_name_id").value
var user_name = document.getElementById("add_user_name_text_id").value
var password = document.getElementById("add_password_text_id").value
var ip = document.getElementById("add_ip_text_id").value
var port = document.getElementById("add_rtsp_port_text_id").value
var http_port = document.getElementById("add_http_port_text_id").value
var mode = document.getElementById("select_mode_id").value
if (parseInt(port) > 400) {
var url = `rtsp://${user_name}:${password}@script${ip}:${port}/stream1`
console.log(url)
}
else {
var url = `http://${user_name}:${password}@script${ip}:${port}`
console.log(url)
}
if (mode == "pass") {
var obj = {
parking_spaces_name: parking_spaces_name,
rtsp_url: url,
rtsp_port: port,
http_port: http_port,
mode: mode,
img: "",
pan: "0",
titl: "0",
zoom: "0",
create_data_time: "1"
}
var stringify_obj = JSON.stringify(obj);
$.ajax({
type: "Post",
url: "http://140.125.20.183:7700/api/Parking_spaces_cam_ptz_pass",
//data: {test_id: test_id, test_date: test_date, test_time: test_time, test_analyst: test_analyst, img: img, data_creat_time: "2022-10-04T18:47:40.887014" },
data: stringify_obj,
contentType: "application/json",
headers: {
'Authorization': token
},
success: function (msg) {
console.log(msg)
add_webcam_view.close()
get_data()
}
});
}
if (mode == "violation") {
var obj = {
parking_spaces_name: parking_spaces_name,
rtsp_url: url,
rtsp_port: port,
http_port: http_port,
mode: mode,
img: "",
pan: "0",
titl: "0",
zoom: "0",
create_data_time: "1"
}
var stringify_obj = JSON.stringify(obj);
$.ajax({
type: "Post",
url: "http://140.125.20.183:7700/api/Parking_spaces_cam_ptz_violation",
//data: {test_id: test_id, test_date: test_date, test_time: test_time, test_analyst: test_analyst, img: img, data_creat_time: "2022-10-04T18:47:40.887014" },
data: stringify_obj,
contentType: "application/json",
headers: {
'Authorization': token
},
success: function (msg) {
console.log(msg)
add_webcam_view.close()
get_data()
}
});
}
}
</script>
<!--跳轉頁面-->
<script>
function CAM_detail(name) {
window.location = "/Engineering/Engineering_CAM_detail/" + name;
}
</script>
<!--檢查token-->
<script>
function token_check() {
// 检查本地存储中是否存在JWT令牌
var token = localStorage.getItem('token_park_space');
console.log(token)
$.ajax({
type: "GET",
url: 'http://140.125.20.183:7700/Users/token_check',
headers: {
'Authorization': token
},
success: function (response) {
console.log(response)
token_check = "true"
from_token_import_id()
},
error: function (xhr) {
console.log("1")
token_check = "false"
window.location.href = '/';
//get_data()
// 处理错误响应,例如跳转到未授权页面
//window.location.href = 'https://example.com/unauthorized_page';
}
});
}
function from_token_import_id() {
var token = localStorage.getItem('token_park_space');
$.ajax({
type: "GET",
url: 'http://140.125.20.183:7700/Users/token-' + token,
headers: {
'Authorization': token
},
success: function (response) {
console.log(response)
from_id_import_user_data(response)
}
});
}
function from_id_import_user_data(id) {
var token = localStorage.getItem('token_park_space');
$.ajax({
type: "GET",
url: 'http://140.125.20.183:7700/Users/user_id-' + id,
headers: {
'Authorization': token
},
success: function (model) {
model = model.result
position = model.lastname
console.log(position)
if (position == "engineer"){
get_data()
}
else{
window.location.href = '/';
}
}
});
}
</script>
<!--開機自啟-->
<script>
window.onload = token_check;
</script>

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,222 @@

@{
ViewData["Title"] = "Engineering_Index";
Layout = "~/Views/Shared/_Layout_Engineering.cshtml";
}
<h1>工程模式</h1>
<div>
<table class="table">
<thead>
<tr>
<th>
演算法名稱
</th>
<th>
狀態
</th>
<th>
啟動時間
</th>
<th>
</th>
</tr>
</thead>
<tbody id="demo">
</tbody>
</table>
</div>
<!--獲取資料-->
<script>
var token = localStorage.getItem('token_park_space');
var token_ckeck //確認token
var position //職位
function get_data(){
$.ajax({
type: "GET",
url: "http://140.125.20.183:7700/api/Parking_space_algorithm",
data: {},
headers: {
'Authorization': token
},
contentType: "application/json",
success: function (Model) {
console.log(Model)
put_data(Model)
}
});
}
function get_data_1() {
$.ajax({
type: "GET",
url: "http://140.125.20.183:7700/api/Parking_space_algorithm",
data: {},
headers: {
'Authorization': token
},
contentType: "application/json",
success: function (Model) {
console.log(Model)
set_data(Model)
}
});
}
</script>
<!--編輯資料-->
<script>
function put_data(Model){
if (Model.length > 0) {
for (var i = 0; i < Model.length; i++) {
if (Model[i].algorithm_name != null) {
data_1 = {
"algorithm_name": Model[i].algorithm_name,
"state": "False",
"run_time": Model[i].run_time,
"algorithm_serial_num": Model[i].algorithm_serial_num
}
var stringify_obj = JSON.stringify(data_1);
$.ajax({
type: "PUT",
url: "http://140.125.20.183:7700/api/Parking_space_algorithm/" + Model[i].algorithm_serial_num,
data: stringify_obj,
headers: {
'Authorization': token
},
contentType: "application/json",
success: function (Model) {
setTimeout('get_data_1()', 1000);
//console.log(Model)
//window.location.reload();
}
});
}
}
}
}
</script>
<!--放置資料-->
<script>
var c=0
function set_data(Model) {
table = "<tr>";
if (Model.length > 0) {
for (var i = 0; i < Model.length; i++) {
if (Model[i].algorithm_name != null) {
table += "<td>" + Model[i].algorithm_name + "</td>"
var state="未啟動"
if (Model[i].state=="True"){
state = "啟動"
}
table += "<td>" + state + "</td>"
table += "<td>" + Model[i].run_time + "</td>"
table += "<td>" + "</td>"
}
table += "</tr>"
table += "<tr>"
}
}
document.getElementById("demo").innerHTML = table
if (c<10){
setTimeout('get_data_1()', 1000);
c = c + 1
}
}
</script>
<!--檢查token-->
<script>
function token_check() {
// 检查本地存储中是否存在JWT令牌
var token = localStorage.getItem('token_park_space');
console.log(token)
$.ajax({
type: "GET",
url: 'http://140.125.20.183:7700/Users/token_check',
headers: {
'Authorization': token
},
success: function (response) {
console.log(response)
token_check = "true"
from_token_import_id()
},
error: function (xhr) {
token_check = "false"
window.location.href = '/';
// 处理错误响应,例如跳转到未授权页面
//window.location.href = 'https://example.com/unauthorized_page';
}
});
}
function from_token_import_id() {
var token = localStorage.getItem('token_park_space');
$.ajax({
type: "GET",
url: 'http://140.125.20.183:7700/Users/token-' + token,
headers: {
'Authorization': token
},
success: function (response) {
console.log(response)
from_id_import_user_data(response)
}
});
}
function from_id_import_user_data(id) {
var token = localStorage.getItem('token_park_space');
$.ajax({
type: "GET",
url: 'http://140.125.20.183:7700/Users/user_id-' + id,
headers: {
'Authorization': token
},
success: function (model) {
model = model.result
position = model.lastname
console.log(position)
if (position == "engineer") {
get_data()
}
else {
window.location.href = '/';
}
}
});
}
</script>
<!--開機自啟-->
<script>
window.onload = token_check;
</script>

View File

@ -0,0 +1,118 @@

@{
ViewData["Title"] = "Engineering_Index";
Layout = "~/Views/Shared/_Layout_Engineering.cshtml";
}
<h1>工程模式</h1>
<div>
<button class="btn btn-primary" onclick="webcam_view()">查看WEBCAM</button>
<button class="btn btn-primary" onclick="LED_view()">字幕機顯示</button>
<button class="btn btn-primary" onclick="Violation_view()">違規區域</button>
</div>
<!--跳轉頁面-->
<script>
function webcam_view(){
window.location = "/Engineering/Engineering_CAM" ;
}
function LED_view() {
window.location = "/Engineering/Engineering_LED";
}
function Violation_view() {
window.location = "/Engineering/Engineering_Violation";
}
</script>
<!--檢查token-->
<script>
function token_check() {
// 检查本地存储中是否存在JWT令牌
var token = localStorage.getItem('token_park_space');
console.log(token)
$.ajax({
type: "GET",
url: 'http://140.125.20.183:7700/Users/token_check',
headers: {
'Authorization': token
},
success: function (response) {
console.log(response)
token_check = "true"
from_token_import_id()
},
error: function (xhr) {
token_check = "false"
window.location.href = '/';
// 处理错误响应,例如跳转到未授权页面
//window.location.href = 'https://example.com/unauthorized_page';
}
});
}
function from_token_import_id() {
var token = localStorage.getItem('token_park_space');
$.ajax({
type: "GET",
url: 'http://140.125.20.183:7700/Users/token-' + token,
headers: {
'Authorization': token
},
success: function (response) {
console.log(response)
from_id_import_user_data(response)
}
});
}
function from_id_import_user_data(id) {
var token = localStorage.getItem('token_park_space');
$.ajax({
type: "GET",
url: 'http://140.125.20.183:7700/Users/user_id-' + id,
headers: {
'Authorization': token
},
success: function (model) {
model = model.result
position = model.lastname
console.log(position)
if (position == "engineer") {
get_data()
}
else {
window.location.href = '/';
}
}
});
}
</script>
<!--開機自啟-->
<script>
window.onload = token_check;
</script>

View File

@ -0,0 +1,180 @@

@{
ViewData["Title"] = "Engineering_LED";
Layout = "~/Views/Shared/_Layout_Engineering.cshtml";
}
<h1>LED 字幕機</h1>
<div>
<button class="btn btn-primary" onclick="add_webcam_view.showModal()" id="add_webcam_id">新增字幕機 </button>
<table class="table">
<thead>
<tr>
<th>
停車場位置
</th>
<th>
字幕機IP
</th>
<th>
字幕機 PORT
</th>
<th>
顯示參數
</th>
<th>
</th>
</tr>
</thead>
<tbody id="demo">
</tbody>
</table>
</div>
<!--獲取資料-->
<script>
var token = localStorage.getItem('token_park_space');
var token_ckeck //確認token
var position //職位
function get_data(){
$.ajax({
type: "GET",
url: "http://140.125.20.183:7700/api/Parking_spaces_lcd_instand",
data: {},
headers: {
'Authorization': token
},
contentType: "application/json",
success: function (Model) {
console.log(Model)
set_data(Model)
}
});
}
</script>
<!--放置資料-->
<script>
function set_data(Model){
table = "<tr>";
console.log(Model.length)
if (Model.length > 0) {
for (var i = 0; i < Model.length; i++) {
if (Model[i].parking_spaces_name != null) {
table += "<td>" + Model[i].parking_spaces_name + "</td>"
var NewArray = Model[i].lcd_ip.split(":");
table += "<td>" + NewArray[0] + "</td>"
table += "<td>" + NewArray[1] + "</td>"
table += "<td>" + Model[i].parking_space_amount + "</td>"
table += "<td>" + '<button class="btn btn-outline-success " onclick="LED_detail(' + "'" + Model[i].parking_spaces_name + "'" + ')">詳細</button>'
}
table += "</tr>"
table += "<tr>"
}
}
document.getElementById("demo").innerHTML = table
}
</script>
<!--跳轉頁面-->
<script>
function LED_detail(name) {
window.location = "/Engineering/Engineering_LED_detail/" + name;
}
</script>
<!--檢查token-->
<script>
function token_check() {
// 检查本地存储中是否存在JWT令牌
var token = localStorage.getItem('token_park_space');
console.log(token)
$.ajax({
type: "GET",
url: 'http://140.125.20.183:7700/Users/token_check',
headers: {
'Authorization': token
},
success: function (response) {
console.log(response)
token_check = "true"
from_token_import_id()
},
error: function (xhr) {
token_check = "false"
window.location.href = '/';
// 处理错误响应,例如跳转到未授权页面
//window.location.href = 'https://example.com/unauthorized_page';
}
});
}
function from_token_import_id() {
var token = localStorage.getItem('token_park_space');
$.ajax({
type: "GET",
url: 'http://140.125.20.183:7700/Users/token-' + token,
headers: {
'Authorization': token
},
success: function (response) {
console.log(response)
from_id_import_user_data(response)
}
});
}
function from_id_import_user_data(id) {
var token = localStorage.getItem('token_park_space');
$.ajax({
type: "GET",
url: 'http://140.125.20.183:7700/Users/user_id-' + id,
headers: {
'Authorization': token
},
success: function (model) {
model = model.result
position = model.lastname
console.log(position)
if (position == "engineer") {
get_data()
}
else {
window.location.href = '/';
}
}
});
}
</script>
<!--開機自啟-->
<script>
window.onload = token_check;
</script>

View File

@ -0,0 +1,271 @@

@{
ViewData["Title"] = "Engineering_LED_detail";
Layout = "~/Views/Shared/_Layout_Engineering.cshtml";
string parking_spaces_name = ViewBag.parking_spaces_name;
}
<input type="hidden" id="parking_spaces_name_id" value=@parking_spaces_name />
<h1>@parking_spaces_name 字幕機</h1>
<div>
<p>
設定LED字幕機參數 :</br>
預設密碼:26888</br>
網路參數高級設置:密碼需要與路由器的子網路遮罩一樣(例:255.255.255.0 , 密碼就為ffffff00)
</p>
<table class="table">
<thead>
<tr>
<th>
停車場位置
</th>
<th>
字幕機IP
</th>
<th>
字幕機 PORT
</th>
<th>
顯示參數
</th>
<th>
</th>
</tr>
</thead>
<tbody id="demo">
</tbody>
</table>
</div>
<!--獲取資料-->
<script>
var token = localStorage.getItem('token_park_space');
var token_ckeck //確認token
var position //職位
var parking_spaces_name = document.getElementById("parking_spaces_name_id").value
function get_data() {
$.ajax({
type: "GET",
url: "http://140.125.20.183:7700/api/Parking_spaces_lcd_instand",
data: {},
headers: {
'Authorization': token
},
contentType: "application/json",
success: function (Model) {
console.log(Model)
set_data(Model)
}
});
}
</script>
<!--放置資料-->
<script>
function set_data(Model) {
table = "<tr>";
console.log(Model.length)
if (Model.length > 0) {
for (var i = 0; i < Model.length; i++) {
if (Model[i].parking_spaces_name == parking_spaces_name) {
table += "<td>" + Model[i].parking_spaces_name + "</td>"
var NewArray = Model[i].lcd_ip.split(":");
table += "<td>" + NewArray[0] + "</td>"
table += "<td>" + NewArray[1] + "</td>"
table += "<td>" + '<input type="text" id = "parking_space_amount_id" value =' + Model[i].parking_space_amount + ' />' + "</td > "
table += "<td>" + '<button class="btn btn-outline-warning " onclick="Update_detail(' + "'" + Model[i].parking_spaces_name + "'" + ')">更新並上傳</button>'
}
table += "</tr>"
table += "<tr>"
}
}
document.getElementById("demo").innerHTML = table
}
</script>
<!--更新並上傳-->
<script>
function Update_detail(parking_spaces_name){
$.ajax({
type: "GET",
url: "http://140.125.20.183:7700/api/Parking_spaces_total_table/" + parking_spaces_name,
data: {},
headers: {
'Authorization': token
},
contentType: "application/json",
success: function (Model) {
console.log(Model)
Update_detail_1(Model)
}
});
}
function Update_detail_1(Model){
var parking_spaces_now_num = document.getElementById("parking_space_amount_id").value
Model.parking_spaces_now_num = parking_spaces_now_num
var stringify_obj = JSON.stringify(Model);
$.ajax({
type: "PUT",
url: "http://140.125.20.183:7700/api/Parking_spaces_total_table/" + parking_spaces_name,
data: stringify_obj,
headers: {
'Authorization': token
},
contentType: "application/json",
success: function (Model) {
console.log(Model)
Update_detail_2()
//window.location.reload();
}
});
}
function Update_detail_2() {
$.ajax({
type: "GET",
url: "http://140.125.20.183:7700/api/Parking_spaces_lcd_instand/parking_space_area-" + parking_spaces_name,
data: {},
headers: {
'Authorization': token
},
contentType: "application/json",
success: function (Model) {
console.log(Model)
if (Model.length > 0) {
for (var i = 0; i < Model.length; i++) {
if (Model[i].parking_spaces_name == parking_spaces_name) {
Update_detail_3(Model[i])
}
}
}
//Update_detail_1(Model)
}
});
}
function Update_detail_3(Model) {
var parking_spaces_now_num = document.getElementById("parking_space_amount_id").value
Model.parking_space_amount = parking_spaces_now_num
var stringify_obj = JSON.stringify(Model);
$.ajax({
type: "PUT",
url: "http://140.125.20.183:7700/api/Parking_spaces_lcd_instand/" + Model.lcd_ip,
data: stringify_obj,
headers: {
'Authorization': token
},
contentType: "application/json",
success: function (Model) {
console.log(Model)
//Update_detail_1(Model)
window.location.reload();
}
});
}
</script>
<!--檢查token-->
<script>
function token_check() {
// 检查本地存储中是否存在JWT令牌
var token = localStorage.getItem('token_park_space');
console.log(token)
$.ajax({
type: "GET",
url: 'http://140.125.20.183:7700/Users/token_check',
headers: {
'Authorization': token
},
success: function (response) {
//console.log(response)
token_check = "true"
from_token_import_id()
},
error: function (xhr) {
token_check = "false"
window.location.href = '/';
// 处理错误响应,例如跳转到未授权页面
//window.location.href = 'https://example.com/unauthorized_page';
}
});
}
function from_token_import_id() {
var token = localStorage.getItem('token_park_space');
$.ajax({
type: "GET",
url: 'http://140.125.20.183:7700/Users/token-' + token,
headers: {
'Authorization': token
},
success: function (response) {
//console.log(response)
from_id_import_user_data(response)
}
});
}
function from_id_import_user_data(id) {
var token = localStorage.getItem('token_park_space');
$.ajax({
type: "GET",
url: 'http://140.125.20.183:7700/Users/user_id-' + id,
headers: {
'Authorization': token
},
success: function (model) {
model = model.result
position = model.lastname
console.log(position)
if (position == "engineer") {
get_data()
}
else {
window.location.href = '/';
}
}
});
}
</script>
<!--開機自啟-->
<script>
window.onload = token_check;
</script>

View File

@ -0,0 +1,170 @@

@{
ViewData["Title"] = "Engineering_Violation";
Layout = "~/Views/Shared/_Layout_Engineering.cshtml";
}
<h1 >校園總違規區域</h1>
<div class="size2">
<button class="btn btn-primary" onclick="add_violation_view.showModal();map_show_1()" id="add_violation_id">新增違規區域</button>
<!--<button class="btn btn-primary" onclick="add_park_space_view.showModal();map_show()" id="add_park_space_id">新增停車區</button>
<button class="btn btn-primary" onclick="add_violation_view.showModal();map_show_1()" id="add_violation_id">新增違規區域</button>
<button style="height:30px;float:right " class="btn btn-outline-secondary" onclick="serch_click()">搜尋</button>
<input type="text" style="float:right" placeholder="請輸入您的車牌" id="serch_text_id" />-->
<table class="table">
<thead>
<tr>
<th>
總違規區域
</th>
<th>
</th>
</tr>
</thead>
<tbody id="demo">
</tbody>
</table>
</div>
<!--獲取資料-->
<script>
var token_ckeck //= document.getElementById("token_ckeck_id").value
var position //職位
function get_data() {
console.log("start")
//token_check = document.getElementById("token_check_id").value
console.log(token_check)
$.ajax({
type: "GET",
url: "http://140.125.20.183:7700/api/Parking_spaces_violation_total_table",
data: {},
contentType: "application/json",
success: function (Model) {
console.log(Model)
set_data(Model)
}
});
}
</script>
<!--放置資料-->
<script>
function set_data(Model){
table = "<tr>";
//console.log(Model.length)
if (Model.length > 0) {
for (var i = 0; i < Model.length; i++) {
if (Model[i].parking_spaces_violation_name != null) {
table += "<td>" + Model[i].parking_spaces_violation_name + "</td>"
table += "<td>"
if (token_check == "true") {
table += '<button class="btn btn-outline-success " onclick="detail_data(' + "'" + Model[i].parking_spaces_violation_name + "'" + ')">詳細</button>' + ' ' + ' '
}
}
table += "</tr>"
table += "<tr>"
}
}
document.getElementById("demo").innerHTML = table
}
</script>
<!--前往詳細頁面-->
<script>
function detail_data(name) {
window.location = "/Engineering/Single_violation_detail/" + name;
}
</script>
<!--檢查token-->
<script>
function token_check() {
// 检查本地存储中是否存在JWT令牌
var token = localStorage.getItem('token_park_space');
console.log(token)
$.ajax({
type: "GET",
url: 'http://140.125.20.183:7700/Users/token_check',
headers: {
'Authorization': token
},
success: function (response) {
console.log(response)
token_check = "true"
from_token_import_id()
},
error: function (xhr) {
token_check = "false"
window.location.href = '/';
// 处理错误响应,例如跳转到未授权页面
//window.location.href = 'https://example.com/unauthorized_page';
}
});
}
function from_token_import_id() {
var token = localStorage.getItem('token_park_space');
$.ajax({
type: "GET",
url: 'http://140.125.20.183:7700/Users/token-' + token,
headers: {
'Authorization': token
},
success: function (response) {
console.log(response)
from_id_import_user_data(response)
}
});
}
function from_id_import_user_data(id) {
var token = localStorage.getItem('token_park_space');
$.ajax({
type: "GET",
url: 'http://140.125.20.183:7700/Users/user_id-' + id,
headers: {
'Authorization': token
},
success: function (model) {
model = model.result
position = model.lastname
console.log(position)
if (position == "engineer") {
get_data()
}
else {
window.location.href = '/';
}
}
});
}
</script>
<!--開機自啟-->
<script>
window.onload = token_check;
</script>

View File

@ -0,0 +1,439 @@
@{
ViewData["Title"] = "Parking_spaces_total_table";
Layout = "~/Views/Shared/_Layout_Engineering.cshtml";
var token_check_1 = ViewBag.token_check;
}
<input type="hidden" id="token_check_id" value=@token_check_1 />
<h1 id="position_id">校園總停車區域</h1>
<div class="size2">
<button class="btn btn-primary" onclick="add_park_space_view.showModal();map_show()" id="add_park_space_id">新增停車區</button>
<!--<button class="btn btn-primary" onclick="add_violation_view.showModal();map_show_1()" id="add_violation_id">新增違規區域</button>-->
<button style="height:30px;float:right " class="btn btn-outline-secondary" onclick="serch_click()">搜尋</button>
<input type="text" style="float:right" placeholder="請輸入您的車牌" id="serch_text_id" />
<table class="table">
<thead>
<tr>
<th>
停車區域
</th>
<th>
總車位
</th>
<th>
剩餘車位
</th>
<th>
</th>
</tr>
</thead>
<tbody id="demo">
</tbody>
</table>
</div>
<!-- css -->
<link rel="stylesheet"
href="https://unpkg.com/leaflet@1.6.0/dist/leaflet.css"
integrity="sha512-xwE/Az9zrjBIphAcBb3F6JVqxf46+CDLwfLMHloNu6KEQCAWi6HcDUbeOfBIptF7tcCzusKFjFw2yuvEpDL9wQ=="
crossorigin="" />
<!-- js -->
<script src="https://unpkg.com/leaflet@1.6.0/dist/leaflet.js"
integrity="sha512-gZwIG9x3wUXg2hdXF6+rVkLF/0Vi9U8D2Ntg4Ga5I5BZpVkVxlJWbSQtXPSiUTtC0TjtGOmxa1AJPuV0CPthew=="
crossorigin="">
</script>
<style>
#myMap {
height: 300px;
}
#myMap_1 {
height: 300px;
}
</style>
<!--新增停車場-彈跳視窗-->
<div>
<dialog id="add_park_space_view" style="width:100%;">
<div>
<button class="btn btn-danger" style="float:right" onclick="add_park_space_view.close();"> 關閉</button>
停車區名稱 : <input type="text" id="add_park_space_name_text_id" /></br></br>
停車位數量 : <input type="text" id="add_park_space_num_text_id" /></br></br>
<button class="btn btn-outline-success" onclick="GPS_text_clicked()">停車場位置</button>緯度<input type="text" size="10" id="add_park_space_GPS_lat_text_id" />經度<input type="text" size="10" id="add_park_space_GPS_lng_text_id" /></br></br>
<div id="myMap"></div>
<button class="btn btn-success" onclick="add_park_space()">上傳</button>
</div>
</dialog>
</div>
<!--新增違規區域-彈跳視窗-->
<div>
<dialog id="add_violation_view" style="width:100%;">
<div>
<button class="btn btn-danger" style="float:right" onclick="add_violation_view.close();"> 關閉</button>
違規區域名稱 : <input type="text" id="add_violation_name_text_id" /></br></br>
<button class="btn btn-outline-success" onclick="GPS_text_clicked()">停車場位置</button>緯度<input type="text" size="10" id="add_violation_GPS_lat_text_id" />經度<input type="text" size="10" id="add_violation_GPS_lng_text_id" /></br></br>
<div id="myMap_1"></div>
<button class="btn btn-success" onclick="add_violation()">上傳</button>
</div>
</dialog>
</div>
<!--map_show_停車場位置-->
<script>
var map
let lat ,lng
function map_show() {
var map_center = [23.691951, 120.535318]
map = L.map("myMap", {
center: map_center,
//center: seriesData,
zoom: 17
});
// 載入圖資
L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
attribution: '&copy; <a href="http://osm.org/copyright">OpenStreetMap</a> contributors'
}).addTo(map);
const popup = L.popup();
function onMapClick(e) {
lat = e.latlng.lat; // 緯度
lng = e.latlng.lng; // 經度
popup
.setLatLng(e.latlng)
.setContent(`緯度:${lat}<br/>經度:${lng}`)
.openOn(map);
console.log(lat, lng)
}
map.on('click', onMapClick);
}
var map_1
function map_show_1() {
var map_center = [23.691951, 120.535318]
map_1 = L.map("myMap_1", {
center: map_center,
//center: seriesData,
zoom: 17
});
// 載入圖資
L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
attribution: '&copy; <a href="http://osm.org/copyright">OpenStreetMap</a> contributors'
}).addTo(map_1);
const popup = L.popup();
function onMapClick(e) {
lat = e.latlng.lat; // 緯度
lng = e.latlng.lng; // 經度
popup
.setLatLng(e.latlng)
.setContent(`緯度:${lat}<br/>經度:${lng}`)
.openOn(map_1);
console.log(lat, lng)
}
map_1.on('click', onMapClick);
}
</script>
<!--紀錄位置-->
<script>
function GPS_text_clicked(){
document.getElementById("add_park_space_GPS_lat_text_id").value=lat
document.getElementById("add_park_space_GPS_lng_text_id").value=lng
}
</script>
<!--顯示車輛位置-彈跳視窗-->
<div>
<dialog id="serch_view" style="width:100%;">
<div>
<button class="btn btn-danger" style="float:right" onclick="serch_view.close();"> 關閉</button>
停車區名稱 : <input type="text" id="park_space_name_text_id" /> </br></br>
車牌號碼 : <input type="text" id="license_plate_number_text_id" /></br></br>
圖 片 : <img id="car_img_text_id" style="width:30%" /></br></br>
進入時間 : <input type="text" id="in_time_text_id" /></br></br>
</div>
</dialog>
</div>
<!--透過車牌號碼搜尋-->
<script>
function serch_click() {
var license_plate_number = document.getElementById("serch_text_id").value
$.ajax({
type: "GET",
url: "http://140.125.20.183:7700/api/Parking_spaces_instant/license_plate_number-" + license_plate_number,
data: {},
contentType: "application/json",
success: function (Model) {
console.log(Model)
document.getElementById("park_space_name_text_id").value = Model[0].parking_spaces_name
document.getElementById("license_plate_number_text_id").value = Model[0].license_plate_number
document.getElementById("car_img_text_id").src = Model[0].car_img
document.getElementById("in_time_text_id").value = Model[0].in_time
serch_view.showModal()
//set_data(Model)
}
});
}
</script>
<!--獲取資料-->
<script>
var token_ckeck //= document.getElementById("token_ckeck_id").value
var position //職位
function get_data(){
console.log("start")
//token_check = document.getElementById("token_check_id").value
console.log(token_check)
$.ajax({
type: "GET",
url: "http://140.125.20.183:7700/api/Parking_spaces_total_table",
data: {},
contentType: "application/json",
success: function (Model) {
//console.log(Model)
set_data(Model)
}
});
}
</script>
<!--放置資料-->
<script>
function set_data(Model){
if(token_check == "true"){
document.getElementById("add_park_space_id").style.display= "block"
}
else{
document.getElementById("add_park_space_id").style.display = "none"
}
if (position == "engineer"){
document.getElementById("position_id").innerHTML = "<p " + ' onclick="engineer_mode()"' + '>校園總停車區域-工程模式</p>'
}
else if (position == "manager") {
//document.getElementById("position_id").innerHTML = "<p " + ' onclick="manager_mode()"' + '>校園總停車區域-管理者模式</p>'
document.getElementById("position_id").innerHTML = '校園總停車區域-管理者模式'
}
else{
document.getElementById("position_id").innerHTML ='校園總停車區域'
}
table ="<tr>";
//console.log(Model.length)
if (Model.length>0){
for (var i=0 ;i<Model.length;i++){
if (Model[i].parking_spaces_name!=null){
table += "<td>" + Model[i].parking_spaces_name +"</td>"
table += "<td id='" + Model[i].parking_spaces_name + "_total'>" + Model[i].parking_spaces_total_num + "</td>"
table += "<td id='" + Model[i].parking_spaces_name + "_total'>" + Model[i].parking_spaces_now_num + "</td>"
//table += "<td id='" + Model[i].parking_spaces_name + "_now'>" + "</td>"
//get_single_parking_space_car(Model[i].parking_spaces_name)
//table += "<td>" + '<button class="btn btn-danger " onclick="delet_data(' + "'" + Model[i].parking_spaces_name + "'" + ')">刪除</button>'
table += "<td>"
if (token_check == "true") {
table += '<button class="btn btn-outline-success " onclick="detail_data(' + "'" + Model[i].parking_spaces_name + "'" + ')">詳細</button>' + ' ' + ' '
}
//table += "<td>" + '<button class="btn btn-outline-success " onclick="detail_data(' + "'" + Model[i].parking_spaces_name + "'" + ')">詳細</button>' +' '+' '
table += '<button class="btn btn-outline-warning " onclick="map_data(' + "'" + Model[i].parking_spaces_name + "'" + ')">地圖</button>' + "</td>"
}
table += "</tr>"
table += "<tr>"
}
}
document.getElementById("demo").innerHTML = table
}
</script>
<!--獲取當下停車數量-->
<script>
function get_single_parking_space_car(name){
$.ajax({
type: "GET",
url: "http://140.125.20.183:7700/api/Parking_spaces_instant/parking_space_area-" + name,
data: {},
contentType: "application/json",
success: function (Model) {
var total = document.getElementById(name+"_total").innerHTML
console.log(total)
var now = Model.length
document.getElementById(name + "_now").innerHTML = total - now
}
});
console.log()
}
</script>
<!--上傳資料-->
<script>
function add_park_space(){
var parking_spaces_name = document.getElementById("add_park_space_name_text_id").value;
var parking_spaces_total_num = document.getElementById("add_park_space_num_text_id").value;
var latitude = document.getElementById("add_park_space_GPS_lat_text_id").value;
var longitude = document.getElementById("add_park_space_GPS_lng_text_id").value;
var obj = { parking_spaces_name: parking_spaces_name, parking_spaces_total_num: parking_spaces_total_num, longitude: longitude, latitude: latitude }
var stringify_obj = JSON.stringify(obj);
$.ajax({
type: "POST",
url: "http://140.125.20.183:7700/api/Parking_spaces_total_table",
//url: "http://140.125.20.183:7700/api/Postural_Analysis_1",
//data: {test_id: test_id, test_date: test_date, test_time: test_time, test_analyst: test_analyst, img: img, data_creat_time: "2022-10-04T18:47:40.887014" },
data: stringify_obj,
contentType: "application/json",
success: function (msg) {
console.log(msg)
add_park_space_view.close()
alert("上傳完成");
get_data()
//test_upload_bt_2()
//wait_view()
}
});
}
</script>
<!--刪除資料-->
<script>
function delet_data(name){
$.ajax({
type: "DELETE",
url: "http://140.125.20.183:7700/api/Parking_spaces_total_table/"+name,
data: {},
contentType: "application/json",
success: function (msg) {
console.log(msg)
get_data()
}
});
}
</script>
<!--前往詳細頁面-->
<script>
function detail_data(name){
window.location = "/Park_spaces/Single_parking_spaces_detail/" + name;
}
function map_data(name) {
window.location = "/Park_spaces/Single_parking_spaces_map/" + name;
}
function engineer_mode() {
window.location = "/Engineering/Engineering_Index";
}
</script>
<!--檢查token-->
<script>
function token_check() {
// 检查本地存储中是否存在JWT令牌
var token = localStorage.getItem('token_park_space');
console.log(token)
$.ajax({
type: "GET",
url: 'http://140.125.20.183:7700/Users/token_check',
headers: {
'Authorization': token
},
success: function (response) {
console.log(response)
token_check = "true"
from_token_import_id()
},
error: function (xhr) {
token_check = "false"
get_data()
// 处理错误响应,例如跳转到未授权页面
//window.location.href = 'https://example.com/unauthorized_page';
}
});
}
function from_token_import_id(){
var token = localStorage.getItem('token_park_space');
$.ajax({
type: "GET",
url: 'http://140.125.20.183:7700/Users/token-' + token,
headers: {
'Authorization': token
},
success: function (response) {
console.log(response)
from_id_import_user_data(response)
}
});
}
function from_id_import_user_data(id){
var token = localStorage.getItem('token_park_space');
$.ajax({
type: "GET",
url: 'http://140.125.20.183:7700/Users/user_id-' + id,
headers: {
'Authorization': token
},
success: function (model) {
model = model.result
position = model.lastname
console.log(position)
if (position == "engineer") {
get_data()
}
else {
window.location.href = '/';
}
}
});
}
</script>
<!--開機自啟-->
<script>
window.onload = token_check;
</script>

View File

@ -0,0 +1,328 @@

@{
ViewData["Title"] = "Single_violation_detail";
Layout = "~/Views/Shared/_Layout_Engineering.cshtml";
var parking_spaces_name = ViewBag.parking_spaces_name;
}
<input type="hidden" id="parking_spaces_name_id" value=@parking_spaces_name />
<h1>違規車輛</h1>
<div class="size2">
<table class="table">
<thead>
<tr>
<th>
違規區域
</th>
<th>
車牌號碼
</th>
<!--<th>
進入圖片
</th>
<th>
違規圖片
</th>-->
<th>
時間
</th>
<th></th>
</tr>
</thead>
<tbody id="demo">
</tbody>
</table>
</div>
<!--車輛詳細-彈跳視窗-->
<div>
<dialog id="detail_car_data_view" style="width:100%;">
<table class="table">
<button class="btn btn-danger" style="float:right" onclick="detail_car_data_view.close();"> 關閉 </button>
<button class="btn btn-warning" style="float:right" onclick="updata_violation_car_get()"> 更新資料 </button><p></p>
<thead>
<tr>
<th>
違規區域
</th>
<th>
車牌號碼
</th>
<th>
進入圖片
</th>
<th>
違規圖片
</th>
<th>
時間
</th>
</tr>
</thead>
<tbody id="detail_car_data">
</tbody>
</table>
<button class="btn btn-outline-success" style="float:left" onclick="previous_detail_data()"> Previous</button>
<button class="btn btn-outline-success" style="float:right" onclick="next_detail_data()"> Next </button>
</dialog>
</div>
<!--獲取資料-->
<script>
var All_Model
var serial_number=0
function get_data() {
var name = document.getElementById("parking_spaces_name_id").value
//console.log(name)
$.ajax({
type: "GET",
url: "http://140.125.20.183:7700/api/Violation_car_table/violation_location_name-" + name,
data: {},
contentType: "application/json",
success: function (Model) {
//console.log(Model)
All_Model = Model
set_data(Model)
}
});
}
</script>
<!--放置資料-->
<script>
function set_data(Model) {
table = "<tr>";
console.log(Model.length)
if (Model.length > 0) {
for (var i = 0; i < Model.length; i++) {
if (Model[i].violation_location_name != null) {
table += "<td>" + Model[i].violation_location_name + "</td>"
table += "<td>" + Model[i].license_plate_number + "</td>"
//table += "<td>" + "</td>"
//table += "<td>" + "</td>"
// table += "<td>" + "<img src=" + Model[i].car_start_img + ' style="width:100%"' + ">" + "</td>"
// table += "<td>" + "<img src=" + Model[i].car_end_img + ' style="width:100% "' + ">" + "</td>"
// 将字符串转换为 Date 对象
var timestampDt = new Date(Model[i].create_data_time);
// 转换为其他格式
var options = { year: 'numeric', month: '2-digit', day: '2-digit', hour: '2-digit', minute: '2-digit', second: '2-digit' };
var formattedDate = timestampDt.toLocaleDateString('en-US', options);
table += "<td>" + formattedDate + "</td>"
table += "<td>" + '<button class="btn btn-outline-success" onclick="detail_data(' + "'" + Model[i].violation_location_name + "','" + i+ "','" + Model[i].create_data_time + "'" + ')">詳細</button>'
table += '<button class="btn btn-danger " onclick="delet_data(' + "'" + Model[i].violation_location_name + "','" + Model[i].license_plate_number + "','" + Model[i].create_data_time + "'" + ')">刪除</button>' + "</td>"
}
table += "</tr>"
table += "<tr>"
}
}
document.getElementById("demo").innerHTML = table
}
</script>
<!--更新違規車輛資料-->
<script>
function updata_violation_car_get() {
var violation_location_name = document.getElementById('parking_spaces_name_id').value
var time = document.getElementById('create_data_time_id').innerHTML
console.log(time)
$.ajax({
type: "GET",
url: "http://140.125.20.183:7700/api/Violation_car_table/location_nam-" + violation_location_name + "-time-" + time,
data: {},
contentType: "application/json",
success: function (Model) {
//console.log(Model)
updata_violation_car_put(Model)
}
});
}
function updata_violation_car_put(Model) {
var violation_location_name = document.getElementById('parking_spaces_name_id').value
var time = document.getElementById('create_data_time_id').innerHTML
var license_plate_number = document.getElementById('license_plate_number_text_id').value
Model.license_plate_number = license_plate_number
//console.log(Model)
var stringify_obj = JSON.stringify(Model);
$.ajax({
type: "PUT",
url: "http://140.125.20.183:7700/api/Violation_car_table/location_nam-" + violation_location_name + "-time-" + time,
data: stringify_obj,
contentType: "application/json",
success: function (Model) {
// console.log(Model)
//updata_violation_car_put(Model)
}
});
}
</script>
<!--下一筆資料-->
<script>
function next_detail_data() {
serial_number = Number(serial_number) + 1
if (serial_number >= All_Model.length) {
window.alert('無下一筆資料')
serial_number = All_Model.length-1
return
}
//console.log(serial_number)
//console.log(All_Model[serial_number])
detail_data(All_Model[serial_number]['violation_location_name'], serial_number, All_Model[serial_number]['create_data_time'])
}
</script>
<!--上一筆資料-->
<script>
function previous_detail_data() {
serial_number = Number(serial_number) - 1
if (serial_number < 0){
window.alert('無上一筆資料')
serial_number = 0
return
}
// console.log(serial_number)
//console.log(All_Model[serial_number])
detail_data(All_Model[serial_number]['violation_location_name'], serial_number, All_Model[serial_number]['create_data_time'])
}
</script>
<!--違規車輛詳細-->
<script>
function detail_data(location_name, car_serial_number, time) {
//console.log(location_name)
//console.log(All_Model[car_serial_number])
//console.log(time)
serial_number = car_serial_number
$.ajax({
type: "GET",
url: "http://140.125.20.183:7700/api/Violation_car_table/location_nam-" + location_name + "-time-" + time,
data: {},
contentType: "application/json",
success: function (Model) {
console.log(Model)
table = "<tr>";
table += "<td>" + Model.violation_location_name + "</td>"
table += "<td>" + '<input type="text" id = "license_plate_number_text_id" value="'+Model.license_plate_number+ '"/>' + "</td>"
//table += "<td>" + "</td>"
//table += "<td>" + "</td>"
table += "<td>" + "<img src=" + Model.car_start_img + ' style="width:100%"' + ">" + "</td>"
table += "<td>" + "<img src=" + Model.car_end_img + ' style="width:100% "' + ">" + "</td>"
table += "<td id = 'create_data_time_id' >" + Model.create_data_time + "</td>"
document.getElementById("detail_car_data").innerHTML = table
}
});
detail_car_data_view.showModal();
}
</script>
<!--刪除資料-->
<script>
function delet_data(location_name , name , time) {
console.log(location_name)
console.log(name)
console.log(time)
$.ajax({
type: "DELETE",
url: "http://140.125.20.183:7700/api/Violation_car_table/location_name-" + location_name + "-time-" + time,
data: {},
contentType: "application/json",
success: function (msg) {
console.log(msg)
get_data()
}
});
}
</script>
<!--檢查token-->
<script>
function token_check() {
// 检查本地存储中是否存在JWT令牌
var token = localStorage.getItem('token_park_space');
console.log(token)
$.ajax({
type: "GET",
url: 'http://140.125.20.183:7700/Users/token_check',
headers: {
'Authorization': token
},
success: function (response) {
console.log(response)
token_check = "true"
from_token_import_id()
},
error: function (xhr) {
token_check = "false"
window.location.href = '/';
// 处理错误响应,例如跳转到未授权页面
//window.location.href = 'https://example.com/unauthorized_page';
}
});
}
function from_token_import_id() {
var token = localStorage.getItem('token_park_space');
$.ajax({
type: "GET",
url: 'http://140.125.20.183:7700/Users/token-' + token,
headers: {
'Authorization': token
},
success: function (response) {
console.log(response)
from_id_import_user_data(response)
}
});
}
function from_id_import_user_data(id) {
var token = localStorage.getItem('token_park_space');
$.ajax({
type: "GET",
url: 'http://140.125.20.183:7700/Users/user_id-' + id,
headers: {
'Authorization': token
},
success: function (model) {
model = model.result
position = model.lastname
console.log(position)
if (position == "engineer") {
get_data()
}
else {
window.location.href = '/';
}
}
});
}
</script>
<!--開機自啟-->
<script>
window.onload = token_check;
</script>

View File

@ -0,0 +1,12 @@
@{
ViewData["Title"] = "Home Page";
}
<div class="text-center">
<h1 class="display-4">Welcome</h1>
<p>Learn about <a href="https://docs.microsoft.com/aspnet/core">building Web apps with ASP.NET Core</a>.</p>
</div>

View File

@ -0,0 +1,266 @@
@{
ViewData["Title"] = "Login";
Layout = null;
}
<!--
<style>
body {
font-family: Arial, sans-serif;
background-color: #f2f2f2;
margin: 0;
padding: 0;
display: flex;
justify-content: center;
align-items: center;
height: 100vh;
}
.container {
background-color: #ffffff;
border-radius: 5px;
padding: 20px;
box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
}
.container h1 {
text-align: center;
margin-bottom: 20px;
}
.container label {
display: block;
margin-bottom: 10px;
font-weight: bold;
}
.container input[type="text"],
.container input[type="password"] {
width: 100%;
padding: 10px;
border: 1px solid #ccc;
border-radius: 5px;
margin-bottom: 20px;
}
.container button {
display: block;
width: 100%;
padding: 10px;
background-color: #4caf50;
color: #ffffff;
border: none;
border-radius: 5px;
cursor: pointer;
}
.container button:hover {
background-color: #45a049;
}
</style>
-->
<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>Login</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="~/bootstrap_1/css/sb-admin-2.min.css" rel="stylesheet">
</head>
<body class="bg-gradient-primary">
<div class="container">
<!-- Outer Row -->
<div class="row justify-content-center">
<div class="col-xl-10 col-lg-12 col-md-9">
<div class="card o-hidden border-0 shadow-lg my-5">
<div class="card-body p-0">
<!-- Nested Row within Card Body -->
<div class="row">
<div class="col-lg-6 ">
<img style="width:100%" src="~/bootstrap_1/img/Yuntech.png">
</div>
<div class="col-lg-6">
<div class="p-5">
<div class="text-center">
<h1>Login</h1>
</div>
<div class="user">
<div class="form-group">
<input type="email" class="form-control form-control-user"
id="username_id" aria-describedby="emailHelp"
placeholder="輸入帳號...">
</div>
<div class="form-group">
<input type="password" class="form-control form-control-user"
id="password_id" placeholder="密碼">
</div>
<a onclick="login_clicked()" class="btn btn-success btn-user btn-block">
Login
</a>
<a onclick="passerby_clicked()" class="btn btn-primary btn-user btn-block">
路人登入
</a>
<hr>
</div>
<hr>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</body>
<!--
<div class="container">
<h1>Login</h1>
<div >
<label for="username">Username:</label>
<input type="text" id="username_id" name="username" required>
<label for="password">Password:</label>
<input type="password" id="password_id" name="password" required>
<button onclick="login_clicked()">登入</button>
<button style="background-color: #0066FF;background-color: #5599FF;" onclick="passerby_clicked()">路人登入</button>
</div>
</div>
-->
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.8.0/jquery.min.js" /></script>
<!--登入頁面-->
<script>
function login_clicked() {
var username = document.getElementById("username_id").value
var password = document.getElementById("password_id").value
console.log(username, password)
var obj = { Username: username, Password: password }
var stringify_obj = JSON.stringify(obj);
/* 0521
$.ajax({
type: "POST",
url: "Users/authenticate",
data: stringify_obj,
contentType: "application/json",
success: function (msg) {
console.log(msg)
var token = msg.token; // 替换为您的JWT令牌
var redirectUrl = "/Park_spaces/Parking_spaces_total_table"; // 替换为您的目标URL
// 构建带有JWT令牌的完整URL
var urlWithToken = redirectUrl + "?token=" + token;
if(msg!=null){
window.location = urlWithToken;
}
//window.location = "/Park_spaces/Parking_spaces_total_table";
}
});
*/
/*0522
$.ajax({
type: "POST",
url: "Users/authenticate",
data: stringify_obj,
contentType: "application/json",
success: function (msg) {
console.log(msg)
var token = msg.token; // 替换为您的JWT令牌
// 将令牌存储在本地存储中
localStorage.setItem('token_park_space', token);
// 跳转到目标页面
window.location.href = '/Park_spaces/Parking_spaces_total_table';
},
error: function (xhr, status, error) {
// 处理错误
window.alert("請輸入正確帳號密碼");
document.getElementById("username_id").value = ""
document.getElementById("password_id").value = ""
console.log("error")
}
});*/
/*0523*/
$.ajax({
type: "POST",
url: "http://140.125.20.183:7700/Users/authenticate",
data: stringify_obj,
contentType: "application/json",
success: function (msg) {
console.log(msg)
var token = msg.token;
go_to_next_view(token)
},
error: function (xhr, status, error) {
// 处理错误
window.alert("請輸入正確帳號密碼");
document.getElementById("username_id").value = ""
document.getElementById("password_id").value = ""
console.log("error")
}
});
}
function go_to_next_view(token_str) {
// 将令牌存储在本地存储中
localStorage.setItem('token_park_space', token_str);
window.location = '/Park_spaces/Parking_spaces_total_table';
/*
// 获取 JWT 令牌
var token = token_str;
$.ajax({
type: "GET",
url: 'Park_spaces/Parking_spaces_total_table',
//url: 'http://localhost:5173/Users/token',
headers: {
'Authorization': token
},
success: function (response) {
// window.location.href = '/test/' + response;
window.location = '/Park_spaces/test/' + response;
//console.log(response)
},
error: function (xhr) {
// 处理错误响应,例如跳转到未授权页面
window.location.href = 'https://example.com/unauthorized_page';
}
});*/
}
</script>
<!--路人登入-->
<script>
function passerby_clicked() {
localStorage.removeItem('token_park_space');
window.location.href = '/Park_spaces/Parking_spaces_total_table';
}
</script>

View File

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

View File

@ -0,0 +1,103 @@
<!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 - Login</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 class="bg-gradient-primary">
<div class="container">
<!-- Outer Row -->
<div class="row justify-content-center">
<div class="col-xl-10 col-lg-12 col-md-9">
<div class="card o-hidden border-0 shadow-lg my-5">
<div class="card-body p-0">
<!-- Nested Row within Card Body -->
<div class="row">
<div class="col-lg-6 d-none d-lg-block bg-login-image"></div>
<div class="col-lg-6">
<div class="p-5">
<div class="text-center">
<h1 class="h4 text-gray-900 mb-4">Welcome Back!</h1>
</div>
<form class="user">
<div class="form-group">
<input type="email" class="form-control form-control-user"
id="exampleInputEmail" aria-describedby="emailHelp"
placeholder="Enter Email Address...">
</div>
<div class="form-group">
<input type="password" class="form-control form-control-user"
id="exampleInputPassword" placeholder="Password">
</div>
<div class="form-group">
<div class="custom-control custom-checkbox small">
<input type="checkbox" class="custom-control-input" id="customCheck">
<label class="custom-control-label" for="customCheck">Remember
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>
<hr>
<div class="text-center">
<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>
</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>

View File

@ -0,0 +1,170 @@

@{
ViewData["Title"] = "Parking_spaces_history";
Layout = "~/Views/Shared/_Layout_Normal.cshtml";
}
<h1>歷史資料</h1>
<div>
<select size="1" width="900" style="width:30%;" id="select_id" onchange="option_date()"></select>
<button style="height:30px;float:right " class="btn btn-outline-secondary" onclick="serch_click()">搜尋</button>
<input type="text" style="float:right" placeholder="請輸入時間" id="serch_text_id" />
</div>
<div class="size2">
<table class="table">
<thead>
<tr>
<th>
停車區域
</th>
<th>
車牌號碼
</th>
<th>
圖片
</th>
<th>
進入時間
</th>
<th>
出去時間
</th>
</tr>
</thead>
<tbody id="demo">
</tbody>
</table>
</div>
<!--透過時間搜尋-->
<script>
function serch_click() {
var date = document.getElementById("serch_text_id").value
$.ajax({
type: "GET",
url: "http://140.125.20.183:7700/api/Parking_spaces_history/date-" + date,
data: {},
contentType: "application/json",
success: function (Model) {
console.log(Model)
set_data(Model)
}
});
}
</script>
<!--獲取資料-->
<script>
function get_data() {
$.ajax({
type: "GET",
//url: "http://140.125.20.183:7700/api/Parking_spaces_history/parking_space_area-" + name,
url: "http://140.125.20.183:7700/api/Parking_spaces_history",
data: {},
contentType: "application/json",
success: function (Model) {
console.log(Model)
set_data(Model)
}
});
}
</script>
<!--放置資料-->
<script>
function set_data(Model) {
table = "<tr>";
console.log(Model.length)
if (Model.length > 0) {
for (var i = 0; i < Model.length; i++) {
if (Model[i].parking_spaces_name != null) {
table += "<td>" + Model[i].parking_spaces_name + "</td>"
table += "<td>" + Model[i].license_plate_number + "</td>"
table += "<td>" + Model[i].car_img + "</td>"
table += "<td>" + Model[i].in_time + "</td>"
table += "<td>" + Model[i].out_time + "</td>"
}
table += "</tr>"
table += "<tr>"
}
}
document.getElementById("demo").innerHTML = table
}
</script>
<!--設定下拉式選單-->
<script>
function select_data(){
$.ajax({
type: "GET",
url: "http://140.125.20.183:7700/api/Parking_spaces_total_table",
data: {},
contentType: "application/json",
success: function (Model) {
//console.log(Model)
var obj = document.getElementById("select_id");
for (var i = 0; i < Model.length; i++) {
obj.options.add(new Option(Model[i].parking_spaces_name));
}
get_data()
}
});
}
</script>
<!--更改下拉式選單-->
<script>
function option_date(){
var name = document.getElementById("select_id").value
$.ajax({
type: "GET",
url: "http://140.125.20.183:7700/api/Parking_spaces_history/parking_space_area-" + name,
data: {},
contentType: "application/json",
success: function (Model) {
console.log(Model)
set_data(Model)
}
});
}
</script>
<!--檢查token-->
<script>
function token_check() {
// 检查本地存储中是否存在JWT令牌
var token = localStorage.getItem('token_park_space');
console.log("TEST_TOKEN")
if (token) {
// 执行所需的操作
console.log(token)
select_data();
} else {
// 重定向到登录页面或其他适当的处理
window.location.href = '/';
}
}
</script>
<!--開機自啟-->
<script>
window.onload = token_check;
</script>

View File

@ -0,0 +1,436 @@
@{
ViewData["Title"] = "Parking_spaces_total_table";
Layout = "~/Views/Shared/_Layout_Normal.cshtml";
var token_check_1 = ViewBag.token_check;
}
<input type="hidden" id="token_check_id" value=@token_check_1 />
<h1 id="position_id">校園總停車區域</h1>
<div class="size2">
<button class="btn btn-primary" onclick="add_park_space_view.showModal();map_show()" id="add_park_space_id">新增停車區</button>
<!--<button class="btn btn-primary" onclick="add_violation_view.showModal();map_show_1()" id="add_violation_id">新增違規區域</button>-->
<button style="height:30px;float:right " class="btn btn-outline-secondary" onclick="serch_click()">搜尋</button>
<input type="text" style="float:right" placeholder="請輸入您的車牌" id="serch_text_id" />
<table class="table">
<thead>
<tr>
<th>
停車區域
</th>
<th>
總車位
</th>
<th>
剩餘車位
</th>
<th>
</th>
</tr>
</thead>
<tbody id="demo">
</tbody>
</table>
</div>
<!-- css -->
<link rel="stylesheet"
href="https://unpkg.com/leaflet@1.6.0/dist/leaflet.css"
integrity="sha512-xwE/Az9zrjBIphAcBb3F6JVqxf46+CDLwfLMHloNu6KEQCAWi6HcDUbeOfBIptF7tcCzusKFjFw2yuvEpDL9wQ=="
crossorigin="" />
<!-- js -->
<script src="https://unpkg.com/leaflet@1.6.0/dist/leaflet.js"
integrity="sha512-gZwIG9x3wUXg2hdXF6+rVkLF/0Vi9U8D2Ntg4Ga5I5BZpVkVxlJWbSQtXPSiUTtC0TjtGOmxa1AJPuV0CPthew=="
crossorigin="">
</script>
<style>
#myMap {
height: 300px;
}
#myMap_1 {
height: 300px;
}
</style>
<!--新增停車場-彈跳視窗-->
<div>
<dialog id="add_park_space_view" style="width:100%;">
<div>
<button class="btn btn-danger" style="float:right" onclick="add_park_space_view.close();"> 關閉</button>
停車區名稱 : <input type="text" id="add_park_space_name_text_id" /></br></br>
停車位數量 : <input type="text" id="add_park_space_num_text_id" /></br></br>
<button class="btn btn-outline-success" onclick="GPS_text_clicked()">停車場位置</button>緯度<input type="text" size="10" id="add_park_space_GPS_lat_text_id" />經度<input type="text" size="10" id="add_park_space_GPS_lng_text_id" /></br></br>
<div id="myMap"></div>
<button class="btn btn-success" onclick="add_park_space()">上傳</button>
</div>
</dialog>
</div>
<!--新增違規區域-彈跳視窗-->
<div>
<dialog id="add_violation_view" style="width:100%;">
<div>
<button class="btn btn-danger" style="float:right" onclick="add_violation_view.close();"> 關閉</button>
違規區域名稱 : <input type="text" id="add_violation_name_text_id" /></br></br>
<button class="btn btn-outline-success" onclick="GPS_text_clicked()">停車場位置</button>緯度<input type="text" size="10" id="add_violation_GPS_lat_text_id" />經度<input type="text" size="10" id="add_violation_GPS_lng_text_id" /></br></br>
<div id="myMap_1"></div>
<button class="btn btn-success" onclick="add_violation()">上傳</button>
</div>
</dialog>
</div>
<!--map_show_停車場位置-->
<script>
var map
let lat ,lng
function map_show() {
var map_center = [23.691951, 120.535318]
map = L.map("myMap", {
center: map_center,
//center: seriesData,
zoom: 17
});
// 載入圖資
L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
attribution: '&copy; <a href="http://osm.org/copyright">OpenStreetMap</a> contributors'
}).addTo(map);
const popup = L.popup();
function onMapClick(e) {
lat = e.latlng.lat; // 緯度
lng = e.latlng.lng; // 經度
popup
.setLatLng(e.latlng)
.setContent(`緯度:${lat}<br/>經度:${lng}`)
.openOn(map);
console.log(lat, lng)
}
map.on('click', onMapClick);
}
var map_1
function map_show_1() {
var map_center = [23.691951, 120.535318]
map_1 = L.map("myMap_1", {
center: map_center,
//center: seriesData,
zoom: 17
});
// 載入圖資
L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
attribution: '&copy; <a href="http://osm.org/copyright">OpenStreetMap</a> contributors'
}).addTo(map_1);
const popup = L.popup();
function onMapClick(e) {
lat = e.latlng.lat; // 緯度
lng = e.latlng.lng; // 經度
popup
.setLatLng(e.latlng)
.setContent(`緯度:${lat}<br/>經度:${lng}`)
.openOn(map_1);
console.log(lat, lng)
}
map_1.on('click', onMapClick);
}
</script>
<!--紀錄位置-->
<script>
function GPS_text_clicked(){
document.getElementById("add_park_space_GPS_lat_text_id").value=lat
document.getElementById("add_park_space_GPS_lng_text_id").value=lng
}
</script>
<!--顯示車輛位置-彈跳視窗-->
<div>
<dialog id="serch_view" style="width:100%;">
<div>
<button class="btn btn-danger" style="float:right" onclick="serch_view.close();"> 關閉</button>
停車區名稱 : <input type="text" id="park_space_name_text_id" /> </br></br>
車牌號碼 : <input type="text" id="license_plate_number_text_id" /></br></br>
圖 片 : <img id="car_img_text_id" style="width:30%" /></br></br>
進入時間 : <input type="text" id="in_time_text_id" /></br></br>
</div>
</dialog>
</div>
<!--透過車牌號碼搜尋-->
<script>
function serch_click() {
var license_plate_number = document.getElementById("serch_text_id").value
$.ajax({
type: "GET",
url: "http://140.125.20.183:7700/api/Parking_spaces_instant/license_plate_number-" + license_plate_number,
data: {},
contentType: "application/json",
success: function (Model) {
console.log(Model)
document.getElementById("park_space_name_text_id").value = Model[0].parking_spaces_name
document.getElementById("license_plate_number_text_id").value = Model[0].license_plate_number
document.getElementById("car_img_text_id").src = Model[0].car_img
document.getElementById("in_time_text_id").value = Model[0].in_time
serch_view.showModal()
//set_data(Model)
}
});
}
</script>
<!--獲取資料-->
<script>
var token_ckeck //= document.getElementById("token_ckeck_id").value
var position //職位
function get_data(){
console.log("start")
//token_check = document.getElementById("token_check_id").value
console.log(token_check)
$.ajax({
type: "GET",
url: "http://140.125.20.183:7700/api/Parking_spaces_total_table",
data: {},
contentType: "application/json",
success: function (Model) {
//console.log(Model)
set_data(Model)
}
});
}
</script>
<!--放置資料-->
<script>
function set_data(Model){
if(token_check == "true"){
document.getElementById("add_park_space_id").style.display= "block"
}
else{
document.getElementById("add_park_space_id").style.display = "none"
}
if (position == "engineer"){
document.getElementById("position_id").innerHTML = "<p " + ' onclick="engineer_mode()"' + '>校園總停車區域-工程模式</p>'
}
else if (position == "manager") {
//document.getElementById("position_id").innerHTML = "<p " + ' onclick="manager_mode()"' + '>校園總停車區域-管理者模式</p>'
document.getElementById("position_id").innerHTML = '校園總停車區域-管理者模式'
}
else{
document.getElementById("position_id").innerHTML ='校園總停車區域'
}
table ="<tr>";
//console.log(Model.length)
if (Model.length>0){
for (var i=0 ;i<Model.length;i++){
if (Model[i].parking_spaces_name!=null){
table += "<td>" + Model[i].parking_spaces_name +"</td>"
table += "<td id='" + Model[i].parking_spaces_name + "_total'>" + Model[i].parking_spaces_total_num + "</td>"
table += "<td id='" + Model[i].parking_spaces_name + "_total'>" + Model[i].parking_spaces_now_num + "</td>"
//table += "<td id='" + Model[i].parking_spaces_name + "_now'>" + "</td>"
//get_single_parking_space_car(Model[i].parking_spaces_name)
//table += "<td>" + '<button class="btn btn-danger " onclick="delet_data(' + "'" + Model[i].parking_spaces_name + "'" + ')">刪除</button>'
table += "<td>"
if (token_check == "true") {
table += '<button class="btn btn-outline-success " onclick="detail_data(' + "'" + Model[i].parking_spaces_name + "'" + ')">詳細</button>' + ' ' + ' '
}
//table += "<td>" + '<button class="btn btn-outline-success " onclick="detail_data(' + "'" + Model[i].parking_spaces_name + "'" + ')">詳細</button>' +' '+' '
table += '<button class="btn btn-outline-warning " onclick="map_data(' + "'" + Model[i].parking_spaces_name + "'" + ')">地圖</button>' + "</td>"
}
table += "</tr>"
table += "<tr>"
}
}
document.getElementById("demo").innerHTML = table
}
</script>
<!--獲取當下停車數量-->
<script>
function get_single_parking_space_car(name){
$.ajax({
type: "GET",
url: "http://140.125.20.183:7700/api/Parking_spaces_instant/parking_space_area-" + name,
data: {},
contentType: "application/json",
success: function (Model) {
var total = document.getElementById(name+"_total").innerHTML
console.log(total)
var now = Model.length
document.getElementById(name + "_now").innerHTML = total - now
}
});
console.log()
}
</script>
<!--上傳資料-->
<script>
function add_park_space(){
var parking_spaces_name = document.getElementById("add_park_space_name_text_id").value;
var parking_spaces_total_num = document.getElementById("add_park_space_num_text_id").value;
var latitude = document.getElementById("add_park_space_GPS_lat_text_id").value;
var longitude = document.getElementById("add_park_space_GPS_lng_text_id").value;
var obj = { parking_spaces_name: parking_spaces_name, parking_spaces_total_num: parking_spaces_total_num, longitude: longitude, latitude: latitude }
var stringify_obj = JSON.stringify(obj);
$.ajax({
type: "POST",
url: "http://140.125.20.183:7700/api/Parking_spaces_total_table",
//url: "http://140.125.20.183:7700/api/Postural_Analysis_1",
//data: {test_id: test_id, test_date: test_date, test_time: test_time, test_analyst: test_analyst, img: img, data_creat_time: "2022-10-04T18:47:40.887014" },
data: stringify_obj,
contentType: "application/json",
success: function (msg) {
console.log(msg)
add_park_space_view.close()
alert("上傳完成");
get_data()
//test_upload_bt_2()
//wait_view()
}
});
}
</script>
<!--刪除資料-->
<script>
function delet_data(name){
$.ajax({
type: "DELETE",
url: "http://140.125.20.183:7700/api/Parking_spaces_total_table/"+name,
data: {},
contentType: "application/json",
success: function (msg) {
console.log(msg)
get_data()
}
});
}
</script>
<!--前往詳細頁面-->
<script>
function detail_data(name){
window.location = "/Park_spaces/Single_parking_spaces_detail/" + name;
}
function map_data(name) {
window.location = "/Park_spaces/Single_parking_spaces_map/" + name;
}
function engineer_mode() {
window.location = "/Engineering/Engineering_Index";
}
</script>
<!--檢查token-->
<script>
function token_check() {
// 检查本地存储中是否存在JWT令牌
var token = localStorage.getItem('token_park_space');
console.log(token)
$.ajax({
type: "GET",
url: 'http://140.125.20.183:7700/Users/token_check',
headers: {
'Authorization': token
},
success: function (response) {
console.log(response)
token_check = "true"
from_token_import_id()
},
error: function (xhr) {
token_check = "false"
get_data()
// 处理错误响应,例如跳转到未授权页面
//window.location.href = 'https://example.com/unauthorized_page';
}
});
}
function from_token_import_id(){
var token = localStorage.getItem('token_park_space');
$.ajax({
type: "GET",
url: 'http://140.125.20.183:7700/Users/token-' + token,
headers: {
'Authorization': token
},
success: function (response) {
console.log(response)
from_id_import_user_data(response)
}
});
}
function from_id_import_user_data(id){
var token = localStorage.getItem('token_park_space');
$.ajax({
type: "GET",
url: 'http://140.125.20.183:7700/Users/user_id-' + id,
headers: {
'Authorization': token
},
success: function (model) {
model = model.result
position = model.lastname
console.log(position)
//window.location = "/Engineering/Engineering_total_table" ;
get_data()
}
});
}
</script>
<!--開機自啟-->
<script>
window.onload = token_check;
</script>

View File

@ -0,0 +1,363 @@

@{
ViewData["Title"] = "Single_parking_spaces_detail";
Layout = "~/Views/Shared/_Layout_Normal.cshtml";
var parking_spaces_name = ViewBag.name;
}
<input type="hidden" id="parking_spaces_name_id" value=@parking_spaces_name />
<h1>停車區-即時停車位</h1>
<div class="size2">
<button class="btn btn-primary" onclick="time_show()">新增車輛</button>
<table class="table">
<thead>
<tr>
<th>
停車區域
</th>
<th>
車牌號碼
</th>
<!--
<th>
圖片
</th>
-->
<th>
進入時間
</th>
<th></th>
</tr>
</thead>
<tbody id="demo">
</tbody>
</table>
</div>
<!--彈跳視窗-->
<div>
<dialog id="add_car_view" style="width:100%;">
<div>
<button class="btn btn-danger" style="float:right" onclick="add_car_view.close();"> 關閉</button>
停車區名稱 : @parking_spaces_name </br></br>
車牌號碼 : <input type="text" id="add_license_plate_number_text_id" /></br></br>
圖 片 : <input type="text" id="add_car_img_text_id" /></br></br>
進入時間 : <input type="text" id="add_in_time_text_id" /></br></br>
<button class="btn btn-success" onclick="add_car()">上傳</button>
</div>
</dialog>
</div>
<!--車輛詳細-彈跳視窗-->
<div>
<dialog id="detail_car_data_view" style="width:100%;">
<table class="table">
<button class="btn btn-danger" style="float:right" onclick="detail_car_data_view.close();"> 關閉</button>
<thead>
<tr>
<th>
停車場
</th>
<th>
車牌號碼
</th>
<th>
圖片
</th>
<th>
時間
</th>
</tr>
</thead>
<tbody id="detail_car_data">
</tbody>
</table>
<button class="btn btn-outline-success" style="float:left" onclick="previous_detail_data()"> Previous</button>
<button class="btn btn-outline-success" style="float:right" onclick="next_detail_data()"> Next </button>
</dialog>
</div>
<!--上傳資料-->
<script>
function add_car() {
var parking_spaces_name = document.getElementById("parking_spaces_name_id").value;
var license_plate_number = document.getElementById("add_license_plate_number_text_id").value;
var car_img = document.getElementById("add_car_img_text_id").value;
var in_time = document.getElementById("add_in_time_text_id").value;
var out_time = ""
var obj = {
parking_spaces_name: parking_spaces_name,
license_plate_number: license_plate_number,
car_img: car_img,
in_time: in_time,
out_time: out_time,
}
//var obj = { parking_spaces_name: parking_spaces_name,license_plate_number: license_plate_number,car_img: car_img,in_time: in_time,out_time:"",}
var stringify_obj = JSON.stringify(obj);
console.log(stringify_obj)
$.ajax({
type: "Post",
url: "http://140.125.20.183:7700/api/Parking_spaces_instant",
//data: {test_id: test_id, test_date: test_date, test_time: test_time, test_analyst: test_analyst, img: img, data_creat_time: "2022-10-04T18:47:40.887014" },
data: stringify_obj,
contentType: "application/json",
success: function (msg) {
console.log(msg)
//add_car_view.close()
add_car_2()
//get_data()
//test_upload_bt_2()
//wait_view()
}
});
}
function add_car_2(){
var parking_spaces_name = document.getElementById("parking_spaces_name_id").value;
var license_plate_number = document.getElementById("add_license_plate_number_text_id").value;
var car_img = document.getElementById("add_car_img_text_id").value;
var in_time = document.getElementById("add_in_time_text_id").value;
var out_time = ""
var obj = {
parking_spaces_name: parking_spaces_name,
license_plate_number: license_plate_number,
car_img: car_img,
in_time: in_time,
out_time: out_time,
}
//var obj = { parking_spaces_name: parking_spaces_name,license_plate_number: license_plate_number,car_img: car_img,in_time: in_time,out_time:"",}
var stringify_obj = JSON.stringify(obj);
console.log(stringify_obj)
$.ajax({
type: "Post",
url: "http://140.125.20.183:7700/api/Parking_spaces_history",
//data: {test_id: test_id, test_date: test_date, test_time: test_time, test_analyst: test_analyst, img: img, data_creat_time: "2022-10-04T18:47:40.887014" },
data: stringify_obj,
contentType: "application/json",
success: function (msg) {
console.log(msg)
add_car_view.close()
//alert("上傳完成");
get_data()
//test_upload_bt_2()
//wait_view()
}
});
}
</script>
<!--時間-->
<script>
function time_show(){
NowDate = new Date();
Y = NowDate.getFullYear();
M = NowDate.getMonth() + 1;
d = NowDate.getDate();
h = NowDate.getHours();
m = NowDate.getMinutes();
s = NowDate.getSeconds();
document.getElementById("add_in_time_text_id").value = Y + "-" + M + "-" + d + " " + h + ":" + m+":" + s
add_car_view.showModal()
}
</script>
<!--獲取資料-->
<script>
var All_Model
var serial_number = 0
function get_data() {
var name = document.getElementById("parking_spaces_name_id").value
$.ajax({
type: "GET",
url: "http://140.125.20.183:7700/api/Parking_spaces_instant/parking_space_area-" + name,
data: {},
contentType: "application/json",
success: function (Model) {
//console.log(Model)
All_Model = Model
set_data(Model)
}
});
}
</script>
<!--放置資料-->
<script>
function set_data(Model) {
table = "<tr>";
console.log(Model.length)
if (Model.length > 0) {
for (var i = 0; i < Model.length; i++) {
if (Model[i].parking_spaces_name != null) {
table += "<td>" + Model[i].parking_spaces_name + "</td>"
table += "<td>" + Model[i].license_plate_number + "</td>"
//table += "<td>" + "<img src=" + Model[i].car_img + ' style="width:100%"' + ">" + "</td>"
table += "<td>" + Model[i].in_time + "</td>"
table += "<td>" + '<button class="btn btn-outline-success" onclick="detail_data(' + "'" + Model[i].parking_spaces_name + "','" +i + "','" + Model[i].data_create_time + "'" + ')">詳細</button>'
table += '<button class="btn btn-danger " onclick="delet_data(' + "'" + Model[i].parking_spaces_name + "','" + Model[i].license_plate_number + "','" + Model[i].data_create_time + "'" + ')">刪除</button>' + "</td>"
}
table += "</tr>"
table += "<tr>"
}
}
document.getElementById("demo").innerHTML = table
}
</script>
<!--下一筆資料-->
<script>
function next_detail_data() {
serial_number = Number(serial_number) + 1
if (serial_number >= All_Model.length) {
window.alert('無下一筆資料')
serial_number = All_Model.length - 1
return
}
//console.log(serial_number)
//console.log(All_Model[serial_number])
detail_data(All_Model[serial_number]['parking_spaces_name'], serial_number, All_Model[serial_number]['data_create_time'])
}
</script>
<!--上一筆資料-->
<script>
function previous_detail_data() {
serial_number = Number(serial_number) - 1
if (serial_number < 0) {
window.alert('無上一筆資料')
serial_number = 0
return
}
// console.log(serial_number)
//console.log(All_Model[serial_number])
detail_data(All_Model[serial_number]['parking_spaces_name'], serial_number, All_Model[serial_number]['data_create_time'])
}
</script>
<!--違規車輛詳細-->
<script>
function detail_data(location_name, car_serial_number, time) {
//console.log(location_name)
//console.log(All_Model[car_serial_number])
//console.log(time)
serial_number = car_serial_number
$.ajax({
type: "GET",
url: "http://140.125.20.183:7700/api/Parking_spaces_instant/parking_space_area_name-" + location_name + "-time-" + time,
data: {},
contentType: "application/json",
success: function (Model) {
console.log(Model)
table = "<tr>";
table += "<td>" + Model.parking_spaces_name + "</td>"
table += "<td>" + Model.license_plate_number + "</td>"
//table += "<td>" + "</td>"
//table += "<td>" + "</td>"
table += "<td>" + "<img src=" + Model.car_img + ' style="width:100%"' + ">" + "</td>"
table += "<td>" + Model.data_create_time + "</td>"
document.getElementById("detail_car_data").innerHTML = table
}
});
detail_car_data_view.showModal();
}
</script>
<!--刪除資料-->
<script>
function delet_data(location_name, name, time) {
console.log(location_name)
console.log(name)
console.log(time)
/*
NowDate = new Date();
Y = NowDate.getFullYear();
M = NowDate.getMonth() + 1;
d = NowDate.getDate();
h = NowDate.getHours();
m = NowDate.getMinutes();
s = NowDate.getSeconds();
var out_time = Y + "/" + M + "/" + d + " " + h + ":" + m
var parking_spaces_name = document.getElementById("parking_spaces_name_id").value;
var license_plate_number_1 = license_plate_number
var car_img = document.getElementById("add_car_img_text_id").value;
var in_time = document.getElementById("add_in_time_text_id").value;
var obj = {
parking_spaces_name: parking_spaces_name,
license_plate_number: license_plate_number_1,
car_img: car_img,
in_time: "",
out_time: out_time,
}
var stringify_obj = JSON.stringify(obj);
console.log(stringify_obj)
$.ajax({
type: "Post",
url: "http://140.125.20.183:7700/api/Parking_spaces_history",
data: stringify_obj,
contentType: "application/json",
success: function (msg) {
console.log(msg)
delet_data_2(license_plate_number)
}
});*/
delet_data_2(location_name, name, time)
}
function delet_data_2(location_name, name, time) {
$.ajax({
type: "DELETE",
url: "http://140.125.20.183:7700/api/Parking_spaces_instant/parking_space_name-" + location_name + "-time-" + time,
data: {},
contentType: "application/json",
success: function (msg) {
console.log(msg)
get_data()
}
});
}
</script>
<!--檢查token-->
<script>
function token_check() {
// 检查本地存储中是否存在JWT令牌
var token = localStorage.getItem('token_park_space');
console.log("TEST_TOKEN")
if (token) {
// 执行所需的操作
console.log(token)
get_data();
} else {
// 重定向到登录页面或其他适当的处理
window.location.href = '/';
}
}
</script>
<!--開機自啟-->
<script>
window.onload = token_check;
</script>

View File

@ -0,0 +1,240 @@
@{
ViewData["Title"] = "Single_parking_spaces_map";
Layout = "~/Views/Shared/_Layout_Normal.cshtml";
var parking_spaces_name = ViewBag.name;
}
<input type="hidden" id="parking_spaces_name_id" value=@parking_spaces_name />
<!-- css -->
<link rel="stylesheet"
href="https://unpkg.com/leaflet@1.6.0/dist/leaflet.css"
integrity="sha512-xwE/Az9zrjBIphAcBb3F6JVqxf46+CDLwfLMHloNu6KEQCAWi6HcDUbeOfBIptF7tcCzusKFjFw2yuvEpDL9wQ=="
crossorigin="" />
<!DOCTYPE html>
<!-- js -->
<script src="https://unpkg.com/leaflet@1.6.0/dist/leaflet.js"
integrity="sha512-gZwIG9x3wUXg2hdXF6+rVkLF/0Vi9U8D2Ntg4Ga5I5BZpVkVxlJWbSQtXPSiUTtC0TjtGOmxa1AJPuV0CPthew=="
crossorigin="">
</script>
<style>
html, body {
padding: 0;
margin: 0;
}
#myMap {
height: 80vh;
}
</style>
<!--擷取當前位置
<button class="btn btn-primary" onclick="getCurrentPosition()">新增停車區</button>-->
<!--地圖-->
<!---->
<button class="btn btn-danger" onclick="google_map_GPS_text_clicked()">導航</button>
<div id="myMap"></div>
<!--連接位置-->
<script>
function google_map_GPS_text_clicked(){
//window.location = "https://www.google.com/maps/place/23.691992,120.533247/data=!4m4!3m3!8m2!3d23.691992!4d120.533247";
window.location = map_src
}
</script>
<!--獲取資料-->
<script>
var map_src
var destination
function get_data() {
var name = document.getElementById("parking_spaces_name_id").value
$.ajax({
type: "GET",
url: "http://140.125.20.183:7700/api/Parking_spaces_total_table/" + name,
data: {},
contentType: "application/json",
success: function (Model) {
console.log(Model)
//set_data(Model)
destination = [parseFloat(Model.latitude), parseFloat(Model.longitude)]
map_src = "https://www.google.com/maps/place/" + Model.latitude + "," + Model.longitude + "/data=!4m4!3m3!8m2!3d" + Model.latitude + "!4d" + Model.longitude
getCurrentPosition()
}
});
}
</script>
<!--當前位置-->
<script>
function getCurrentPosition() {
const successCallback = (position) => {
console.log(position.coords.latitude);
console.log(position.coords.longitude);
my_ip = [position.coords.latitude, position.coords.longitude]
//destination = [23.691452, 120.536338]
map_show(destination, my_ip)
};
const errorCallback = (error) => {
console.log(error);
//destination = [23.691452, 120.536338]
map_show(destination, destination)
};
navigator.geolocation.getCurrentPosition(successCallback, errorCallback);
}
</script>
<script>
function getCurrentPosition_2() {
const successCallback = (position) => {
console.log(position.coords.latitude);
console.log(position.coords.longitude);
my_ip = [position.coords.latitude, position.coords.longitude]
//my_ip = [position.coords.latitude, position.coords.longitude]
//destination = [23.691452, 120.536338]
map.removeLayer(parking_space_ip)
map.removeLayer(my_car_ip)
map_show_2(destination, my_ip)
};
const errorCallback = (error) => {
console.log(error);
//destination = [23.691452, 120.536338]
map_show_2(destination, destination)
};
navigator.geolocation.getCurrentPosition(successCallback, errorCallback);
}
</script>
<!--map_show_停車場位置-->
<script>
var map
function map_show(destination, my_ip) {
var map_center = destination
var fork = [];
map = L.map("myMap", {
center: map_center,
//center: seriesData,
zoom: 17
});
var parking_space_icon = L.icon({
iconUrl: '/image/icon/parking_space_icon.png',
iconSize: [34, 34], // size of the icon
iconAnchor: [27.3, 11.35], // point of the icon which will correspond to marker's location
});
parking_space_ip = L.marker(map_center, {
icon: parking_space_icon,
title: "",
opacity: 1.0
}).addTo(map);
var car_icon = L.icon({
iconUrl: '/image/icon/car_icon.png',
iconSize: [24, 24], // size of the icon
iconAnchor: [27.3, 11.35], // point of the icon which will correspond to marker's location
});
my_car_ip = L.marker(my_ip, {
icon: car_icon,
title: "",
opacity: 1.0
}).addTo(map);
//map.removeLayer(parking_space_ip)
//map.removeLayer(my_car_ip)
// 載入圖資
L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
attribution: '&copy; <a href="http://osm.org/copyright">OpenStreetMap</a> contributors'
}).addTo(map);
window.setTimeout(getCurrentPosition_2, 1000)
}
</script>
<script>
var parking_space_ip
var my_car_ip
function map_show_2(destination, my_ip) {
//map.clearLayers();
var map_center = destination
var fork = [];
var parking_space_icon = L.icon({
iconUrl: '/image/icon/parking_space_icon.png',
iconSize: [34, 34], // size of the icon
iconAnchor: [27.3, 11.35], // point of the icon which will correspond to marker's location
});
parking_space_ip = L.marker(map_center, {
icon: parking_space_icon,
title: "",
opacity: 1.0
}).addTo(map);
var car_icon = L.icon({
iconUrl: '/image/icon/car_icon.png',
iconSize: [24, 24], // size of the icon
iconAnchor: [27.3, 11.35], // point of the icon which will correspond to marker's location
});
my_car_ip=L.marker(my_ip, {
icon: car_icon,
title: "",
opacity: 1.0
}).addTo(map);
window.setTimeout(getCurrentPosition_2, 1000)
}
</script>
<!--檢查token-->
<script>
function token_check() {
// 检查本地存储中是否存在JWT令牌
var token = localStorage.getItem('token_park_space');
console.log("TEST_TOKEN")
if (token) {
// 执行所需的操作
console.log(token)
get_data();
} else {
// 重定向到登录页面或其他适当的处理
window.location.href = '/Home/Login';
}
}
</script>
<!--開機自啟-->
<script>
window.onload = get_data;
</script>

View File

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

View File

@ -0,0 +1,55 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>@ViewData["Title"] - Parking_spaces</title>
<link rel="stylesheet" href="~/lib/bootstrap/dist/css/bootstrap.min.css" />
<link rel="stylesheet" href="~/css/site.css" asp-append-version="true" />
<link rel="stylesheet" href="~/Parking_spaces.styles.css" asp-append-version="true" />
</head>
<body>
<header>
<nav class="navbar navbar-expand-sm navbar-toggleable-sm navbar-light bg-white border-bottom box-shadow mb-3">
<div class="container-fluid">
<a class="navbar-brand" asp-area="" asp-controller="Park_spaces" asp-action="Parking_spaces_total_table">停車位</a>
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target=".navbar-collapse" aria-controls="navbarSupportedContent"
aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="navbar-collapse collapse d-sm-inline-flex justify-content-between">
<ul class="navbar-nav flex-grow-1">
<!--
<li class="nav-item">
<a class="nav-link text-dark" asp-area="" asp-controller="Park_spaces" asp-action="Parking_spaces_total_table">停車位總表</a>
</li>
<li class="nav-item">
<a class="nav-link text-dark" asp-area="" asp-controller="Park_spaces" asp-action="Parking_spaces_history">停車歷史</a>
</li>-->
<!--
<li class="nav-item">
<a class="nav-link text-dark" asp-area="" asp-controller="Home" asp-action="Privacy">Privacy</a>
</li>
-->
</ul>
</div>
</div>
</nav>
</header>
<div class="container">
<main role="main" class="pb-3">
@RenderBody()
</main>
</div>
<footer class="border-top footer text-muted">
<div class="container">
&copy; 2023 - Parking_spaces - <a asp-area="" asp-controller="Home" asp-action="Privacy">Privacy</a>
</div>
</footer>
<script src="~/lib/jquery/dist/jquery.min.js"></script>
<script src="~/lib/bootstrap/dist/js/bootstrap.bundle.min.js"></script>
<script src="~/js/site.js" asp-append-version="true"></script>
@await RenderSectionAsync("Scripts", required: false)
</body>
</html>

View File

@ -0,0 +1,48 @@
/* Please see documentation at https://docs.microsoft.com/aspnet/core/client-side/bundling-and-minification
for details on configuring this project to bundle and minify static web assets. */
a.navbar-brand {
white-space: normal;
text-align: center;
word-break: break-all;
}
a {
color: #0077cc;
}
.btn-primary {
color: #fff;
background-color: #1b6ec2;
border-color: #1861ac;
}
.nav-pills .nav-link.active, .nav-pills .show > .nav-link {
color: #fff;
background-color: #1b6ec2;
border-color: #1861ac;
}
.border-top {
border-top: 1px solid #e5e5e5;
}
.border-bottom {
border-bottom: 1px solid #e5e5e5;
}
.box-shadow {
box-shadow: 0 .25rem .75rem rgba(0, 0, 0, .05);
}
button.accept-policy {
font-size: 1rem;
line-height: inherit;
}
.footer {
position: absolute;
bottom: 0;
width: 100%;
white-space: nowrap;
line-height: 60px;
}

View File

@ -0,0 +1,477 @@
<!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>工程模式</title>
<!-- Custom fonts for this template-->
<link href="~/bootstrap_1/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="~/bootstrap_1/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">-->
<a class="sidebar-brand d-flex align-items-center justify-content-center" asp-area="" asp-controller="Park_spaces" asp-action="Parking_spaces_total_table">
<!--
<div class="sidebar-brand-icon rotate-n-15">
<i class="fas fa-laugh-wink"></i>
</div>
<div class="sidebar-brand-text mx-3">工程模式 <sup>2</sup></div>-->
<div class="sidebar-brand-text mx-3">
<img class="img-profile rounded-circle" style="width:20%" src="~/bootstrap_1/img/Yuntech.png">
停車位
</div>
</a>
<!-- Divider -->
<hr class="sidebar-divider my-0">
<!-- Nav Item - Dashboard -->
<li class="nav-item active">
<!--<a class="nav-link" href="/Engineering/Engineering_Index">-->
<a class="nav-link" asp-area="" asp-controller="Engineering" asp-action="Engineering_Index">
<i class="fas fa-fw fa-tachometer-alt"></i>
<span>工程模式</span>
</a>
</li>
<!-- Divider -->
<!--<hr class="sidebar-divider">-->
<!-- Heading -->
<div class="sidebar-heading">
設定介面
</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>設定參數</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" asp-controller="Engineering" asp-action="Engineering_CAM">查看WEBCAM</a>
<a class="collapse-item" asp-controller="Engineering" asp-action="Engineering_LED">字幕機顯示</a>
<a class="collapse-item" asp-controller="Engineering" asp-action="Engineering_Violation"> 違規區域</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>
<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>
<span class="badge badge-danger badge-counter">7</span>
</a>
<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">碼農</span>
<img class="img-profile rounded-circle"
src="~/bootstrap_1/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" onclick="Logout_clicked()">
<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">
@RenderBody()
</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 &copy; 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>
<!-- Bootstrap core JavaScript-->
<script src="~/bootstrap_1/vendor/jquery/jquery.min.js"></script>
<script src="~/bootstrap_1/vendor/bootstrap/js/bootstrap.bundle.min.js"></script>
<!-- Core plugin JavaScript-->
<script src="~/bootstrap_1/vendor/jquery-easing/jquery.easing.min.js"></script>
<!-- Custom scripts for all pages-->
<script src="~/bootstrap_1/js/sb-admin-2.min.js"></script>
<!-- Page level plugins -->
<script src="~/bootstrap_1/vendor/chart.js/Chart.min.js"></script>
<!-- Page level custom scripts -->
<script src="~/bootstrap_1/js/demo/chart-area-demo.js"></script>
<script src="~/bootstrap_1/js/demo/chart-pie-demo.js"></script>
<!--登出-->
<script>
function Logout_clicked() {
localStorage.removeItem('token_park_space');
window.location.href = '/';
}
</script>
</body>
</html>

View File

@ -0,0 +1,166 @@
<!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="">
<!-- Custom fonts for this template-->
<link href="~/bootstrap_1/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="~/bootstrap_1/css/sb-admin-2.min.css" rel="stylesheet">
</head>
<body id="page-top" >
<!-- Page Wrapper -->
<div id="wrapper">
</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">
<a class="sidebar-brand d-flex align-items-center justify-content-center" asp-area="" asp-controller="Park_spaces" asp-action="Parking_spaces_total_table">
<!--
<div class="sidebar-brand-icon rotate-n-15">
<i class="fas fa-laugh-wink"></i>
</div>
<div class="sidebar-brand-text mx-3">工程模式 <sup>2</sup></div>-->
<div class="sidebar-brand-text mx-3">
<img class="img-profile rounded-circle" style="width:20%" src="~/bootstrap_1/img/Yuntech.png">
停車位
</div>
</a>
<!-- Sidebar Toggle (Topbar) -->
<button id="sidebarToggleTop" class="btn btn-link d-md-none rounded-circle mr-3">
<i class="fa fa-bars"></i>
</button>
<ul class="navbar-nav ml-auto">
<li class="nav-item dropdown no-arrow mx-1">
</li>
<!-- Nav Item - Messages -->
<li class="nav-item dropdown no-arrow mx-1">
</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">使用者</span>
<img class="img-profile rounded-circle"
src="~/bootstrap_1/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="#" data-toggle="modal" data-target="#logoutModal" onclick="Logout_clicked()">
<i class="fas fa-sign-out-alt fa-sm fa-fw mr-2 text-gray-400"></i>
Logout
</a>
</div>
</li>
</ul>
</nav>
<!-- Begin Page Content -->
<div class="container-fluid">
@RenderBody()
</div>
<!-- /.container-fluid -->
</div>
</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="~/bootstrap_1/vendor/jquery/jquery.min.js"></script>
<script src="~/bootstrap_1/vendor/bootstrap/js/bootstrap.bundle.min.js"></script>
<!-- Core plugin JavaScript-->
<script src="~/bootstrap_1/vendor/jquery-easing/jquery.easing.min.js"></script>
<!-- Custom scripts for all pages-->
<script src="~/bootstrap_1/js/sb-admin-2.min.js"></script>
<!-- Page level plugins -->
<script src="~/bootstrap_1/vendor/chart.js/Chart.min.js"></script>
<!-- Page level custom scripts -->
<script src="~/bootstrap_1/js/demo/chart-area-demo.js"></script>
<script src="~/bootstrap_1/js/demo/chart-pie-demo.js"></script>
<!--登出-->
<script>
function Logout_clicked() {
localStorage.removeItem('token_park_space');
window.location.href = '/';
}
</script>
</body>
</html>

View File

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

View File

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

View File

@ -0,0 +1,3 @@
@{
Layout = "_Layout";
}

View File

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

View File

@ -0,0 +1,12 @@
{
"AppSettings": {
"Secret": "Leo token test jwt park spaces lab 124"
},
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
},
"AllowedHosts": "*"
}

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.6 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 36 KiB

View File

@ -0,0 +1,38 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 25.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 108.3 108.3" style="enable-background:new 0 0 108.3 108.3;" xml:space="preserve">
<style type="text/css">
.st0{fill:#E6E6E6;}
.st1{fill:#FFB8B8;}
.st2{fill:#575A89;}
.st3{fill:#2F2E41;}
</style>
<g id="Group_45" transform="translate(-191 -152.079)">
<g id="Group_30" transform="translate(282.246 224.353)">
<path id="Path_944" class="st0" d="M17.1-18.1c0,10.5-3,20.8-8.8,29.6c-1.2,1.9-2.5,3.6-4,5.3c-3.4,4-7.3,7.4-11.6,10.3
c-1.2,0.8-2.4,1.5-3.6,2.2c-6.5,3.6-13.7,5.8-21,6.5c-1.7,0.2-3.4,0.2-5.1,0.2c-4.7,0-9.4-0.6-14-1.8c-2.6-0.7-5.1-1.6-7.6-2.6
c-1.3-0.5-2.5-1.1-3.7-1.8c-2.9-1.5-5.6-3.3-8.2-5.3c-1.2-0.9-2.3-1.9-3.4-2.9C-95.8,1.3-97.1-33-76.8-54.9s54.6-23.3,76.5-2.9
C10.8-47.6,17.1-33.2,17.1-18.1L17.1-18.1z"/>
<path id="Path_945" class="st1" d="M-50.2-13.2c0,0,4.9,13.7,1.1,21.4s6,16.4,6,16.4s25.8-13.1,22.5-19.7s-8.8-15.3-7.7-20.8
L-50.2-13.2z"/>
<ellipse id="Ellipse_185" class="st1" cx="-40.6" cy="-25.5" rx="17.5" ry="17.5"/>
<path id="Path_946" class="st2" d="M-51.1,34.2c-2.6-0.7-5.1-1.6-7.6-2.6l0.5-13.3l4.9-11c1.1,0.9,2.3,1.6,3.5,2.3
c0.3,0.2,0.6,0.3,0.9,0.5c4.6,2.2,12.2,4.2,19.5-1.3c2.7-2.1,5-4.7,6.7-7.6L-8.8,9l0.7,8.4l0.8,9.8c-1.2,0.8-2.4,1.5-3.6,2.2
c-6.5,3.6-13.7,5.8-21,6.5c-1.7,0.2-3.4,0.2-5.1,0.2C-41.8,36.1-46.5,35.4-51.1,34.2z"/>
<path id="Path_947" class="st2" d="M-47.7-0.9L-47.7-0.9l-0.7,7.2l-0.4,3.8l-0.5,5.6l-1.8,18.5c-2.6-0.7-5.1-1.6-7.6-2.6
c-1.3-0.5-2.5-1.1-3.7-1.8c-2.9-1.5-5.6-3.3-8.2-5.3l-1.9-9l0.1-0.1L-47.7-0.9z"/>
<path id="Path_948" class="st2" d="M-10.9,29.3c-6.5,3.6-13.7,5.8-21,6.5c0.4-6.7,1-13.1,1.6-18.8c0.3-2.9,0.7-5.7,1.1-8.2
c1.2-8,2.5-13.5,3.4-14.2l6.1,4L4.9,7.3l-0.5,9.5c-3.4,4-7.3,7.4-11.6,10.3C-8.5,27.9-9.7,28.7-10.9,29.3z"/>
<path id="Path_949" class="st2" d="M-70.5,24.6c-1.2-0.9-2.3-1.9-3.4-2.9l0.9-6.1l0.7-0.1l3.1-0.4l6.8,14.8
C-65.2,28.3-67.9,26.6-70.5,24.6L-70.5,24.6z"/>
<path id="Path_950" class="st2" d="M8.3,11.5c-1.2,1.9-2.5,3.6-4,5.3c-3.4,4-7.3,7.4-11.6,10.3c-1.2,0.8-2.4,1.5-3.6,2.2l-0.6-2.8
l3.5-9.1l4.2-11.1l8.8,1.1C6.1,8.7,7.2,10.1,8.3,11.5z"/>
<path id="Path_951" class="st3" d="M-23.9-41.4c-2.7-4.3-6.8-7.5-11.6-8.9l-3.6,2.9l1.4-3.3c-1.2-0.2-2.3-0.2-3.5-0.2l-3.2,4.1
l1.3-4c-5.6,0.7-10.7,3.7-14,8.3c-4.1,5.9-4.8,14.1-0.8,20c1.1-3.4,2.4-6.6,3.5-9.9c0.9,0.1,1.7,0.1,2.6,0l1.3-3.1l0.4,3
c4.2-0.4,10.3-1.2,14.3-1.9l-0.4-2.3l2.3,1.9c1.2-0.3,1.9-0.5,1.9-0.7c2.9,4.7,5.8,7.7,8.8,12.5C-22.1-29.8-20.2-35.3-23.9-41.4z"
/>
<ellipse id="Ellipse_186" class="st1" cx="-24.9" cy="-26.1" rx="1.2" ry="2.4"/>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.8 KiB

View File

@ -0,0 +1,38 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 25.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="_x38_8ce59e9-c4b8-4d1d-9d7a-ce0190159aa8"
xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 231.8 231.8"
style="enable-background:new 0 0 231.8 231.8;" xml:space="preserve">
<style type="text/css">
.st0{opacity:0.5;}
.st1{fill:url(#SVGID_1_);}
.st2{fill:#F5F5F5;}
.st3{fill:#333333;}
.st4{fill:#4E73DF;}
.st5{opacity:0.1;enable-background:new ;}
.st6{fill:#BE7C5E;}
</style>
<g class="st0">
<linearGradient id="SVGID_1_" gradientUnits="userSpaceOnUse" x1="115.89" y1="525.2" x2="115.89" y2="756.98" gradientTransform="matrix(1 0 0 -1 0 756.98)">
<stop offset="0" style="stop-color:#808080;stop-opacity:0.25"/>
<stop offset="0.54" style="stop-color:#808080;stop-opacity:0.12"/>
<stop offset="1" style="stop-color:#808080;stop-opacity:0.1"/>
</linearGradient>
<circle class="st1" cx="115.9" cy="115.9" r="115.9"/>
</g>
<circle class="st2" cx="115.9" cy="115.3" r="113.4"/>
<path class="st3" d="M71.6,116.3c0,0-12.9,63.4-19.9,59.8c0,0,67.7,58.5,127.5,0c0,0-10.5-44.6-25.7-59.8H71.6z"/>
<path class="st4" d="M116.2,229c22.2,0,43.9-6.5,62.4-18.7c-4.2-22.8-20.1-24.1-20.1-24.1H70.8c0,0-15,1.2-19.7,22.2
C70.1,221.9,92.9,229.1,116.2,229z"/>
<circle class="st3" cx="115" cy="112.8" r="50.3"/>
<path class="st5" d="M97.3,158.4h35.1l0,0v28.1c0,9.7-7.8,17.5-17.5,17.5l0,0c-9.7,0-17.5-7.9-17.5-17.5L97.3,158.4L97.3,158.4z"/>
<path class="st6" d="M100.7,157.1h28.4c1.9,0,3.4,1.5,3.4,3.3v0v24.7c0,9.7-7.8,17.5-17.5,17.5l0,0c-9.7,0-17.5-7.9-17.5-17.5v0
v-24.7C97.4,158.6,98.9,157.1,100.7,157.1z"/>
<path class="st5" d="M97.4,171.6c11.3,4.2,23.8,4.3,35.1,0.1v-4.3H97.4V171.6z"/>
<circle class="st6" cx="115" cy="123.7" r="50.3"/>
<path class="st3" d="M66.9,104.6h95.9c0,0-8.2-38.7-44.4-36.2S66.9,104.6,66.9,104.6z"/>
<ellipse class="st6" cx="65.8" cy="121.5" rx="4.7" ry="8.8"/>
<ellipse class="st6" cx="164" cy="121.5" rx="4.7" ry="8.8"/>
<path class="st5" d="M66.9,105.9h95.9c0,0-8.2-38.7-44.4-36.2S66.9,105.9,66.9,105.9z"/>
</svg>

After

Width:  |  Height:  |  Size: 2.1 KiB

View File

@ -0,0 +1,44 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 25.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="_x38_8ce59e9-c4b8-4d1d-9d7a-ce0190159aa8"
xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 231.8 231.8"
style="enable-background:new 0 0 231.8 231.8;" xml:space="preserve">
<style type="text/css">
.st0{opacity:0.5;}
.st1{fill:url(#SVGID_1_);}
.st2{fill:#F5F5F5;}
.st3{fill:#4E73DF;}
.st4{fill:#72351C;}
.st5{opacity:0.1;enable-background:new ;}
.st6{fill:#FDA57D;}
</style>
<g class="st0">
<linearGradient id="SVGID_1_" gradientUnits="userSpaceOnUse" x1="115.89" y1="526.22" x2="115.89" y2="758" gradientTransform="matrix(1 0 0 -1 0 758)">
<stop offset="0" style="stop-color:#808080;stop-opacity:0.25"/>
<stop offset="0.54" style="stop-color:#808080;stop-opacity:0.12"/>
<stop offset="1" style="stop-color:#808080;stop-opacity:0.1"/>
</linearGradient>
<circle class="st1" cx="115.9" cy="115.9" r="115.9"/>
</g>
<circle class="st2" cx="116.1" cy="115.1" r="113.4"/>
<path class="st3" d="M116.2,229c22.2,0,43.9-6.5,62.4-18.7c-4.2-22.9-20.1-24.2-20.1-24.2H70.8c0,0-15,1.2-19.7,22.2
C70.1,221.9,92.9,229.1,116.2,229z"/>
<circle class="st4" cx="115" cy="112.8" r="54.8"/>
<path class="st5" d="M97.3,158.4h35.1l0,0v28.1c0,9.7-7.8,17.6-17.5,17.6c0,0,0,0,0,0l0,0c-9.7,0-17.5-7.9-17.5-17.5L97.3,158.4
L97.3,158.4z"/>
<path class="st6" d="M100.7,157.1h28.4c1.9,0,3.3,1.5,3.3,3.4v24.7c0,9.7-7.9,17.5-17.5,17.5l0,0c-9.7,0-17.5-7.9-17.5-17.5v-24.7
C97.3,158.6,98.8,157.1,100.7,157.1L100.7,157.1z"/>
<path class="st5" d="M97.4,171.6c11.3,4.2,23.8,4.3,35.1,0.1v-4.3H97.4V171.6z"/>
<circle class="st6" cx="115" cy="123.7" r="50.3"/>
<path class="st5" d="M79.2,77.9c0,0,21.2,43,81,18l-13.9-21.8l-24.7-8.9L79.2,77.9z"/>
<path class="st4" d="M79.2,77.3c0,0,21.2,43,81,18l-13.9-21.8l-24.7-8.9L79.2,77.3z"/>
<path class="st4" d="M79,74.4c1.4-4.4,3.9-8.4,7.2-11.7c9.9-9.8,26.1-11.8,34.4-23c1.8,3.1,0.7,7.1-2.4,8.9
c-0.2,0.1-0.4,0.2-0.6,0.3c8-0.1,17.2-0.8,21.7-7.3c2.3,5.3,1.3,11.4-2.5,15.7c7.1,0.3,14.6,5.1,15.1,12.2c0.3,4.7-2.6,9.1-6.5,11.9
s-8.5,3.9-13.1,4.9C118.8,89.2,70.3,101.6,79,74.4z"/>
<path class="st4" d="M165.3,124.1H164L138,147.2c-25-11.7-43.3,0-43.3,0l-27.2-22.1l-2.7,0.3c0.8,27.8,23.9,49.6,51.7,48.9
C143.6,173.5,165.3,151.3,165.3,124.1L165.3,124.1z M115,156.1c-9.8,0-17.7-2-17.7-4.4s7.9-4.4,17.7-4.4s17.7,2,17.7,4.4
S124.7,156.1,115,156.1L115,156.1z"/>
<ellipse class="st6" cx="64.7" cy="123.6" rx="4.7" ry="8.8"/>
<ellipse class="st6" cx="165.3" cy="123.6" rx="4.7" ry="8.8"/>
</svg>

After

Width:  |  Height:  |  Size: 2.6 KiB

View File

@ -0,0 +1,47 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 25.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="_x38_8ce59e9-c4b8-4d1d-9d7a-ce0190159aa8"
xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 231.8 231.8"
style="enable-background:new 0 0 231.8 231.8;" xml:space="preserve">
<style type="text/css">
.st0{opacity:0.5;}
.st1{fill:url(#SVGID_1_);}
.st2{fill:#F5F5F5;}
.st3{fill:#4E73DF;}
.st4{fill:#F55F44;}
.st5{opacity:0.1;enable-background:new ;}
.st6{fill:#FDA57D;}
.st7{fill:#333333;}
</style>
<g class="st0">
<linearGradient id="SVGID_1_" gradientUnits="userSpaceOnUse" x1="115.89" y1="9.36" x2="115.89" y2="241.14" gradientTransform="matrix(1 0 0 -1 0 241.14)">
<stop offset="0" style="stop-color:#808080;stop-opacity:0.25"/>
<stop offset="0.54" style="stop-color:#808080;stop-opacity:0.12"/>
<stop offset="1" style="stop-color:#808080;stop-opacity:0.1"/>
</linearGradient>
<circle class="st1" cx="115.9" cy="115.9" r="115.9"/>
</g>
<circle class="st2" cx="116.1" cy="115.1" r="113.4"/>
<path class="st3" d="M116.2,229c22.2,0,43.8-6.5,62.3-18.7c-4.2-22.8-20.1-24.2-20.1-24.2H70.8c0,0-15,1.2-19.7,22.2
C70.1,221.9,92.9,229.1,116.2,229z"/>
<circle class="st4" cx="115" cy="112.8" r="54.8"/>
<path class="st5" d="M97.3,158.4h35.1l0,0v28.1c0,9.7-7.9,17.5-17.5,17.5l0,0l0,0c-9.7,0-17.5-7.9-17.5-17.5l0,0L97.3,158.4
L97.3,158.4z"/>
<path class="st6" d="M100.7,157.1h28.4c1.9,0,3.4,1.5,3.4,3.4l0,0v24.7c0,9.7-7.9,17.5-17.5,17.5l0,0l0,0c-9.7,0-17.5-7.9-17.5-17.5
l0,0v-24.7C97.4,158.6,98.8,157.1,100.7,157.1L100.7,157.1L100.7,157.1z"/>
<path class="st5" d="M97.4,171.6c11.3,4.2,23.8,4.3,35.1,0.1v-4.3H97.4V171.6z"/>
<circle class="st6" cx="115" cy="123.7" r="50.3"/>
<circle class="st4" cx="114.9" cy="57.1" r="20.2"/>
<circle class="st4" cx="114.9" cy="37.1" r="13.3"/>
<path class="st4" d="M106.2,68.2c-9.9-4.4-14.5-15.8-10.5-25.9c-0.1,0.3-0.3,0.6-0.4,0.9c-4.6,10.2,0,22.2,10.2,26.8
s22.2,0,26.8-10.2c0.1-0.3,0.2-0.6,0.4-0.9C127.6,68.5,116,72.6,106.2,68.2z"/>
<path class="st5" d="M79.2,77.9c0,0,21.2,43,81,18l-13.9-21.8l-24.7-8.9L79.2,77.9z"/>
<path class="st4" d="M79.2,77.3c0,0,21.2,43,81,18l-13.9-21.8l-24.7-8.9L79.2,77.3z"/>
<path class="st7" d="M95.5,61.6c13-1,26.1-1,39.2,0C134.7,61.6,105.8,64.3,95.5,61.6z"/>
<path class="st4" d="M118,23c-1,0-2,0-3,0.2h0.8c7.3,0.2,13.1,6.4,12.8,13.7c-0.2,6.2-4.7,11.5-10.8,12.6
c7.3,0.1,13.3-5.8,13.4-13.2C131.2,29.1,125.3,23.1,118,23L118,23z"/>
<ellipse class="st6" cx="64.7" cy="123.6" rx="4.7" ry="8.8"/>
<ellipse class="st6" cx="165.3" cy="123.6" rx="4.7" ry="8.8"/>
<polygon class="st4" points="76,78.6 85.8,73.5 88,81.6 82,85.7 "/>
</svg>

After

Width:  |  Height:  |  Size: 2.7 KiB

View File

@ -0,0 +1,39 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 25.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="b759170a-51c3-4e2f-999d-77dec9fd6d11"
xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 650.9 610.5"
style="enable-background:new 0 0 650.9 610.5;" xml:space="preserve">
<style type="text/css">
.st0{fill:#AFC0E0;}
.st1{opacity:0.2;fill:#FFFFFF;enable-background:new ;}
.st2{opacity:0.1;enable-background:new ;}
.st3{fill:#E3E8F4;}
.st4{fill:#4E73DF;}
</style>
<path class="st0" d="M174,321c-2-1.6-4.2-3-6.6-4.2c-51.8-26.2-157,67.8-157,67.8L0,372.7c0,0,42.1-43.8,92.4-117.3
c45.2-66.1,150.7-51.8,171.4-48.3c2.3,0.4,3.6,0.7,3.6,0.7C298.7,288.3,174,321,174,321z"/>
<path class="st1" d="M269.4,213.9c-0.6-2-1.3-4-2-6c0,0-1.2-0.2-3.6-0.7c-20.7-3.5-126.2-17.8-171.4,48.3C42.1,329,0,372.7,0,372.7
l5.9,6.7c0,0,42.1-43.8,92.4-117.3C143.3,196.3,248,210.2,269.4,213.9z"/>
<path class="st0" d="M337.7,533.4c-79.2,40.8-127.8,77.1-127.8,77.1l-10.5-11.9c0,0,111.1-96.8,85.3-150.9c-0.5-1.2-1.2-2.3-1.9-3.4
c0,0,47.9-119.6,123.9-78.5c0,0,0.1,1,0.2,2.9C407.8,387.8,409.7,496.3,337.7,533.4z"/>
<path class="st2" d="M174,321c-2-1.6-4.2-3-6.6-4.2c29.3-38.9,61.5-75.5,96.3-109.7c2.3,0.4,3.6,0.7,3.6,0.7
C298.7,288.3,174,321,174,321z"/>
<path class="st2" d="M406.9,368.6c-38.6,29.6-79.4,56.1-122.3,79.1c-0.5-1.2-1.2-2.3-1.9-3.4c0,0,47.9-119.6,123.9-78.5
C406.7,365.7,406.8,366.7,406.9,368.6z"/>
<path class="st3" d="M263.6,455.5c-20.3,10.4-41.6,20.5-64,30.2c-33.6,14.6-51.5-2.2-80.7-91.5c0,0,12.5-22.5,37.2-57
c54.3-75.8,167.5-209.1,336.1-286.7C542.7,27.1,596.1,10.1,650.9,0c0,0-9.1,68.8-62,160.1S439.1,365.3,263.6,455.5z"/>
<circle class="st0" cx="435.6" cy="199.7" r="71.6"/>
<path class="st4" d="M469.2,237.9c-21,18.6-53.1,16.6-71.7-4.5c-7.8-8.8-12.2-20-12.7-31.8c-0.2-4.7,0.3-9.4,1.4-14
c0.5-2,1.1-4.1,1.9-6c2.9-7.7,7.7-14.5,13.8-19.9c0.3-0.3,0.6-0.5,0.9-0.8c17.1-14.4,41.5-15.9,60.3-3.8c3.5,2.3,6.7,4.9,9.5,7.9
l1,1.1C492.2,187.2,490.2,219.3,469.2,237.9C469.2,237.8,469.2,237.9,469.2,237.9z"/>
<path class="st0" d="M588.9,160.1c-83-35.2-96.8-109.6-96.8-109.6C542.7,27,596.1,10.1,650.9,0C650.9,0,641.8,68.8,588.9,160.1z"/>
<path class="st0" d="M263.6,455.5c-13.7,7.1-27.9,13.9-42.6,20.7c-7,3.2-14.1,6.4-21.4,9.5c-10.9,4.7-51.5-2.2-80.7-91.5
c0,0,4.1-7.3,12.1-20c6.1-9.6,14.5-22.2,25.1-37c0,0,11,33.2,41.1,67.3C215.8,425.7,238.4,443,263.6,455.5z"/>
<path class="st3" d="M221,476.2c-7,3.2-14.1,6.4-21.4,9.5c-10.9,4.7-51.5-2.2-80.7-91.5c0,0,4.1-7.3,12.1-20
C131,374.2,170.2,456.9,221,476.2z"/>
<path class="st1" d="M463.2,157l-0.1,0l-60.1,3.9c-0.3,0.3-0.6,0.5-0.9,0.8c-6.2,5.4-10.9,12.3-13.8,19.9l84.5-16.6L463.2,157z"/>
<path class="st1" d="M438.8,194.3l-53.9,7.3c-0.2-4.7,0.3-9.4,1.4-14l52.8,1.4L438.8,194.3z"/>
<path class="st1" d="M131.7,408.7c0,0,12.5-22.5,37.2-57C223.2,276,336.4,142.7,504.9,65c45.6-21.1,93.3-36.9,142.5-47.3
C650.1,6.4,650.9,0,650.9,0c-54.8,10.1-108.2,27-158.7,50.5c-168.6,77.7-281.8,211-336.1,286.7c-24.7,34.4-37.2,57-37.2,57
c11.5,35.3,26.6,57,40.5,70.3C149.4,451.4,139.7,433.3,131.7,408.7z"/>
</svg>

After

Width:  |  Height:  |  Size: 3.1 KiB

View File

@ -0,0 +1,118 @@
// Set new default font family and font color to mimic Bootstrap's default styling
Chart.defaults.global.defaultFontFamily = 'Nunito', '-apple-system,system-ui,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,sans-serif';
Chart.defaults.global.defaultFontColor = '#858796';
function number_format(number, decimals, dec_point, thousands_sep) {
// * example: number_format(1234.56, 2, ',', ' ');
// * return: '1 234,56'
number = (number + '').replace(',', '').replace(' ', '');
var n = !isFinite(+number) ? 0 : +number,
prec = !isFinite(+decimals) ? 0 : Math.abs(decimals),
sep = (typeof thousands_sep === 'undefined') ? ',' : thousands_sep,
dec = (typeof dec_point === 'undefined') ? '.' : dec_point,
s = '',
toFixedFix = function(n, prec) {
var k = Math.pow(10, prec);
return '' + Math.round(n * k) / k;
};
// Fix for IE parseFloat(0.55).toFixed(0) = 0;
s = (prec ? toFixedFix(n, prec) : '' + Math.round(n)).split('.');
if (s[0].length > 3) {
s[0] = s[0].replace(/\B(?=(?:\d{3})+(?!\d))/g, sep);
}
if ((s[1] || '').length < prec) {
s[1] = s[1] || '';
s[1] += new Array(prec - s[1].length + 1).join('0');
}
return s.join(dec);
}
// Area Chart Example
var ctx = document.getElementById("myAreaChart");
var myLineChart = new Chart(ctx, {
type: 'line',
data: {
labels: ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"],
datasets: [{
label: "Earnings",
lineTension: 0.3,
backgroundColor: "rgba(78, 115, 223, 0.05)",
borderColor: "rgba(78, 115, 223, 1)",
pointRadius: 3,
pointBackgroundColor: "rgba(78, 115, 223, 1)",
pointBorderColor: "rgba(78, 115, 223, 1)",
pointHoverRadius: 3,
pointHoverBackgroundColor: "rgba(78, 115, 223, 1)",
pointHoverBorderColor: "rgba(78, 115, 223, 1)",
pointHitRadius: 10,
pointBorderWidth: 2,
data: [0, 10000, 5000, 15000, 10000, 20000, 15000, 25000, 20000, 30000, 25000, 40000],
}],
},
options: {
maintainAspectRatio: false,
layout: {
padding: {
left: 10,
right: 25,
top: 25,
bottom: 0
}
},
scales: {
xAxes: [{
time: {
unit: 'date'
},
gridLines: {
display: false,
drawBorder: false
},
ticks: {
maxTicksLimit: 7
}
}],
yAxes: [{
ticks: {
maxTicksLimit: 5,
padding: 10,
// Include a dollar sign in the ticks
callback: function(value, index, values) {
return '$' + number_format(value);
}
},
gridLines: {
color: "rgb(234, 236, 244)",
zeroLineColor: "rgb(234, 236, 244)",
drawBorder: false,
borderDash: [2],
zeroLineBorderDash: [2]
}
}],
},
legend: {
display: false
},
tooltips: {
backgroundColor: "rgb(255,255,255)",
bodyFontColor: "#858796",
titleMarginBottom: 10,
titleFontColor: '#6e707e',
titleFontSize: 14,
borderColor: '#dddfeb',
borderWidth: 1,
xPadding: 15,
yPadding: 15,
displayColors: false,
intersect: false,
mode: 'index',
caretPadding: 10,
callbacks: {
label: function(tooltipItem, chart) {
var datasetLabel = chart.datasets[tooltipItem.datasetIndex].label || '';
return datasetLabel + ': $' + number_format(tooltipItem.yLabel);
}
}
}
}
});

View File

@ -0,0 +1,111 @@
// Set new default font family and font color to mimic Bootstrap's default styling
Chart.defaults.global.defaultFontFamily = 'Nunito', '-apple-system,system-ui,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,sans-serif';
Chart.defaults.global.defaultFontColor = '#858796';
function number_format(number, decimals, dec_point, thousands_sep) {
// * example: number_format(1234.56, 2, ',', ' ');
// * return: '1 234,56'
number = (number + '').replace(',', '').replace(' ', '');
var n = !isFinite(+number) ? 0 : +number,
prec = !isFinite(+decimals) ? 0 : Math.abs(decimals),
sep = (typeof thousands_sep === 'undefined') ? ',' : thousands_sep,
dec = (typeof dec_point === 'undefined') ? '.' : dec_point,
s = '',
toFixedFix = function(n, prec) {
var k = Math.pow(10, prec);
return '' + Math.round(n * k) / k;
};
// Fix for IE parseFloat(0.55).toFixed(0) = 0;
s = (prec ? toFixedFix(n, prec) : '' + Math.round(n)).split('.');
if (s[0].length > 3) {
s[0] = s[0].replace(/\B(?=(?:\d{3})+(?!\d))/g, sep);
}
if ((s[1] || '').length < prec) {
s[1] = s[1] || '';
s[1] += new Array(prec - s[1].length + 1).join('0');
}
return s.join(dec);
}
// Bar Chart Example
var ctx = document.getElementById("myBarChart");
var myBarChart = new Chart(ctx, {
type: 'bar',
data: {
labels: ["January", "February", "March", "April", "May", "June"],
datasets: [{
label: "Revenue",
backgroundColor: "#4e73df",
hoverBackgroundColor: "#2e59d9",
borderColor: "#4e73df",
data: [4215, 5312, 6251, 7841, 9821, 14984],
}],
},
options: {
maintainAspectRatio: false,
layout: {
padding: {
left: 10,
right: 25,
top: 25,
bottom: 0
}
},
scales: {
xAxes: [{
time: {
unit: 'month'
},
gridLines: {
display: false,
drawBorder: false
},
ticks: {
maxTicksLimit: 6
},
maxBarThickness: 25,
}],
yAxes: [{
ticks: {
min: 0,
max: 15000,
maxTicksLimit: 5,
padding: 10,
// Include a dollar sign in the ticks
callback: function(value, index, values) {
return '$' + number_format(value);
}
},
gridLines: {
color: "rgb(234, 236, 244)",
zeroLineColor: "rgb(234, 236, 244)",
drawBorder: false,
borderDash: [2],
zeroLineBorderDash: [2]
}
}],
},
legend: {
display: false
},
tooltips: {
titleMarginBottom: 10,
titleFontColor: '#6e707e',
titleFontSize: 14,
backgroundColor: "rgb(255,255,255)",
bodyFontColor: "#858796",
borderColor: '#dddfeb',
borderWidth: 1,
xPadding: 15,
yPadding: 15,
displayColors: false,
caretPadding: 10,
callbacks: {
label: function(tooltipItem, chart) {
var datasetLabel = chart.datasets[tooltipItem.datasetIndex].label || '';
return datasetLabel + ': $' + number_format(tooltipItem.yLabel);
}
}
},
}
});

View File

@ -0,0 +1,35 @@
// Set new default font family and font color to mimic Bootstrap's default styling
Chart.defaults.global.defaultFontFamily = 'Nunito', '-apple-system,system-ui,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,sans-serif';
Chart.defaults.global.defaultFontColor = '#858796';
// Pie Chart Example
var ctx = document.getElementById("myPieChart");
var myPieChart = new Chart(ctx, {
type: 'doughnut',
data: {
labels: ["Direct", "Referral", "Social"],
datasets: [{
data: [55, 30, 15],
backgroundColor: ['#4e73df', '#1cc88a', '#36b9cc'],
hoverBackgroundColor: ['#2e59d9', '#17a673', '#2c9faf'],
hoverBorderColor: "rgba(234, 236, 244, 1)",
}],
},
options: {
maintainAspectRatio: false,
tooltips: {
backgroundColor: "rgb(255,255,255)",
bodyFontColor: "#858796",
borderColor: '#dddfeb',
borderWidth: 1,
xPadding: 15,
yPadding: 15,
displayColors: false,
caretPadding: 10,
},
legend: {
display: false
},
cutoutPercentage: 80,
},
});

View File

@ -0,0 +1,4 @@
// Call the dataTables jQuery plugin
$(document).ready(function() {
$('#dataTable').DataTable();
});

View File

@ -0,0 +1,56 @@
(function($) {
"use strict"; // Start of use strict
// Toggle the side navigation
$("#sidebarToggle, #sidebarToggleTop").on('click', function(e) {
$("body").toggleClass("sidebar-toggled");
$(".sidebar").toggleClass("toggled");
if ($(".sidebar").hasClass("toggled")) {
$('.sidebar .collapse').collapse('hide');
};
});
// Close any open menu accordions when window is resized below 768px
$(window).resize(function() {
if ($(window).width() < 768) {
$('.sidebar .collapse').collapse('hide');
};
// Toggle the side navigation when window is resized below 480px
if ($(window).width() < 480 && !$(".sidebar").hasClass("toggled")) {
$("body").addClass("sidebar-toggled");
$(".sidebar").addClass("toggled");
$('.sidebar .collapse').collapse('hide');
};
});
// Prevent the content wrapper from scrolling when the fixed side navigation hovered over
$('body.fixed-nav .sidebar').on('mousewheel DOMMouseScroll wheel', function(e) {
if ($(window).width() > 768) {
var e0 = e.originalEvent,
delta = e0.wheelDelta || -e0.detail;
this.scrollTop += (delta < 0 ? 1 : -1) * 30;
e.preventDefault();
}
});
// Scroll to top button appear
$(document).on('scroll', function() {
var scrollDistance = $(this).scrollTop();
if (scrollDistance > 100) {
$('.scroll-to-top').fadeIn();
} else {
$('.scroll-to-top').fadeOut();
}
});
// Smooth scrolling using jQuery easing
$(document).on('click', 'a.scroll-to-top', function(e) {
var $anchor = $(this);
$('html, body').stop().animate({
scrollTop: ($($anchor.attr('href')).offset().top)
}, 1000, 'easeInOutExpo');
e.preventDefault();
});
})(jQuery); // End of use strict

View File

@ -0,0 +1,7 @@
/*!
* Start Bootstrap - SB Admin 2 v4.1.3 (https://startbootstrap.com/theme/sb-admin-2)
* Copyright 2013-2021 Start Bootstrap
* Licensed under MIT (https://github.com/StartBootstrap/startbootstrap-sb-admin-2/blob/master/LICENSE)
*/
!function(l){"use strict";l("#sidebarToggle, #sidebarToggleTop").on("click",function(e){l("body").toggleClass("sidebar-toggled"),l(".sidebar").toggleClass("toggled"),l(".sidebar").hasClass("toggled")&&l(".sidebar .collapse").collapse("hide")}),l(window).resize(function(){l(window).width()<768&&l(".sidebar .collapse").collapse("hide"),l(window).width()<480&&!l(".sidebar").hasClass("toggled")&&(l("body").addClass("sidebar-toggled"),l(".sidebar").addClass("toggled"),l(".sidebar .collapse").collapse("hide"))}),l("body.fixed-nav .sidebar").on("mousewheel DOMMouseScroll wheel",function(e){var o;768<l(window).width()&&(o=(o=e.originalEvent).wheelDelta||-o.detail,this.scrollTop+=30*(o<0?1:-1),e.preventDefault())}),l(document).on("scroll",function(){100<l(this).scrollTop()?l(".scroll-to-top").fadeIn():l(".scroll-to-top").fadeOut()}),l(document).on("click","a.scroll-to-top",function(e){var o=l(this);l("html, body").stop().animate({scrollTop:l(o.attr("href")).offset().top},1e3,"easeInOutExpo"),e.preventDefault()})}(jQuery);

View File

@ -0,0 +1,52 @@
.btn-circle {
border-radius: 100%;
height: 2.5rem;
width: 2.5rem;
font-size: 1rem;
display: inline-flex;
align-items: center;
justify-content: center;
&.btn-sm {
height: 1.8rem;
width: 1.8rem;
font-size: 0.75rem;
}
&.btn-lg {
height: 3.5rem;
width: 3.5rem;
font-size: 1.35rem;
}
}
.btn-icon-split {
padding: 0;
overflow: hidden;
display: inline-flex;
align-items: stretch;
justify-content: center;
.icon {
background: fade-out($black, .85);
display: inline-block;
padding: $btn-padding-y $btn-padding-x;
}
.text {
display: inline-block;
padding: $btn-padding-y $btn-padding-x;
}
&.btn-sm {
.icon {
padding: $btn-padding-y-sm $btn-padding-x-sm;
}
.text {
padding: $btn-padding-y-sm $btn-padding-x-sm;
}
}
&.btn-lg {
.icon {
padding: $btn-padding-y-lg $btn-padding-x-lg;
}
.text {
padding: $btn-padding-y-lg $btn-padding-x-lg;
}
}
}

View File

@ -0,0 +1,36 @@
// Custom Card Styling
.card {
.card-header {
// Format Dropdowns in Card Headings
.dropdown {
line-height: 1;
.dropdown-menu {
line-height: 1.5;
}
}
}
// Collapsable Card Styling
.card-header[data-toggle="collapse"] {
text-decoration: none;
position: relative;
padding: 0.75rem 3.25rem 0.75rem 1.25rem;
&::after {
position: absolute;
right: 0;
top: 0;
padding-right: 1.725rem;
line-height: 51px;
font-weight: 900;
content: '\f107';
font-family: 'Font Awesome 5 Free';
color: $gray-400;
}
&.collapsed {
border-radius: $card-border-radius;
&::after {
content: '\f105';
}
}
}
}

View File

@ -0,0 +1,29 @@
// Area Chart
.chart-area {
position: relative;
height: 10rem;
width: 100%;
@include media-breakpoint-up(md) {
height: 20rem;
}
}
// Bar Chart
.chart-bar {
position: relative;
height: 10rem;
width: 100%;
@include media-breakpoint-up(md) {
height: 20rem;
}
}
// Pie Chart
.chart-pie {
position: relative;
height: 15rem;
width: 100%;
@include media-breakpoint-up(md) {
height: calc(20rem - 43px) !important;
}
}

View File

@ -0,0 +1,21 @@
// Custom Dropdown Styling
.dropdown {
.dropdown-menu {
font-size: $dropdown-font-size;
.dropdown-header {
@extend .text-uppercase;
font-weight: 800;
font-size: 0.65rem;
color: $gray-500;
}
}
}
// Utility class to hide arrow from dropdown
.dropdown.no-arrow {
.dropdown-toggle::after {
display: none;
}
}

View File

@ -0,0 +1,52 @@
// Lucas Bebber's Glitch Effect
// Tutorial and CSS from CSS Tricks
// https://css-tricks.com/glitch-effect-text-images-svg/
.error {
color: $gray-800;
font-size: 7rem;
position: relative;
line-height: 1;
width: 12.5rem;
}
@keyframes noise-anim {
$steps: 20;
@for $i from 0 through $steps {
#{percentage($i*(1/$steps))} {
clip: rect(random(100)+px,9999px,random(100)+px,0);
}
}
}
.error:after {
content: attr(data-text);
position: absolute;
left: 2px;
text-shadow: -1px 0 $red;
top: 0;
color: $gray-800;
background: $gray-100;
overflow: hidden;
clip: rect(0,900px,0,0);
animation: noise-anim 2s infinite linear alternate-reverse;
}
@keyframes noise-anim-2 {
$steps: 20;
@for $i from 0 through $steps {
#{percentage($i*(1/$steps))} {
clip: rect(random(100)+px,9999px,random(100)+px,0);
}
}
}
.error:before {
content: attr(data-text);
position: absolute;
left: -2px;
text-shadow: 1px 0 $blue;
top: 0;
color: $gray-800;
background: $gray-100;
overflow: hidden;
clip: rect(0,900px,0,0);
animation: noise-anim-2 3s infinite linear alternate-reverse;
}

View File

@ -0,0 +1,14 @@
footer.sticky-footer {
padding: 2rem 0;
flex-shrink: 0;
.copyright {
line-height: 1;
font-size: 0.8rem;
}
}
body.sidebar-toggled {
footer.sticky-footer {
width: 100%;
}
}

View File

@ -0,0 +1,60 @@
// Global component styles
html {
position: relative;
min-height: 100%;
}
body {
height: 100%;
}
a {
&:focus {
outline: none;
}
}
// Main page wrapper
#wrapper {
display: flex;
#content-wrapper {
background-color: $gray-100;
width: 100%;
overflow-x: hidden;
#content {
flex: 1 0 auto;
}
}
}
// Set container padding to match gutter width instead of default 15px
.container,
.container-fluid {
padding-left: $grid-gutter-width;
padding-right: $grid-gutter-width;
}
// Scroll to top button
.scroll-to-top {
position: fixed;
right: 1rem;
bottom: 1rem;
display: none;
width: 2.75rem;
height: 2.75rem;
text-align: center;
color: $white;
background: fade-out($gray-800, .5);
line-height: 46px;
&:focus,
&:hover {
color: white;
}
&:hover {
background: $gray-800;
}
i {
font-weight: 800;
}
}

View File

@ -0,0 +1,50 @@
// Pulling these images from Unsplash
// Toshi the dog from https://unsplash.com/@charlesdeluvio - what a funny dog...
.bg-login-image {
background: url($login-image);
background-position: center;
background-size: cover;
}
.bg-register-image {
background: url($register-image);
background-position: center;
background-size: cover;
}
.bg-password-image {
background: url($password-image);
background-position: center;
background-size: cover;
}
form.user {
.custom-checkbox.small {
label {
line-height: 1.5rem;
}
}
.form-control-user {
font-size: 0.8rem;
border-radius: 10rem;
padding: 1.5rem 1rem;
}
.btn-user {
font-size: 0.8rem;
border-radius: 10rem;
padding: 0.75rem 1rem;
}
}
.btn-google {
@include button-variant($brand-google, $white);
}
.btn-facebook {
@include button-variant($brand-facebook, $white);
}

View File

@ -0,0 +1 @@

View File

@ -0,0 +1,3 @@
@import "navs/global.scss";
@import "navs/topbar.scss";
@import "navs/sidebar.scss";

View File

@ -0,0 +1,7 @@
@import "utilities/animation.scss";
@import "utilities/background.scss";
@import "utilities/display.scss";
@import "utilities/text.scss";
@import "utilities/border.scss";
@import "utilities/progress.scss";
@import "utilities/rotate.scss";

View File

@ -0,0 +1,81 @@
// Override Bootstrap default variables here
// Do not edit any of the files in /vendor/bootstrap/scss/!
// Color Variables
// Bootstrap Color Overrides
$white: #fff !default;
$gray-100: #f8f9fc !default;
$gray-200: #eaecf4 !default;
$gray-300: #dddfeb !default;
$gray-400: #d1d3e2 !default;
$gray-500: #b7b9cc !default;
$gray-600: #858796 !default;
$gray-700: #6e707e !default;
$gray-800: #5a5c69 !default;
$gray-900: #3a3b45 !default;
$black: #000 !default;
$blue: #4e73df !default;
$indigo: #6610f2 !default;
$purple: #6f42c1 !default;
$pink: #e83e8c !default;
$red: #e74a3b !default;
$orange: #fd7e14 !default;
$yellow: #f6c23e !default;
$green: #1cc88a !default;
$teal: #20c9a6 !default;
$cyan: #36b9cc !default;
// Custom Colors
$brand-google: #ea4335 !default;
$brand-facebook: #3b5998 !default;
// Set Contrast Threshold
$yiq-contrasted-threshold: 195 !default;
// Typography
$body-color: $gray-600 !default;
$font-family-sans-serif: "Nunito", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", 'Noto Color Emoji' !default;
$font-weight-light: 300 !default;
// $font-weight-base: 400;
$headings-font-weight: 400 !default;
// Shadows
$box-shadow-sm: 0 0.125rem 0.25rem 0 rgba($gray-900, .2) !default;
$box-shadow: 0 0.15rem 1.75rem 0 rgba($gray-900, .15) !default;
// $box-shadow-lg: 0 1rem 3rem rgba($black, .175) !default;
// Borders Radius
$border-radius: 0.35rem !default;
$border-color: darken($gray-200, 2%) !default;
// Spacing Variables
// Change below variable if the height of the navbar changes
$topbar-base-height: 4.375rem !default;
// Change below variable to change the width of the sidenav
$sidebar-base-width: 14rem !default;
// Change below variable to change the width of the sidenav when collapsed
$sidebar-collapsed-width: 6.5rem !default;
// Card
$card-cap-bg: $gray-100 !default;
$card-border-color: $border-color !default;
// Adjust column spacing for symmetry
$spacer: 1rem !default;
$grid-gutter-width: $spacer * 1.5 !default;
// Transitions
$transition-collapse: height .15s ease !default;
// Dropdowns
$dropdown-font-size: 0.85rem !default;
$dropdown-border-color: $border-color !default;
// Images
$login-image: 'https://source.unsplash.com/K4mSJ7kc0As/600x800' !default;
$register-image: 'https://source.unsplash.com/Mv9hjnEUHR4/600x800' !default;
$password-image: 'https://source.unsplash.com/oWTW-jNGl9I/600x800' !default;

View File

@ -0,0 +1,42 @@
// Global styles for both custom sidebar and topbar compoments
.sidebar,
.topbar {
.nav-item {
// Customize Dropdown Arrows for Navbar
&.dropdown {
.dropdown-toggle {
&::after {
width: 1rem;
text-align: center;
float: right;
vertical-align: 0;
border: 0;
font-weight: 900;
content: '\f105';
font-family: 'Font Awesome 5 Free';
}
}
&.show {
.dropdown-toggle::after {
content: '\f107';
}
}
}
// Counter for nav links and nav link image sizing
.nav-link {
position: relative;
.badge-counter {
position: absolute;
transform: scale(0.7);
transform-origin: top right;
right: .25rem;
margin-top: -.25rem;
}
.img-profile {
height: 2rem;
width: 2rem;
}
}
}
}

View File

@ -0,0 +1,477 @@
// Sidebar
.sidebar {
width: $sidebar-collapsed-width;
min-height: 100vh;
.nav-item {
position: relative;
&:last-child {
margin-bottom: 1rem;
}
.nav-link {
text-align: center;
padding: 0.75rem 1rem;
width: $sidebar-collapsed-width;
span {
font-size: 0.65rem;
display: block;
}
}
&.active {
.nav-link {
font-weight: 700;
}
}
// Accordion
.collapse {
position: absolute;
left: calc(#{$sidebar-collapsed-width} + #{$grid-gutter-width} / 2);
z-index: 1;
top: 2px;
// Grow In Animation
@extend .animated--grow-in;
.collapse-inner {
border-radius: $border-radius;
box-shadow: $box-shadow;
}
}
.collapsing {
display: none;
transition: none;
}
.collapse,
.collapsing {
.collapse-inner {
padding: .5rem 0;
min-width: 10rem;
font-size: $dropdown-font-size;
margin: 0 0 1rem 0;
.collapse-header {
margin: 0;
white-space: nowrap;
padding: .5rem 1.5rem;
text-transform: uppercase;
font-weight: 800;
font-size: 0.65rem;
color: $gray-500;
}
.collapse-item {
padding: 0.5rem 1rem;
margin: 0 0.5rem;
display: block;
color: $gray-900;
text-decoration: none;
border-radius: $border-radius;
white-space: nowrap;
&:hover {
background-color: $gray-200;
}
&:active {
background-color: $gray-300;
}
&.active {
color: $primary;
font-weight: 700;
}
}
}
}
}
#sidebarToggle {
width: 2.5rem;
height: 2.5rem;
text-align: center;
margin-bottom: 1rem;
cursor: pointer;
&::after {
font-weight: 900;
content: '\f104';
font-family: 'Font Awesome 5 Free';
margin-right: 0.1rem;
}
&:hover {
text-decoration: none;
}
&:focus {
outline: none;
}
}
&.toggled {
width: 0 !important;
overflow: hidden;
#sidebarToggle::after {
content: '\f105';
font-family: 'Font Awesome 5 Free';
margin-left: 0.25rem;
}
.sidebar-card {
display: none;
}
}
.sidebar-brand {
height: $topbar-base-height;
text-decoration: none;
font-size: 1rem;
font-weight: 800;
padding: 1.5rem 1rem;
text-align: center;
text-transform: uppercase;
letter-spacing: 0.05rem;
z-index: 1;
.sidebar-brand-icon i {
font-size: 2rem;
}
.sidebar-brand-text {
display: none;
}
}
hr.sidebar-divider {
margin: 0 1rem 1rem;
}
.sidebar-heading {
text-align: center;
padding: 0 1rem;
font-weight: 800;
font-size: 0.65rem;
@extend .text-uppercase;
}
.sidebar-card {
display: flex;
flex-direction: column;
align-items: center;
font-size: $font-size-sm;
border-radius: $border-radius;
color: fade-out($white, 0.2);
margin-left: 1rem;
margin-right: 1rem;
margin-bottom: 1rem;
padding: 1rem;
background-color: fade-out($black, 0.9);
.sidebar-card-illustration {
height: 3rem;
display: block;
}
.sidebar-card-title {
font-weight: bold;
}
p {
font-size: 0.75rem;
color: fade-out($white, 0.5);
}
}
}
@include media-breakpoint-up(md) {
.sidebar {
width: $sidebar-base-width !important;
.nav-item {
// Accordion
.collapse {
position: relative;
left: 0;
z-index: 1;
top: 0;
animation: none;
.collapse-inner {
border-radius: 0;
box-shadow: none;
}
}
.collapsing {
display: block;
transition: $transition-collapse;
}
.collapse,
.collapsing {
margin: 0 1rem;
}
.nav-link {
display: block;
width: 100%;
text-align: left;
padding: 1rem;
width: $sidebar-base-width;
i {
font-size: 0.85rem;
margin-right: 0.25rem;
}
span {
font-size: 0.85rem;
display: inline;
}
// Accordion Arrow Icon
&[data-toggle="collapse"] {
&::after {
width: 1rem;
text-align: center;
float: right;
vertical-align: 0;
border: 0;
font-weight: 900;
content: '\f107';
font-family: 'Font Awesome 5 Free';
}
&.collapsed::after {
content: '\f105';
}
}
}
}
.sidebar-brand {
.sidebar-brand-icon i {
font-size: 2rem;
}
.sidebar-brand-text {
display: inline;
}
}
.sidebar-heading {
text-align: left;
}
&.toggled {
overflow: visible;
width: $sidebar-collapsed-width !important;
.nav-item {
// Accordion
.collapse {
position: absolute;
left: calc(#{$sidebar-collapsed-width} + #{$grid-gutter-width} / 2);
z-index: 1;
top: 2px;
// Grow In Animation for Toggled State
animation-name: growIn;
animation-duration: 200ms;
animation-timing-function: transform cubic-bezier(.18, 1.25, .4, 1), opacity cubic-bezier(0, 1, .4, 1);
.collapse-inner {
box-shadow: $box-shadow;
border-radius: $border-radius;
}
}
.collapsing {
display: none;
transition: none;
}
.collapse,
.collapsing {
margin: 0;
}
&:last-child {
margin-bottom: 1rem;
}
.nav-link {
text-align: center;
padding: 0.75rem 1rem;
width: $sidebar-collapsed-width;
span {
font-size: 0.65rem;
display: block;
}
i {
margin-right: 0;
}
&[data-toggle="collapse"]::after {
display: none;
}
}
}
.sidebar-brand {
.sidebar-brand-icon i {
font-size: 2rem;
}
.sidebar-brand-text {
display: none;
}
}
.sidebar-heading {
text-align: center;
}
}
}
}
// Sidebar Color Variants
// Sidebar Light
.sidebar-light {
.sidebar-brand {
color: $gray-700;
}
hr.sidebar-divider {
border-top: 1px solid $gray-200;
}
.sidebar-heading {
color: $gray-500;
}
.nav-item {
.nav-link {
color: $gray-600;
i {
color: $gray-400;
}
&:active,
&:focus,
&:hover {
color: $gray-700;
i {
color: $gray-700;
}
}
// Accordion
&[data-toggle="collapse"]::after {
color: $gray-500;
}
}
&.active {
.nav-link {
color: $gray-700;
i {
color: $gray-700;
}
}
}
}
// Color the sidebar toggler
#sidebarToggle {
background-color: $gray-200;
&::after {
color: $gray-500;
}
&:hover {
background-color: $gray-300;
}
}
}
// Sidebar Dark
.sidebar-dark {
.sidebar-brand {
color: $white;
}
hr.sidebar-divider {
border-top: 1px solid fade-out($white, 0.85);
}
.sidebar-heading {
color: fade-out($white, 0.6);
}
.nav-item {
.nav-link {
color: fade-out($white, 0.2);
i {
color: fade-out($white, 0.7);
}
&:active,
&:focus,
&:hover {
color: $white;
i {
color: $white;
}
}
// Accordion
&[data-toggle="collapse"]::after {
color: fade-out($white, 0.5);
}
}
&.active {
.nav-link {
color: $white;
i {
color: $white;
}
}
}
}
// Color the sidebar toggler
#sidebarToggle {
background-color: fade-out($white, 0.8);
&::after {
color: fade-out($white, 0.5);
}
&:hover {
background-color: fade-out($white, 0.75);
}
}
&.toggled {
#sidebarToggle::after {
color: fade-out($white, 0.5);
}
}
}

View File

@ -0,0 +1,144 @@
// Topbar
.topbar {
height: $topbar-base-height;
#sidebarToggleTop {
height: 2.5rem;
width: 2.5rem;
&:hover {
background-color: $gray-200;
}
&:active {
background-color: $gray-300;
}
}
.navbar-search {
width: 25rem;
input {
font-size: 0.85rem;
height: auto;
}
}
.topbar-divider {
width: 0;
border-right: 1px solid $border-color;
height: calc(#{$topbar-base-height} - 2rem);
margin: auto 1rem;
}
.nav-item {
.nav-link {
height: $topbar-base-height;
display: flex;
align-items: center;
padding: 0 0.75rem;
&:focus {
outline: none;
}
}
&:focus {
outline: none;
}
}
.dropdown {
position: static;
.dropdown-menu {
width: calc(100% - #{$grid-gutter-width});
right: $grid-gutter-width / 2;
}
}
.dropdown-list {
padding: 0;
border: none;
overflow: hidden;
.dropdown-header {
background-color: $primary;
border: 1px solid $primary;
padding-top: 0.75rem;
padding-bottom: 0.75rem;
color: $white;
}
.dropdown-item {
white-space: normal;
padding-top: 0.5rem;
padding-bottom: 0.5rem;
border-left: 1px solid $border-color;
border-right: 1px solid $border-color;
border-bottom: 1px solid $border-color;
line-height: 1.3rem;
.dropdown-list-image {
position: relative;
height: 2.5rem;
width: 2.5rem;
img {
height: 2.5rem;
width: 2.5rem;
}
.status-indicator {
background-color: $gray-200;
height: 0.75rem;
width: 0.75rem;
border-radius: 100%;
position: absolute;
bottom: 0;
right: 0;
border: .125rem solid $white;
}
}
.text-truncate {
max-width: 10rem;
}
&:active {
background-color: $gray-200;
color: $gray-900;
}
}
}
@include media-breakpoint-up(sm) {
.dropdown {
position: relative;
.dropdown-menu {
width: auto;
right: 0;
}
}
.dropdown-list {
width: 20rem !important;
.dropdown-item {
.text-truncate {
max-width: 13.375rem;
}
}
}
}
}
.topbar.navbar-dark {
.navbar-nav {
.nav-item {
.nav-link {
color: fade-out($white, 0.2);
&:hover {
color: $white;
}
&:active {
color: $white;
}
}
}
}
}
.topbar.navbar-light {
.navbar-nav {
.nav-item {
.nav-link {
color: $gray-400;
&:hover {
color: $gray-500;
}
&:active {
color: $gray-600;
}
}
}
}
}

View File

@ -0,0 +1,20 @@
// Import Custom SB Admin 2 Variables (Overrides Default Bootstrap Variables)
@import "variables.scss";
// Import Bootstrap
@import "../vendor/bootstrap/scss/bootstrap.scss";
// Import Custom SB Admin 2 Mixins and Components
@import "mixins.scss";
@import "global.scss";
@import "utilities.scss";
// Custom Components
@import "dropdowns.scss";
@import "navs.scss";
@import "buttons.scss";
@import "cards.scss";
@import "charts.scss";
@import "login.scss";
@import "error.scss";
@import "footer.scss";

View File

@ -0,0 +1,37 @@
// Animation Utilities
// Grow In Animation
@keyframes growIn {
0% {
transform: scale(0.9);
opacity: 0;
}
100% {
transform: scale(1);
opacity: 1;
}
}
.animated--grow-in {
animation-name: growIn;
animation-duration: 200ms;
animation-timing-function: transform cubic-bezier(.18,1.25,.4,1), opacity cubic-bezier(0,1,.4,1);
}
// Fade In Animation
@keyframes fadeIn {
0% {
opacity: 0;
}
100% {
opacity: 1;
}
}
.animated--fade-in {
animation-name: fadeIn;
animation-duration: 200ms;
animation-timing-function: opacity cubic-bezier(0,1,.4,1);
}

View File

@ -0,0 +1,17 @@
// Background Gradient Utilities
@each $color, $value in $theme-colors {
.bg-gradient-#{$color} {
background-color: $value;
background-image: linear-gradient(180deg, $value 10%, darken($value, 15%) 100%);
background-size: cover;
}
}
// Grayscale Background Utilities
@each $level, $value in $grays {
.bg-gray-#{$level} {
background-color: $value !important;
}
}

View File

@ -0,0 +1,7 @@
@each $color, $value in $theme-colors {
@each $position in ['left', 'bottom'] {
.border-#{$position}-#{$color} {
border-#{$position}: .25rem solid $value !important;
}
}
}

View File

@ -0,0 +1,4 @@
// Overflow Hidden
.o-hidden {
overflow: hidden !important;
}

View File

@ -0,0 +1,3 @@
.progress-sm {
height: .5rem;
}

View File

@ -0,0 +1,7 @@
.rotate-15 {
transform: rotate(15deg);
}
.rotate-n-15 {
transform: rotate(-15deg);
}

View File

@ -0,0 +1,54 @@
// Grayscale Text Utilities
.text-xs {
font-size: .7rem;
}
.text-lg {
font-size: 1.2rem;
}
.text-gray-100 {
color: $gray-100 !important;
}
.text-gray-200 {
color: $gray-200 !important;
}
.text-gray-300 {
color: $gray-300 !important;
}
.text-gray-400 {
color: $gray-400 !important;
}
.text-gray-500 {
color: $gray-500 !important;
}
.text-gray-600 {
color: $gray-600 !important;
}
.text-gray-700 {
color: $gray-700 !important;
}
.text-gray-800 {
color: $gray-800 !important;
}
.text-gray-900 {
color: $gray-900 !important;
}
.icon-circle {
height: 2.5rem;
width: 2.5rem;
border-radius: 100%;
display: flex;
align-items: center;
justify-content: center;
}

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,52 @@
//
// Base styles
//
.alert {
position: relative;
padding: $alert-padding-y $alert-padding-x;
margin-bottom: $alert-margin-bottom;
border: $alert-border-width solid transparent;
@include border-radius($alert-border-radius);
}
// Headings for larger alerts
.alert-heading {
// Specified to prevent conflicts of changing $headings-color
color: inherit;
}
// Provide class for links that match alerts
.alert-link {
font-weight: $alert-link-font-weight;
}
// Dismissible alerts
//
// Expand the right padding and account for the close button's positioning.
.alert-dismissible {
padding-right: $close-font-size + $alert-padding-x * 2;
// Adjust close link position
.close {
position: absolute;
top: 0;
right: 0;
z-index: 2;
padding: $alert-padding-y $alert-padding-x;
color: inherit;
}
}
// Alternate styles
//
// Generate contextual modifier classes for colorizing the alert.
@each $color, $value in $theme-colors {
.alert-#{$color} {
@include alert-variant(theme-color-level($color, $alert-bg-level), theme-color-level($color, $alert-border-level), theme-color-level($color, $alert-color-level));
}
}

View File

@ -0,0 +1,54 @@
// Base class
//
// Requires one of the contextual, color modifier classes for `color` and
// `background-color`.
.badge {
display: inline-block;
padding: $badge-padding-y $badge-padding-x;
@include font-size($badge-font-size);
font-weight: $badge-font-weight;
line-height: 1;
text-align: center;
white-space: nowrap;
vertical-align: baseline;
@include border-radius($badge-border-radius);
@include transition($badge-transition);
@at-root a#{&} {
@include hover-focus() {
text-decoration: none;
}
}
// Empty badges collapse automatically
&:empty {
display: none;
}
}
// Quick fix for badges in buttons
.btn .badge {
position: relative;
top: -1px;
}
// Pill badges
//
// Make them extra rounded with a modifier to replace v3's badges.
.badge-pill {
padding-right: $badge-pill-padding-x;
padding-left: $badge-pill-padding-x;
@include border-radius($badge-pill-border-radius);
}
// Colors
//
// Contextual variations (linked badges get darker on :hover).
@each $color, $value in $theme-colors {
.badge-#{$color} {
@include badge-variant($value);
}
}

View File

@ -0,0 +1,42 @@
.breadcrumb {
display: flex;
flex-wrap: wrap;
padding: $breadcrumb-padding-y $breadcrumb-padding-x;
margin-bottom: $breadcrumb-margin-bottom;
@include font-size($breadcrumb-font-size);
list-style: none;
background-color: $breadcrumb-bg;
@include border-radius($breadcrumb-border-radius);
}
.breadcrumb-item {
// The separator between breadcrumbs (by default, a forward-slash: "/")
+ .breadcrumb-item {
padding-left: $breadcrumb-item-padding;
&::before {
float: left; // Suppress inline spacings and underlining of the separator
padding-right: $breadcrumb-item-padding;
color: $breadcrumb-divider-color;
content: escape-svg($breadcrumb-divider);
}
}
// IE9-11 hack to properly handle hyperlink underlines for breadcrumbs built
// without `<ul>`s. The `::before` pseudo-element generates an element
// *within* the .breadcrumb-item and thereby inherits the `text-decoration`.
//
// To trick IE into suppressing the underline, we give the pseudo-element an
// underline and then immediately remove it.
+ .breadcrumb-item:hover::before {
text-decoration: underline;
}
// stylelint-disable-next-line no-duplicate-selectors
+ .breadcrumb-item:hover::before {
text-decoration: none;
}
&.active {
color: $breadcrumb-active-color;
}
}

View File

@ -0,0 +1,163 @@
// stylelint-disable selector-no-qualifying-type
// Make the div behave like a button
.btn-group,
.btn-group-vertical {
position: relative;
display: inline-flex;
vertical-align: middle; // match .btn alignment given font-size hack above
> .btn {
position: relative;
flex: 1 1 auto;
// Bring the hover, focused, and "active" buttons to the front to overlay
// the borders properly
@include hover() {
z-index: 1;
}
&:focus,
&:active,
&.active {
z-index: 1;
}
}
}
// Optional: Group multiple button groups together for a toolbar
.btn-toolbar {
display: flex;
flex-wrap: wrap;
justify-content: flex-start;
.input-group {
width: auto;
}
}
.btn-group {
// Prevent double borders when buttons are next to each other
> .btn:not(:first-child),
> .btn-group:not(:first-child) {
margin-left: -$btn-border-width;
}
// Reset rounded corners
> .btn:not(:last-child):not(.dropdown-toggle),
> .btn-group:not(:last-child) > .btn {
@include border-right-radius(0);
}
> .btn:not(:first-child),
> .btn-group:not(:first-child) > .btn {
@include border-left-radius(0);
}
}
// Sizing
//
// Remix the default button sizing classes into new ones for easier manipulation.
.btn-group-sm > .btn { @extend .btn-sm; }
.btn-group-lg > .btn { @extend .btn-lg; }
//
// Split button dropdowns
//
.dropdown-toggle-split {
padding-right: $btn-padding-x * .75;
padding-left: $btn-padding-x * .75;
&::after,
.dropup &::after,
.dropright &::after {
margin-left: 0;
}
.dropleft &::before {
margin-right: 0;
}
}
.btn-sm + .dropdown-toggle-split {
padding-right: $btn-padding-x-sm * .75;
padding-left: $btn-padding-x-sm * .75;
}
.btn-lg + .dropdown-toggle-split {
padding-right: $btn-padding-x-lg * .75;
padding-left: $btn-padding-x-lg * .75;
}
// The clickable button for toggling the menu
// Set the same inset shadow as the :active state
.btn-group.show .dropdown-toggle {
@include box-shadow($btn-active-box-shadow);
// Show no shadow for `.btn-link` since it has no other button styles.
&.btn-link {
@include box-shadow(none);
}
}
//
// Vertical button groups
//
.btn-group-vertical {
flex-direction: column;
align-items: flex-start;
justify-content: center;
> .btn,
> .btn-group {
width: 100%;
}
> .btn:not(:first-child),
> .btn-group:not(:first-child) {
margin-top: -$btn-border-width;
}
// Reset rounded corners
> .btn:not(:last-child):not(.dropdown-toggle),
> .btn-group:not(:last-child) > .btn {
@include border-bottom-radius(0);
}
> .btn:not(:first-child),
> .btn-group:not(:first-child) > .btn {
@include border-top-radius(0);
}
}
// Checkbox and radio options
//
// In order to support the browser's form validation feedback, powered by the
// `required` attribute, we have to "hide" the inputs via `clip`. We cannot use
// `display: none;` or `visibility: hidden;` as that also hides the popover.
// Simply visually hiding the inputs via `opacity` would leave them clickable in
// certain cases which is prevented by using `clip` and `pointer-events`.
// This way, we ensure a DOM element is visible to position the popover from.
//
// See https://github.com/twbs/bootstrap/pull/12794 and
// https://github.com/twbs/bootstrap/pull/14559 for more information.
.btn-group-toggle {
> .btn,
> .btn-group > .btn {
margin-bottom: 0; // Override default `<label>` value
input[type="radio"],
input[type="checkbox"] {
position: absolute;
clip: rect(0, 0, 0, 0);
pointer-events: none;
}
}
}

View File

@ -0,0 +1,142 @@
// stylelint-disable selector-no-qualifying-type
//
// Base styles
//
.btn {
display: inline-block;
font-family: $btn-font-family;
font-weight: $btn-font-weight;
color: $body-color;
text-align: center;
text-decoration: if($link-decoration == none, null, none);
white-space: $btn-white-space;
vertical-align: middle;
user-select: none;
background-color: transparent;
border: $btn-border-width solid transparent;
@include button-size($btn-padding-y, $btn-padding-x, $btn-font-size, $btn-line-height, $btn-border-radius);
@include transition($btn-transition);
@include hover() {
color: $body-color;
text-decoration: none;
}
&:focus,
&.focus {
outline: 0;
box-shadow: $btn-focus-box-shadow;
}
// Disabled comes first so active can properly restyle
&.disabled,
&:disabled {
opacity: $btn-disabled-opacity;
@include box-shadow(none);
}
&:not(:disabled):not(.disabled) {
cursor: if($enable-pointer-cursor-for-buttons, pointer, null);
&:active,
&.active {
@include box-shadow($btn-active-box-shadow);
&:focus {
@include box-shadow($btn-focus-box-shadow, $btn-active-box-shadow);
}
}
}
}
// Future-proof disabling of clicks on `<a>` elements
a.btn.disabled,
fieldset:disabled a.btn {
pointer-events: none;
}
//
// Alternate buttons
//
@each $color, $value in $theme-colors {
.btn-#{$color} {
@include button-variant($value, $value);
}
}
@each $color, $value in $theme-colors {
.btn-outline-#{$color} {
@include button-outline-variant($value);
}
}
//
// Link buttons
//
// Make a button look and behave like a link
.btn-link {
font-weight: $font-weight-normal;
color: $link-color;
text-decoration: $link-decoration;
@include hover() {
color: $link-hover-color;
text-decoration: $link-hover-decoration;
}
&:focus,
&.focus {
text-decoration: $link-hover-decoration;
}
&:disabled,
&.disabled {
color: $btn-link-disabled-color;
pointer-events: none;
}
// No need for an active state here
}
//
// Button Sizes
//
.btn-lg {
@include button-size($btn-padding-y-lg, $btn-padding-x-lg, $btn-font-size-lg, $btn-line-height-lg, $btn-border-radius-lg);
}
.btn-sm {
@include button-size($btn-padding-y-sm, $btn-padding-x-sm, $btn-font-size-sm, $btn-line-height-sm, $btn-border-radius-sm);
}
//
// Block button
//
.btn-block {
display: block;
width: 100%;
// Vertically space out multiple block buttons
+ .btn-block {
margin-top: $btn-block-spacing-y;
}
}
// Specificity overrides
input[type="submit"],
input[type="reset"],
input[type="button"] {
&.btn-block {
width: 100%;
}
}

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