update v0.0.2 twa sys
This commit is contained in:
@ -1,9 +1,12 @@
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.AspNetCore.Mvc.Abstractions;
|
||||
using Microsoft.AspNetCore.Mvc.Controllers;
|
||||
using Microsoft.AspNetCore.Mvc.Filters;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
@ -35,6 +38,7 @@ namespace AppLibs.Libs
|
||||
// Không có vr => return ViewAsync ngay, bỏ qua action
|
||||
if (context.Controller is Controller c)
|
||||
{
|
||||
ApplyActionAttributesToController(c, context.ActionDescriptor);
|
||||
var result = await ControllerExtensions.ViewAsync(c);
|
||||
context.Result = result; // short-circuit
|
||||
return;
|
||||
@ -42,5 +46,31 @@ namespace AppLibs.Libs
|
||||
|
||||
context.Result = new NotFoundResult();
|
||||
}
|
||||
private static void ApplyActionAttributesToController(Controller controller, ActionDescriptor ad)
|
||||
{
|
||||
if (ad is not ControllerActionDescriptor cad) return;
|
||||
|
||||
// Lấy attribute từ method, fallback về controller (nếu bạn có gắn ở class)
|
||||
var layoutAttr = cad.MethodInfo.GetCustomAttribute<LayoutAttribute>(inherit: true)
|
||||
?? cad.ControllerTypeInfo.GetCustomAttribute<LayoutAttribute>(inherit: true);
|
||||
|
||||
var pageAttr = cad.MethodInfo.GetCustomAttribute<PageInforAttribute>(inherit: true)
|
||||
?? cad.ControllerTypeInfo.GetCustomAttribute<PageInforAttribute>(inherit: true);
|
||||
|
||||
// Truyền qua ViewData (View đọc trực tiếp được),
|
||||
// đồng thời bỏ bản gốc vào HttpContext.Items nếu View/Helper cần cả object.
|
||||
if (layoutAttr != null)
|
||||
{
|
||||
controller.ViewData["LayoutName"] = layoutAttr.LayoutName;
|
||||
}
|
||||
|
||||
if (pageAttr != null)
|
||||
{
|
||||
controller.ViewData["PageID"] =pageAttr.PageID;
|
||||
controller.ViewData["Title"] = pageAttr.PageName;
|
||||
controller.ViewData["FlexPage"] = pageAttr.FlexPage;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@ -19,6 +19,7 @@ namespace AppLibs.Libs
|
||||
|
||||
private string _layoutName;
|
||||
|
||||
public string LayoutName { set { _layoutName = value; } get { return _layoutName; } }
|
||||
public LayoutAttribute():this(LayoutOptions.Default)
|
||||
{
|
||||
}
|
||||
|
||||
@ -11,15 +11,20 @@ namespace AppLibs.Libs
|
||||
|
||||
public PageInforAttribute(string pageID, string pageName)
|
||||
{
|
||||
this._pageID = pageID;
|
||||
this._pageName = pageName;
|
||||
this.PageID = pageID;
|
||||
this.PageName = pageName;
|
||||
}
|
||||
|
||||
public PageInforAttribute(string pageID, string pageName, string flexPage) : this(pageID, pageName)
|
||||
{
|
||||
this._flexPage = flexPage;
|
||||
this.FlexPage = flexPage;
|
||||
|
||||
}
|
||||
|
||||
public string PageID { get => _pageID; set => _pageID = value; }
|
||||
public string PageName { get => _pageName; set => _pageName = value; }
|
||||
public string FlexPage { get => _flexPage; set => _flexPage = value; }
|
||||
|
||||
public void OnActionExecuted(ActionExecutedContext context)
|
||||
{
|
||||
}
|
||||
@ -29,9 +34,9 @@ namespace AppLibs.Libs
|
||||
Controller? controller = context.Controller as Controller;
|
||||
if (controller != null)
|
||||
{
|
||||
controller.ViewData["PageID"] = this._pageID;
|
||||
controller.ViewData["Title"] = this._pageName;
|
||||
controller.ViewData["FlexPage"] = this._flexPage;
|
||||
controller.ViewData["PageID"] = this.PageID;
|
||||
controller.ViewData["Title"] = this.PageName;
|
||||
controller.ViewData["FlexPage"] = this.FlexPage;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,4 +1,20 @@
|
||||
[
|
||||
{
|
||||
"id": 48151624,
|
||||
"title": "Trans World Aviation announces expanded Cargo GSSA partnership with Philippine Airlines at DAD",
|
||||
"contentDesc": "Trans World Aviation expands partnership with Philippine Airlines, appointed Cargo GSSA for Da Nang alongside Hanoi. TWA delivers proven sales, compliant operations, DGR/cold-chain handling, and real-time support as PR’s single cargo contact at both stations.",
|
||||
"pathImage": "48151624.png",
|
||||
"pathPdf": "VINCI wins rights to manage Phnom Penh\u2019s new airport as French-Cambodian entente cordiale takes off.pdf",
|
||||
"catName": "Events"
|
||||
},
|
||||
{
|
||||
"id": 48151654,
|
||||
"title": "Trans World Aviation appointed Passenger GSSA for SriLankan Airlines across Vietnam",
|
||||
"contentDesc": "Trans World Aviation is appointed SriLankan Airlines’ Passenger GSSA for Vietnam, expanding on its Cargo GSSA since 2016. TWA now handles sales, ticketing, airport coordination, charters, compliance, and real-time customer support nationwide.",
|
||||
"pathImage": "48151654.png",
|
||||
"pathPdf": "VINCI wins rights to manage Phnom Penh\u2019s new airport as French-Cambodian entente cordiale takes off.pdf",
|
||||
"catName": "Events"
|
||||
},
|
||||
{
|
||||
"id": 48151623,
|
||||
"title": "VINCI secures management rights for Cambodia\u0027s new Phnom Penh airport.",
|
||||
|
||||
File diff suppressed because one or more lines are too long
66
TWA-App/Views/Home/TestPage.cshtml
Normal file
66
TWA-App/Views/Home/TestPage.cshtml
Normal file
@ -0,0 +1,66 @@
|
||||
<div class="d-f f-c">
|
||||
<p class="sub-title">
|
||||
Aviation Support
|
||||
</p>
|
||||
<h2 class="title">Our Flight Support Services</h2>
|
||||
|
||||
<p class="desc">
|
||||
Our Flight Support suite delivers regulatory, operational and safety services that keep aircraft on schedule and crews informed. We combine regulatory expertise, real‑time monitoring and technical analysis to secure permits, coordinate slots, manage clearances, and provide actionable flight planning and weather intelligence for safe, efficient operations
|
||||
</p>
|
||||
<div class="con-image mb-4">
|
||||
<img alt="Overview of TWA cargo charter operations" class="w-100" src="~/images/3000/3001/cargo-charter-operations.png">
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
<div class="d-f mt-2">
|
||||
<h3 class="title underline">Overflight & Landing/Take-off Permit</h3>
|
||||
</div>
|
||||
<p class="desc">
|
||||
Our team leverages long-standing relationships with civil aviation authorities and diplomatic channels to accelerate permit processing and reduce administrative steps for partners. We provide targeted guidance on documentation, fee handling, and route packaging to fast-track approvals and resolve bottlenecks before they impact operations
|
||||
</p>
|
||||
|
||||
<div class="d-f mt-2">
|
||||
<h3 class="title underline">Slot & PPR</h3>
|
||||
</div>
|
||||
<p class="desc">
|
||||
Through established contacts with airport operator & slot requests, Prior Permission Required (PPR), we could streamline request preferred slots, managing contingencies, and maintaining direct lines, that are able to minimize ground delays with optimal touchdown/takeoff windows and align schedules with network requirements
|
||||
</p>
|
||||
|
||||
<div class="d-f mt-2">
|
||||
<h3 class="title underline">Air Traffic Clearances</h3>
|
||||
</div>
|
||||
<p class="desc">
|
||||
Our operational liaisons and experienced dispatchers coordinate with ATC units to simplify clearance workflows and shorten lead times. By preparing robust, pre-vetted flight plans and ATC clearances as well as managing tactical negotiations on routing or altitude constraints, we help reduce delays and limit re-clearance cycles in congested airspace
|
||||
</p>
|
||||
|
||||
<div class="d-f mt-2">
|
||||
<h3 class="title underline">Real-Time Flight Tracking</h3>
|
||||
</div>
|
||||
<p class="desc">
|
||||
We provide continuous real‑time flight monitoring and situational awareness through integrated monitoring tools and automated alerts watch‑desk along with staffed operations desk to detect deviations, airspace constraints, and ground disruptions immediately. This enables proactive interventions, timely stakeholder notifications, and rapid contingency execution to protect schedules and cargo integrity
|
||||
</p>
|
||||
|
||||
<div class="d-f mt-2">
|
||||
<h3 class="title underline">Inhouse Flight Planning</h3>
|
||||
</div>
|
||||
<p class="desc">
|
||||
Our in-house flight planning team develops optimized routings, precise fuel calculations, weight and balance plans, and alternates tailored to aircraft performance and operational rules along with compliant alternate strategies. We incorporate NOTAMs, airspace constraints and cost‑effective routings to produce robust flight plans that minimize operational risk and support efficient dispatch decisions
|
||||
</p>
|
||||
|
||||
<div class="d-f mt-2">
|
||||
<h3 class="title underline">Weather Briefing</h3>
|
||||
</div>
|
||||
<p class="desc">
|
||||
We deliver concise, operational weather briefings covering enroute conditions, departure/arrival aerodrome forecasts, turbulence, icing, and volcanic ash or other hazards. Briefings include impact analysis, recommended mitigations measures and alternate planning considerations so crews and dispatchers can make informed, safety‑driven choices
|
||||
</p>
|
||||
|
||||
<div class="d-f mt-2">
|
||||
<h3 class="title underline">Weather Briefing</h3>
|
||||
</div>
|
||||
<p class="desc">
|
||||
Runway Analysis: Our runway analysis combines aerodrome data, aircraft performance modeling, and real-time conditions to produce accurate takeoff and landing performance parameters for each aerodrome and aircraft type. Analyses factors in temperature, pressure altitude, load and runway contamination to ensure regulatory compliance and operational safety across varying scenarios
|
||||
|
||||
</p>
|
||||
BIN
TWA-App/wwwroot/images/news/48151624.png
Normal file
BIN
TWA-App/wwwroot/images/news/48151624.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 2.3 MiB |
BIN
TWA-App/wwwroot/images/news/48151654.png
Normal file
BIN
TWA-App/wwwroot/images/news/48151654.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 2.3 MiB |
@ -64,7 +64,7 @@ window.LoadingNews = function () {
|
||||
});
|
||||
const data = await response.json();
|
||||
totalPages = data.totalP;
|
||||
|
||||
htm = "";
|
||||
const initialSlides = data.data.forEach(d => {
|
||||
htm += `<div class="grid-item">
|
||||
<div class="grid-card ">
|
||||
|
||||
@ -771,7 +771,6 @@ class AApp extends window.AObject {
|
||||
loadedPage() {
|
||||
this.metaPage = document.head.querySelector("meta[name=idPage]");
|
||||
if (this.metaPage != null && this.isLoadedLayout) {
|
||||
console.log(window.location.href);
|
||||
this.cachePage.searchFlexPage(window.getPathFromUrl(window.location.href), ((tmp) => {
|
||||
tmp = tmp.layout.info;
|
||||
if (tmp != null && tmp.dynamicF != null) {
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
using AppLibs.Libs;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using TWASys_App.Models;
|
||||
|
||||
namespace TWASys_App.Controllers
|
||||
{
|
||||
@ -13,5 +14,37 @@ namespace TWASys_App.Controllers
|
||||
{
|
||||
return await this.ViewAsync();
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
public async Task<IActionResult> SignIn([FromForm] UserModel user)
|
||||
{
|
||||
if (user.Username is not null && user.Password is not null && user.Username.Length > 0 && user.Password.Length > 0)
|
||||
{
|
||||
await Task.Delay(100);
|
||||
if (user.Username.ToLower().Equals("admin") && user.Password.Equals("TWA@2025"))
|
||||
{
|
||||
HttpContext.Session.SetString("userID", "admin");
|
||||
return Json(new MessageHeader
|
||||
{
|
||||
ID = 10003,
|
||||
Message = "Login Success",
|
||||
Status = 1
|
||||
});
|
||||
}
|
||||
return Json(new MessageHeader
|
||||
{
|
||||
ID = 10002,
|
||||
Message = "The username or password you entered is incorrect",
|
||||
Status = 0
|
||||
});
|
||||
}
|
||||
return Json(new MessageHeader
|
||||
{
|
||||
ID = 10001,
|
||||
Message = "The username and password are required",
|
||||
Status = 0
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@ -67,6 +67,12 @@ namespace TWASys_App.Controllers
|
||||
return await TypeStorageServerModel.GetAllTypeStorage();
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
public async Task<IActionResult> GetStorage([FromForm] StorageModel model)
|
||||
{
|
||||
return await model.GetStorages();
|
||||
}
|
||||
|
||||
[HttpGet]
|
||||
public async Task<IActionResult> GetValidationDomain()
|
||||
{
|
||||
@ -85,6 +91,13 @@ namespace TWASys_App.Controllers
|
||||
return Json(await model.AddAsync());
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
public async Task<IActionResult> UpdateStorageSize([FromForm] StorageModel model)
|
||||
{
|
||||
|
||||
return Json(await model.UpdateStorageSize());
|
||||
}
|
||||
|
||||
[HttpGet]
|
||||
public async Task<IActionResult> GenerationAccessToken()
|
||||
{
|
||||
@ -116,6 +129,19 @@ namespace TWASys_App.Controllers
|
||||
});
|
||||
}
|
||||
|
||||
[HttpGet]
|
||||
public async Task<IActionResult> CheckStorageInit()
|
||||
{
|
||||
await Task.Delay(1);
|
||||
var f = System.IO.File.Exists(System.IO.Path.GetFullPath("Json/dataServer.json"));
|
||||
return Json(new MessageHeader
|
||||
{
|
||||
ID= 61011,
|
||||
Message=f?"has":"no",
|
||||
Status=1
|
||||
});
|
||||
}
|
||||
|
||||
[HttpGet]
|
||||
public async Task<IActionResult> GetSysInfo()
|
||||
{
|
||||
|
||||
@ -17,5 +17,8 @@ namespace TWASys_App.DBModels
|
||||
|
||||
[NotMapped()]
|
||||
public ICollection<ServerAuthorization_has_Token> Tokens { get; set; } = new List<ServerAuthorization_has_Token>();
|
||||
|
||||
[NotMapped()]
|
||||
public ICollection<RefreshToken> RefreshTokens { get; set; } = new List<RefreshToken>();
|
||||
}
|
||||
}
|
||||
|
||||
@ -17,9 +17,12 @@ namespace TWASys_App.DBModels
|
||||
|
||||
public DateTime? CreateDate { get; set; }
|
||||
|
||||
|
||||
public int? Size { get; set; } = null;
|
||||
public string ControllerID { get; set; } = "";
|
||||
|
||||
public int Status { get; set; } = 0;
|
||||
|
||||
[NotMapped]
|
||||
public TypeStorageServer TypeStorageServer { set; get; } = null!;
|
||||
}
|
||||
}
|
||||
|
||||
3
TWASys-App/Json/dataServer1.json
Normal file
3
TWASys-App/Json/dataServer1.json
Normal file
@ -0,0 +1,3 @@
|
||||
{
|
||||
|
||||
}
|
||||
@ -46,7 +46,7 @@
|
||||
},
|
||||
{
|
||||
"id": "8000",
|
||||
"name": "Rooms Management",
|
||||
"name": "Website Management",
|
||||
"icon": "",
|
||||
"group": 1,
|
||||
"url": "",
|
||||
|
||||
@ -1,7 +1,11 @@
|
||||
|
||||
using AppLibs.Libs;
|
||||
using Dapper;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.AspNetCore.Razor.Language.Intermediate;
|
||||
using Microsoft.VisualBasic;
|
||||
using MySqlConnector;
|
||||
using Newtonsoft.Json;
|
||||
using System.Data.Common;
|
||||
using System.Xml.Linq;
|
||||
using TWASys_App.Dapper.AExtentions;
|
||||
@ -11,6 +15,7 @@ namespace TWASys_App.Models
|
||||
{
|
||||
public class StorageModel : ModelBase
|
||||
{
|
||||
public long IdStorageServer { set; get; }
|
||||
public long StorageTypeID { set; get; }
|
||||
|
||||
public string ControllerName { set; get; } = "";
|
||||
@ -19,6 +24,7 @@ namespace TWASys_App.Models
|
||||
|
||||
public ICollection<ValidationDomain> ValidationDomains { set; get; } = new List<ValidationDomain>();
|
||||
|
||||
public int Size { set; get; };
|
||||
public string IpPublic { set; get; } = "";
|
||||
|
||||
public string IpPrivatev4 { set; get; } = "";
|
||||
@ -54,6 +60,45 @@ namespace TWASys_App.Models
|
||||
|
||||
public string RTokenValue { set; get; } = "";
|
||||
|
||||
public async Task<IActionResult> GetStorages(int status = 0)
|
||||
{
|
||||
await using (var con = new MySqlConnection(DBManagement.GetConnectionString()))
|
||||
{
|
||||
string sql = @"
|
||||
WITH d AS (
|
||||
SELECT *
|
||||
FROM StorageServer
|
||||
WHERE status = @status
|
||||
ORDER BY idStorageServer
|
||||
LIMIT @PageSize OFFSET @Offset)
|
||||
SELECT d.*,t.typeName FROM d
|
||||
JOIN TypeStorageServer t ON t.idTypeStorageServer = d.idTypeStorageServer;
|
||||
";
|
||||
await con.OpenAsync();
|
||||
if (IsFirstQuery)
|
||||
{
|
||||
await using (var multi = await con
|
||||
.QueryMultipleAsync("SELECT COUNT(*) FROM StorageServer;" + sql, new { Offset = (PageNumber - 1) * PageSize, PageSize = this.PageSize, status = status }))
|
||||
{
|
||||
int maxRow = await multi.ReadSingleAsync<int>();
|
||||
var types = await multi.ReadAsync();
|
||||
return new JsonResult(new
|
||||
{
|
||||
mrows = maxRow,
|
||||
data = JsonConvert.SerializeObject(types)
|
||||
});
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
var t = (await con.QueryAsync(sql, new { Offset = (PageNumber - 1) * PageSize, PageSize = this.PageSize, status = status }));
|
||||
return new JsonResult(new
|
||||
{
|
||||
data = JsonConvert.SerializeObject(t)
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
public override async Task<MessageHeader> AddAsync()
|
||||
{
|
||||
await using var con = new MySqlConnector.MySqlConnection(DBManagement.GetConnectionString(true));
|
||||
@ -114,6 +159,12 @@ namespace TWASys_App.Models
|
||||
ExpireDate = DateTime.UtcNow.AddMonths(3),
|
||||
Status = 0
|
||||
};
|
||||
var ssAT = new ServerAuthorization_has_Token
|
||||
{
|
||||
IdToken = TokenID,
|
||||
Count = 1,
|
||||
Status = 0
|
||||
};
|
||||
var rT = new RefreshToken
|
||||
{
|
||||
IdRefreshToken = RTokenID,
|
||||
@ -129,6 +180,7 @@ namespace TWASys_App.Models
|
||||
bi.AddRow(ss_lc);
|
||||
bi.AddRow(serverAuthorization);
|
||||
bi.AddRow(token);
|
||||
bi.AddRow(ssAT);
|
||||
bi.AddRow(rT);
|
||||
await bi.ExcuteQuery();
|
||||
await trans.CommitAsync();
|
||||
@ -155,5 +207,73 @@ namespace TWASys_App.Models
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public async Task<MessageHeader> UpdateStorageSize()
|
||||
{
|
||||
var fMess = new MessageHeader();
|
||||
string sql = @"UPDATE StorageServer
|
||||
SET Size = @size
|
||||
Where idStorageServer = @idStorage;
|
||||
WITH sa_need AS (
|
||||
SELECT idServerAuthorization
|
||||
FROM ServerAuthorization
|
||||
WHERE idStorageServer = @idStorage
|
||||
),
|
||||
maxc AS (
|
||||
SELECT idServerAuthorization, MAX(`count`) AS max_count
|
||||
FROM ServerAuthorization_has_Token
|
||||
WHERE idServerAuthorization IN (SELECT idServerAuthorization FROM sa_need)
|
||||
GROUP BY idServerAuthorization
|
||||
)
|
||||
SELECT
|
||||
sa.idServerAuthorization,
|
||||
st.idToken,
|
||||
t.accessToken
|
||||
FROM sa_need sa
|
||||
JOIN maxc m ON m.idServerAuthorization = sa.idServerAuthorization
|
||||
JOIN ServerAuthorization_has_Token st
|
||||
ON st.idServerAuthorization = sa.idServerAuthorization AND st.`count` = m.max_count
|
||||
LEFT JOIN Token t ON t.idToken = st.idToken;
|
||||
WITH sa_need AS (
|
||||
SELECT idServerAuthorization
|
||||
FROM ServerAuthorization
|
||||
WHERE idStorageServer = @idStorage)
|
||||
SELECT r.*
|
||||
FROM sa_need s
|
||||
JOIN RefreshToken r
|
||||
ON r.idServerAuthorization = s.idServerAuthorization
|
||||
WHERE r.idRefreshToken = (
|
||||
SELECT r2.idRefreshToken
|
||||
FROM RefreshToken r2
|
||||
WHERE r2.idServerAuthorization = s.idServerAuthorization and r2.status = 0
|
||||
ORDER BY r2.expireDate DESC
|
||||
LIMIT 1);";
|
||||
try
|
||||
{
|
||||
await using var con = new MySqlConnection(DBManagement.GetConnectionString(true));
|
||||
await con.OpenAsync();
|
||||
using var trans = await con.BeginTransactionAsync();
|
||||
using var multi = await con.QueryMultipleAsync(sql, new { size = Size, id = IdStorageServer }, trans);
|
||||
IList<dynamic> tokens = (await multi.ReadAsync()).AsList();
|
||||
IList<dynamic> rTokens = (await multi.ReadAsync()).AsList();
|
||||
using (var writer = new StreamWriter(Path.GetFullPath("Json/dataServer.json"), false))
|
||||
{
|
||||
await writer.WriteAsync(JsonConvert.SerializeObject(new
|
||||
{
|
||||
idRToken = "",
|
||||
rToken = "",
|
||||
cDate = "",
|
||||
eDate = "",
|
||||
token = "",
|
||||
idToken = ""
|
||||
}));
|
||||
}
|
||||
}
|
||||
catch (DbException ex)
|
||||
{
|
||||
|
||||
}
|
||||
return fMess;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
8
TWASys-App/Models/UserModel.cs
Normal file
8
TWASys-App/Models/UserModel.cs
Normal file
@ -0,0 +1,8 @@
|
||||
namespace TWASys_App.Models
|
||||
{
|
||||
public class UserModel
|
||||
{
|
||||
public string Username { set; get; } = "";
|
||||
public string Password { set; get; } = "";
|
||||
}
|
||||
}
|
||||
@ -2,6 +2,7 @@
|
||||
using Microsoft.AspNetCore.Http.Features;
|
||||
using System.Net;
|
||||
using System.Text;
|
||||
using TWASys_App.Models.Login;
|
||||
|
||||
await WSNavigation.LoadJson();
|
||||
var builder = WebApplication.CreateBuilder(args);
|
||||
@ -10,6 +11,7 @@ builder.Services.Configure<FormOptions>(o => {
|
||||
});
|
||||
builder.Services.AddControllers(options =>
|
||||
{
|
||||
options.Filters.Add(new LoginCheckFilter());
|
||||
options.Filters.Add<AsyncGateAttribute>();
|
||||
}).AddJsonOptions(options =>
|
||||
{
|
||||
|
||||
@ -6,38 +6,39 @@
|
||||
<div class="frm-login">
|
||||
<div class="ws-login">
|
||||
<div class="frm-header d-f f-c a-i-center">
|
||||
<a app-nav href="@Url.AbsoluteContent("~/")" class="c_logo d-f j-c-center">
|
||||
<a app-nav href="@Url.AbsoluteContent("~/")" class="c_logo d-f j-c-center mb-4">
|
||||
<img src="@Url.AbsoluteContent("~/images/logo/slogo.png")">
|
||||
|
||||
</a>
|
||||
|
||||
</div>
|
||||
<div class="AWizard tabcontents">
|
||||
<div class="tabcontent">
|
||||
|
||||
<div class="frm-header">
|
||||
<h2 class="title">Sign In</h2>
|
||||
<span class="d-f f-wrap desc">Bạn chưa có tài khoản? <a href="javascript:void(0)" class="ml-2" id="navSignUp">Đăng ký ngay</a></span>
|
||||
<span class="d-f f-wrap desc a-i-center">Don’t have an account? <a href="javascript:void(0)" class="ml-2" id="navSignUp">Sign up</a></span>
|
||||
</div>
|
||||
<div class="frm-input mt-4">
|
||||
<label>Username</label>
|
||||
<div class="c-input">
|
||||
<span class="ico atg a-1x atg-user"></span>
|
||||
<input type="text" class="input" placeholder="Your username" />
|
||||
<input id="txtUser" type="text" class="input" placeholder="Your username" />
|
||||
<span class="line"></span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="frm-input">
|
||||
<div class="frm-input mb-2">
|
||||
<label>Password</label>
|
||||
<div class="c-input">
|
||||
<span class="ico atg a-1x atg-user"></span>
|
||||
<input type="password" class="input" placeholder="Your password" />
|
||||
<input id="txtPass" type="password" class="input" placeholder="Your password" />
|
||||
<span class="line"></span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="c_validation" id="frm_login_summary">
|
||||
<p class="mess_error"></p>
|
||||
</div>
|
||||
<div class="frm-header d-f f-wrap j-c-between a-i-center">
|
||||
<a href="javascript:void(0)" id="forgetPass">Forget the password?</a>
|
||||
<button class="btn btn-primary btn-effect">Sign In</button>
|
||||
<button class="btn btn-primary btn-effect" id="SignIn">Sign in</button>
|
||||
</div>
|
||||
|
||||
|
||||
@ -114,6 +115,8 @@
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -19,11 +19,12 @@
|
||||
<div class="cfull">
|
||||
<div class="r-n-g">
|
||||
<div class="c-12">
|
||||
<div class="card-body">
|
||||
<div class="d-f">
|
||||
<div class="card-body" data-dropdown>
|
||||
<div class="d-f dropdown aslidedown">
|
||||
<h4>Storage Initialization</h4>
|
||||
<div class="more"><span class="atg atg-more"></span></div>
|
||||
</div>
|
||||
<div class="sub-item">
|
||||
<div class="d-f f-c form-group-con mb-2 ">
|
||||
<div class="form-group d-f f-c">
|
||||
<label>Total Size</label>
|
||||
@ -51,22 +52,21 @@
|
||||
</div>
|
||||
<div class="brn-group">
|
||||
<button id="btAdd" type="button" class="btn btn-effect btn-primary mt-2 waves-effect waves-float d-f a-i-center">
|
||||
Add
|
||||
</button>
|
||||
<button id="btLogin" type="button" class="btn btn-effect btn-primary mt-2 waves-effect waves-float d-f a-i-center">
|
||||
Login Microsoft 365
|
||||
Save
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="c-12">
|
||||
<div class="card-body">
|
||||
<div class="d-f">
|
||||
<div class="card-body" data-dropdown>
|
||||
<a class="d-f dropdown aslidedown">
|
||||
<h4>Storage Setting</h4>
|
||||
<div class="more"><span class="atg atg-more"></span></div>
|
||||
</div>
|
||||
</a>
|
||||
<div class="sub-item">
|
||||
<h5 class="mt-2 mb-2">Search Fillter</h5>
|
||||
<div class="d-f f-c form-group-con mb-2 ">
|
||||
<div class="form-group d-f f-c">
|
||||
@ -125,14 +125,16 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="c-12">
|
||||
<div class="card-body">
|
||||
<div class="d-f">
|
||||
<div class="card-body" data-dropdown>
|
||||
<div class="d-f dropdown aslidedown">
|
||||
<h4>Your Storage</h4>
|
||||
<div class="more"><span class="atg atg-more"></span></div>
|
||||
</div>
|
||||
<div class="sub-item">
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -23,7 +23,7 @@
|
||||
user-select: none
|
||||
}
|
||||
|
||||
a {,
|
||||
a {
|
||||
text-decoration: none
|
||||
}
|
||||
|
||||
|
||||
@ -43,9 +43,9 @@
|
||||
.abs-table th {
|
||||
color: #fff;
|
||||
background-color: #36304a;
|
||||
padding: 20px 10px 20px;
|
||||
font-size: .9rem;
|
||||
font-weight: 500;
|
||||
padding: 18px 10px 18px;
|
||||
font-size: .82rem;
|
||||
font-weight: 600;
|
||||
text-transform: capitalize;
|
||||
letter-spacing: .5px
|
||||
}
|
||||
@ -64,7 +64,7 @@
|
||||
text-align: center;
|
||||
font-weight: 400;
|
||||
color: #808080;
|
||||
padding: 8px 15px
|
||||
padding: 15px
|
||||
}
|
||||
|
||||
.abs-container {
|
||||
|
||||
@ -53,7 +53,6 @@
|
||||
max-width: 100% !important
|
||||
}
|
||||
}
|
||||
|
||||
.ws-login {
|
||||
box-shadow: 0 2px 3px rgba(96, 96, 96, 0.1);
|
||||
background-color: #fff;
|
||||
@ -79,11 +78,12 @@
|
||||
padding-left: 25px;
|
||||
}
|
||||
|
||||
.ws-login .title, .ws-login .desc {
|
||||
.ws-login .desc{
|
||||
font-size: .92rem;
|
||||
}
|
||||
|
||||
.ws-login .hint {
|
||||
font-size: .82rem;
|
||||
font-size: .8rem;
|
||||
}
|
||||
|
||||
|
||||
@ -109,8 +109,8 @@
|
||||
margin-right: -15px;
|
||||
}
|
||||
|
||||
.frm-input, .frm-header {
|
||||
padding: 0 15px;
|
||||
.frm-input, .frm-header, .c_validation {
|
||||
padding: 0 5px;
|
||||
margin-bottom: 25px;
|
||||
}
|
||||
|
||||
@ -163,3 +163,9 @@
|
||||
.frm-input .c-input:not(.line) input:hover, .frm-input .c-input:not(.line) input:focus, .frm-input .con-aselect.active .aselect {
|
||||
border-color: var(--color-primary);
|
||||
}
|
||||
|
||||
.main-login a {
|
||||
color: #454545;
|
||||
font-size: .85rem;
|
||||
font-weight: 600
|
||||
}
|
||||
@ -28,6 +28,7 @@ html {
|
||||
font-weight: 500;
|
||||
}
|
||||
a{
|
||||
position: relative;
|
||||
text-decoration: none
|
||||
}
|
||||
|
||||
@ -73,8 +74,10 @@ body[page="10001"] #header {
|
||||
|
||||
h1, h2, h3, h4, h5, h6 {
|
||||
font-weight: 600;
|
||||
color: #5e5873;
|
||||
margin-bottom: 5px
|
||||
color: #5e5873
|
||||
}
|
||||
h2{
|
||||
font-size: 2rem;
|
||||
}
|
||||
|
||||
h5 {
|
||||
@ -340,7 +343,8 @@ nav {
|
||||
transform: rotate(90deg);
|
||||
}
|
||||
.more span {
|
||||
transition: all .3s ease-in;
|
||||
display: inline-block;
|
||||
transition: all .3s ease-in-out;
|
||||
transform: rotate(0)
|
||||
}
|
||||
.more {
|
||||
@ -464,6 +468,16 @@ nav {
|
||||
right: 0
|
||||
}
|
||||
|
||||
.card-body .dropdown{
|
||||
cursor: pointer
|
||||
}
|
||||
|
||||
.card-body .sub-item{
|
||||
box-shadow: none !important;
|
||||
position: relative !important
|
||||
}
|
||||
|
||||
|
||||
.card-body {
|
||||
border-radius: var(--border-radius);
|
||||
padding: 20px 20px;
|
||||
@ -793,6 +807,40 @@ nav {
|
||||
box-shadow: 0 3px 10px 0 rgb(34 41 47 / 10%);
|
||||
}
|
||||
|
||||
.amultitag .item{
|
||||
transition: all .3s ease-in-out;
|
||||
cursor: pointer;
|
||||
border-radius: var(--radius);
|
||||
margin: 5px;
|
||||
background: var(--color-primary);
|
||||
padding: 5px 10px;
|
||||
font-size: .8rem;
|
||||
color: #fff
|
||||
}
|
||||
.amultitag .item .con-ico {
|
||||
margin-left: 0;
|
||||
height: 20px;
|
||||
border-radius: 50%;
|
||||
color: #5e5873;
|
||||
visibility: hidden;
|
||||
width: 0;
|
||||
transition-delay: 0;
|
||||
transition: width .3s ease-in-out, visibility .3s ease-in-out;
|
||||
transition-delay: .3s;
|
||||
transition: background .3s ease-in-out, margin-left .3s ease-in-out
|
||||
}
|
||||
.amultitag .item:hover .con-ico {
|
||||
margin-left: 10px;
|
||||
background: #fff;
|
||||
visibility: visible;
|
||||
width: 20px
|
||||
}
|
||||
|
||||
.amultitag .item:hover .con-ico:hover{
|
||||
color:#fff;
|
||||
background: var(--secondary);
|
||||
}
|
||||
|
||||
.form-group input, .form-group .aselect, .form-group textarea {
|
||||
font-size: .85rem;
|
||||
width: 100%;
|
||||
@ -1210,17 +1258,17 @@ input[type=checkbox] {
|
||||
top: 50%;
|
||||
transform: translateY(-50%)
|
||||
}
|
||||
.mess-info{
|
||||
[class^=mess_] {
|
||||
font-size: .82rem;
|
||||
font-weight: 400;
|
||||
margin: 5px 0;
|
||||
}
|
||||
|
||||
.mess-success {
|
||||
.mess_success {
|
||||
color: #28c76f;
|
||||
}
|
||||
|
||||
.mess-error {
|
||||
.mess_error {
|
||||
color: #ea5455;
|
||||
}
|
||||
|
||||
@ -1264,7 +1312,7 @@ input[type=checkbox] {
|
||||
|
||||
.animationSlide {
|
||||
width: 100%;
|
||||
overflow-x: hidden;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.animationSlide .slideContent {
|
||||
@ -1273,11 +1321,16 @@ input[type=checkbox] {
|
||||
}
|
||||
|
||||
.animationSlide .tabcontent.show {
|
||||
visibility: visible;
|
||||
height: auto;
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.animationSlide .tabcontent {
|
||||
opacity: 0;
|
||||
transition: .3s all ease-in-out
|
||||
visibility:hidden;
|
||||
height: 0;
|
||||
opacity: 0
|
||||
}
|
||||
|
||||
.animationFade .tabcontent {
|
||||
@ -1303,3 +1356,9 @@ input[type=checkbox] {
|
||||
padding: 0;
|
||||
}
|
||||
/*******************End Page**********************/
|
||||
|
||||
|
||||
/*********Login Form**********/
|
||||
.c_validation{
|
||||
margin-bottom: 15px !important
|
||||
}
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
import AWizard from "/js/libs/js-AWizard.js";
|
||||
import AButton from "/js/libs/js-AButton.js";
|
||||
|
||||
window.L10001 = function () {
|
||||
Waves.attach('.btn-effect', ['waves-float']);
|
||||
@ -18,6 +19,49 @@ window.L10001 = function () {
|
||||
navSignUp.addEventListener("click", (e) => {
|
||||
wrd1.nextPage(2);
|
||||
});
|
||||
|
||||
window.requestTimeout(() => {
|
||||
const v = document.querySelector(".c-login");
|
||||
let top = (v.parentElement.clientHeight / 2) - (v.clientHeight / 2);
|
||||
if (v.clientHeight <= window.innerHeight) {
|
||||
top = top - (window.innerHeight - v.clientHeight) / 2
|
||||
} else {
|
||||
top = top - 40;
|
||||
}
|
||||
|
||||
if (window.getOS() == "iOS") {
|
||||
} else {
|
||||
window.smScroll.scrollTop = top;
|
||||
}
|
||||
}, 500);
|
||||
|
||||
let btn = new AButton(document.getElementById("SignIn"));
|
||||
btn.on("click_SignIn", (el) => {
|
||||
btn.AddLoading(el);
|
||||
document.querySelector("#frm_login_summary .mess_error").innerHTML = "";
|
||||
let promise = new Promise(async function (resolve, reject) {
|
||||
const fd = new FormData();
|
||||
fd.append("username", document.getElementById("txtUser").value);
|
||||
fd.append("password", document.getElementById("txtPass").value)
|
||||
const response = await fetch(`/Login/SignIn`, {
|
||||
method: 'POST',
|
||||
body: fd
|
||||
});
|
||||
const data = await response.json();
|
||||
if (data) {
|
||||
switch (data.Status) {
|
||||
case 0:
|
||||
document.querySelector("#frm_login_summary .mess_error").innerHTML = data.Message;
|
||||
break;
|
||||
case 1:
|
||||
window.app.initNavApp("/");
|
||||
break;
|
||||
}
|
||||
btn.RemoveLoading(el);
|
||||
}
|
||||
});
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
function ComeBack(e, wrd) {
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
import ASpinButton from '/js/libs/js-ASpinButton.js';
|
||||
import ASpinButton from '/js/libs/js-ASpinButton.js';
|
||||
import ASlideDown from '/js/libs/js-ASlideDown.js';
|
||||
import AButton from '/js/libs/js-AButton.js';
|
||||
import AMultiTag from '/js/libs/js-AMultiTag.js';
|
||||
import AModal from '/js/libs/js-AModal.js';
|
||||
@ -7,8 +8,10 @@ import ASelect from '/js/libs/js-ASelect.js';
|
||||
import AOverlay from '/js/libs/js-AOverlay.js';
|
||||
import AWizard from '/js/libs/js-AWizard.js';
|
||||
import AAutoFill from '/js/libs/js-AAutoFill.js';
|
||||
import ATable from '/js/libs/js-ATable.js';
|
||||
|
||||
const tmp = `<div class="slider-scrollbar" data-scrollbar>
|
||||
const tmp = `
|
||||
<div class="slider-scrollbar" data-scrollbar>
|
||||
<div class="aslider">
|
||||
<h4 class="mb-2">Storage Server</h4>
|
||||
<div class="atabs">
|
||||
@ -33,8 +36,7 @@ const tmp = `<div class="slider-scrollbar" data-scrollbar>
|
||||
<div class="form-group d-f f-c">
|
||||
<label for="idType">Storage Server Type</label>
|
||||
<div class="input-group">
|
||||
<select id="idType" class="aselect dropdown" data-width="auto" data-max-height="250" isSearch>
|
||||
</select>
|
||||
<select id="idType" class="aselect dropdown" data-width="auto" data-max-height="250" isSearch></select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group d-f f-c">
|
||||
@ -52,12 +54,9 @@ const tmp = `<div class="slider-scrollbar" data-scrollbar>
|
||||
<div class="form-group d-f f-c">
|
||||
<label for="validDomain">Validation Domain</label>
|
||||
<div class="input-group">
|
||||
<select id="validDomain" class="aselect dropdown" data-width="auto" data-max-height="250" isMultiple>
|
||||
|
||||
</select>
|
||||
<select id="validDomain" class="aselect dropdown" data-width="auto" data-max-height="250" isMultiple></select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div class="tabcontent">
|
||||
@ -97,15 +96,13 @@ const tmp = `<div class="slider-scrollbar" data-scrollbar>
|
||||
<div class="form-group d-f f-c">
|
||||
<label for="idSiteList">Sites List</label>
|
||||
<div class="input-group">
|
||||
<select id="idSiteList" class="aselect dropdown" data-width="auto" data-max-height="250" isSearch>
|
||||
</select>
|
||||
<select id="idSiteList" class="aselect dropdown" data-width="auto" data-max-height="250" isSearch></select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group d-f f-c">
|
||||
<label for="idDrivesList">Drives List</label>
|
||||
<div class="input-group">
|
||||
<select id="idDrivesList" class="aselect dropdown" data-width="auto" data-max-height="250" isSearch>
|
||||
</select>
|
||||
<select id="idDrivesList" class="aselect dropdown" data-width="auto" data-max-height="250" isSearch></select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group d-f f-c">
|
||||
@ -257,15 +254,9 @@ const tmp = `<div class="slider-scrollbar" data-scrollbar>
|
||||
</div>
|
||||
</div>
|
||||
<div class="tabcontent">
|
||||
<div class="c-table">
|
||||
</div>
|
||||
<div class="form-group d-f">
|
||||
<button id="btAddStorage" type="button" class="btn btn-effect btn-primary mt-2 waves-effect waves-float d-f a-i-center">
|
||||
Next
|
||||
</button>
|
||||
<button id="btReset" type="button" class="btn btn-effect btn-primary mt-2 ml-2 waves-effect waves-float d-f a-i-center">
|
||||
Reset
|
||||
</button>
|
||||
<div class="storageTb c-table"></div>
|
||||
<div class="form-group d-f p-0">
|
||||
<button id="btSaveST" type="button" class="btn btn-effect btn-primary mt-2 waves-effect waves-float d-f a-i-center">Save</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="tabcontent">
|
||||
@ -273,9 +264,8 @@ const tmp = `<div class="slider-scrollbar" data-scrollbar>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>`;
|
||||
|
||||
|
||||
</div>
|
||||
`;
|
||||
const lay1 = `
|
||||
<div class="w-100 h-100">
|
||||
<iframe id="authenMic"></iframe>
|
||||
@ -288,25 +278,60 @@ window.L6101 = function () {
|
||||
window.app.loadCSS(asyncStyleSheets);
|
||||
var ov = new AOverlay(document.body);
|
||||
ov.createOverlay();
|
||||
|
||||
const $v = id => (document.getElementById(id)?.value ?? '').trim();
|
||||
let tbSS = null;
|
||||
let eleSS = new ASlideDown(document.querySelectorAll(".aslidedown"));
|
||||
let pr1 = new Promise(async function (resolve, reject) {
|
||||
const response = await fetch("/Storage/CheckStorageInit", {
|
||||
method: 'GET',
|
||||
headers: {
|
||||
'Accept': 'application/json'
|
||||
}
|
||||
});
|
||||
const data = await response.json();
|
||||
if (data.Status == 1) {
|
||||
if (data.Message == "has") {
|
||||
eleSS.get(0).disable_Close();
|
||||
eleSS.get(1).enable_Open();
|
||||
eleSS.get(2).enable_Open();
|
||||
} else {
|
||||
eleSS.get(0).enable_Open();
|
||||
eleSS.get(1).disable_Close();
|
||||
eleSS.get(2).disable_Close();
|
||||
var ele1 = new ASpinButton(document.getElementById("totalSize"));
|
||||
var ele2 = new AMultiTag(document.getElementById("listStorage"));
|
||||
|
||||
const $v = id => (document.getElementById(id)?.value ?? '').trim();
|
||||
var slider = new AModal(tmp);
|
||||
slider.createModal("CustomForm", "slider-right");
|
||||
var Scrollbar = window.Scrollbar;
|
||||
const mScroll = Scrollbar.init(slider.CustomContainer.querySelector(".slider-scrollbar"), window.scroll_options);
|
||||
slider.overlay.isCloseOverlay(true);
|
||||
|
||||
var tabs = new ATab(slider.CustomContainer.querySelector(".atabs"), slider.CustomContainer.querySelector(".StorageTabs"));
|
||||
var wrd1 = new AWizard(slider.CustomContainer.querySelector(".AWizard"));
|
||||
var wrd1 = new AWizard(slider.CustomContainer.querySelector(".awStorageConnector"));
|
||||
var as = new ASelect(slider.CustomContainer.querySelectorAll(".aselect"));
|
||||
window.testV = as;
|
||||
|
||||
var asIdType = as.get(0);
|
||||
wrd1.on("onBeforeBack", (evt) => {
|
||||
mScroll.scrollTo(0, 0);
|
||||
});
|
||||
tabs.on("changed", (e) => {
|
||||
if (e.tabIndex == 1) {
|
||||
if (tbSS == null) {
|
||||
tbSS = new ATable(document.querySelector(".storageTb"), 10);
|
||||
tbSS.labelID = "idStorageServer";
|
||||
tbSS.SetScrollBarY(400);
|
||||
tbSS.AddHeader("Storage Name", "180px", "180px", "storageName");
|
||||
tbSS.AddHeader("Storage Type", "180px", "180px", "typeName");
|
||||
tbSS.AddHeader("Controller Name", "180px", "180px", "controllerID");
|
||||
tbSS.AddHeader("Create Date", "240px", "240px", "createDate");
|
||||
tbSS.IsCheckBox(true);
|
||||
tbSS.LoadDataUrl("/Storage/GetStorage");
|
||||
} else {
|
||||
// tb.RefreshCurrentPage();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
});
|
||||
wrd1.on("onAfterNext", (evt) => {
|
||||
if (evt.indexPage > 0) {
|
||||
if (as.get(0).isLockElement() || as.get(1).isLockElement()) {
|
||||
@ -412,8 +437,7 @@ window.L6101 = function () {
|
||||
});
|
||||
break;
|
||||
}
|
||||
} else if (evt.indexPage == 1)
|
||||
{
|
||||
} else if (evt.indexPage == 1) {
|
||||
|
||||
}
|
||||
else if (evt.indexPage == 2) {
|
||||
@ -447,7 +471,6 @@ window.L6101 = function () {
|
||||
}
|
||||
|
||||
}, true);
|
||||
|
||||
var asVD = as.get(1);
|
||||
ele2.on("btnAdd_Click", (e) => {
|
||||
asIdType.lockElement();
|
||||
@ -505,9 +528,6 @@ window.L6101 = function () {
|
||||
|
||||
});
|
||||
|
||||
Waves.attach('.btn-effect', ['waves-float']);
|
||||
Waves.init({ duration: 1000, delay: 200 });
|
||||
|
||||
let eleAddStorage = document.getElementById("btAddStorage");
|
||||
let asAddStorage = new AButton(eleAddStorage);
|
||||
asAddStorage.on("click_btAddStorage", (e) => {
|
||||
@ -538,139 +558,24 @@ window.L6101 = function () {
|
||||
xhr.send(JSON.stringify(data));
|
||||
});
|
||||
|
||||
//var btnAdd = document.getElementById("btAdd");
|
||||
let btSaveST = new AButton(document.getElementById("btSaveST"));
|
||||
btSaveST.on("click_btSaveST", (evt) => {
|
||||
const listC = tbSS.absRows.querySelectorAll("input[type=checkbox][rowCheck]:checked");
|
||||
listC.forEach((el) => {
|
||||
const rowST = tbSS.data[el.closest("tr").getAttribute("data-id")];
|
||||
ele2.addItem(rowST.idStorageServer, rowST.storageName, rowST, null);
|
||||
});
|
||||
btSaveST.RemoveLoading(evt);
|
||||
slider.removeModal();
|
||||
});
|
||||
|
||||
//var tabs = new ATab(document.querySelector(".atabs"), document.querySelector(".tabcontents"));
|
||||
//var tb = new ATable(document.querySelector(".c-table"), 10);
|
||||
//var btUpdate = new AButton(document.getElementById("btUpdate"));
|
||||
//var btn = new AButton(btnAdd);
|
||||
//var m = new AModal(null);
|
||||
//var mU = new AModal(null);
|
||||
//var btBack = document.getElementById("btBack");
|
||||
//btBack.addEventListener("click", (e) => {
|
||||
// tabs.selectedTab(0);
|
||||
//})
|
||||
//let promise = new Promise(function (resolve, reject) {
|
||||
// tb.AddHeader("ID", "120px", "", "IdTypeStorageServer");
|
||||
// tb.AddHeader("Storage Type Name", "", "240px", "TypeName");
|
||||
// tb.AddHeader("Action", "180px", "", "Action", function (id, obj) {
|
||||
// var ac = document.createElement("div");
|
||||
// ac.classList.add("d-f", "j-c-center");
|
||||
// var d = document.createElement("button");
|
||||
// d.classList.add("btn", "btn-warning", "mr-2");
|
||||
// var ico = document.createElement("span");
|
||||
// ico.classList.add("atg", "atg-pencil");
|
||||
// d.appendChild(ico);
|
||||
// d.addEventListener("click", ((e) => { updateClick.call(tabs, e, id, obj); }));
|
||||
// ac.appendChild(d);
|
||||
// d = document.createElement("button");
|
||||
// d.classList.add("btn", "btn-danger");
|
||||
// var ico = document.createElement("span");
|
||||
// ico.classList.add("atg", "atg-x");
|
||||
// d.appendChild(ico);
|
||||
// ac.appendChild(d);
|
||||
// return ac;
|
||||
// });
|
||||
// tb.SetScrollBarY(300);
|
||||
// tb.IsCheckBox(true);
|
||||
// tb.LoadDataUrl("/Storage/GetTypeStorage");
|
||||
//});
|
||||
|
||||
//m.overlay.setIndex(2101);
|
||||
//m.createModal("OK");
|
||||
//m.on("OK", () => {
|
||||
// btn.RemoveLoading(btnAdd);
|
||||
// tb.RefreshPage(1, true);
|
||||
//});
|
||||
//m.on("Close", () => { btn.RemoveLoading(btnAdd); });
|
||||
//btn.on("click_btAdd", function (e) {
|
||||
// const xhr = new XMLHttpRequest();
|
||||
// xhr.open("POST", "/Storage/AddType");
|
||||
// xhr.setRequestHeader('Content-type', 'application/json; charset=UTF-8');
|
||||
// var data = {
|
||||
// "Name": document.getElementById("inpType").value
|
||||
// };
|
||||
// var f = function (ev) {
|
||||
// if (ev.currentTarget.readyState == 4) {
|
||||
// if (ev.currentTarget.status == 200) {
|
||||
// var obj = JSON.parse(ev.currentTarget.responseText);
|
||||
// if (ev.Status == 0) {
|
||||
// m.AModalOK.title("Message Error", "mess-error");
|
||||
// m.AModalOK.message(ev.Message);
|
||||
// } else {
|
||||
// m.AModalOK.title("Message", "mess-success");
|
||||
// m.AModalOK.message("Row Insert Success!");
|
||||
// }
|
||||
// m.showModal();
|
||||
// }
|
||||
// }
|
||||
|
||||
// };
|
||||
// xhr.addEventListener("readystatechange", f, false);
|
||||
// xhr.send(JSON.stringify(data));
|
||||
//});
|
||||
|
||||
//tabs.lockTabs.push(1);
|
||||
|
||||
//mU.overlay.setIndex(2101);
|
||||
//mU.createModal("OK");
|
||||
//mU.on("OK", () => {
|
||||
// btUpdate.RemoveLoading(document.getElementById("btUpdate"));
|
||||
// tabs.selectedTab(0);
|
||||
// tb.RefreshCurrentPage();
|
||||
//});
|
||||
//mU.on("Close", () => { btn.RemoveLoading(document.getElementById("btUpdate")); });
|
||||
|
||||
//btUpdate.on("click_btUpdate", (evt) => {
|
||||
// var inp = document.getElementById("inpEType");
|
||||
// var inpID = document.getElementById("inpEID");
|
||||
// if (inpID.value != "") {
|
||||
// const xhr = new XMLHttpRequest();
|
||||
// xhr.open("POST", "/Storage/UpdateType");
|
||||
// xhr.setRequestHeader('Content-type', 'application/json; charset=UTF-8');
|
||||
// var data = {
|
||||
// "ID": inpID.value,
|
||||
// "Name": inp.value
|
||||
// };
|
||||
// var f = function (ev) {
|
||||
// if (ev.currentTarget.readyState == 4) {
|
||||
// if (ev.currentTarget.status == 200) {
|
||||
// var obj = JSON.parse(ev.currentTarget.responseText);
|
||||
// if (ev.Status == 0) {
|
||||
// mU.AModalOK.title("Message Error", "mess-error");
|
||||
// mU.AModalOK.message(ev.Message);
|
||||
// } else {
|
||||
// mU.AModalOK.title("Message", "mess-success");
|
||||
// mU.AModalOK.message("Row Update Success!");
|
||||
// }
|
||||
// mU.showModal();
|
||||
// }
|
||||
// }
|
||||
|
||||
// };
|
||||
// xhr.addEventListener("readystatechange", f, false);
|
||||
// xhr.send(JSON.stringify(data));
|
||||
// }
|
||||
//});
|
||||
|
||||
//var btSearch = new AButton(document.getElementById("btSearch"));
|
||||
//btSearch.on("click_btSearch", function (evt) {
|
||||
// var fr = new FormData();
|
||||
// fr.append("keyword", document.getElementById("inpKey").value);
|
||||
// tb.LoadDataFirst(fr);
|
||||
// btSearch.RemoveLoading(evt);
|
||||
//});
|
||||
}
|
||||
}
|
||||
});
|
||||
Waves.attach('.btn-effect', ['waves-float']);
|
||||
Waves.init({ duration: 1000, delay: 200 });
|
||||
|
||||
//function updateClick(e, id, obj) {
|
||||
// this.enableTab(1);
|
||||
// this.selectedTab(1);
|
||||
// var inp = document.getElementById("inpEType");
|
||||
// var inpID = document.getElementById("inpEID");
|
||||
// inp.value = obj.TypeName;
|
||||
// inpID.value = obj.IdTypeStorageServer;
|
||||
//}
|
||||
|
||||
}
|
||||
|
||||
|
||||
window.AScript.set("6101", true);
|
||||
@ -14,7 +14,6 @@ class AsyncLayout extends ALayout {
|
||||
super.dispose();
|
||||
}
|
||||
renderMenu() {
|
||||
console.log("ÁDASD");
|
||||
this.isLoaded = true;
|
||||
var asyncStyleSheets = [
|
||||
'https://fonts.googleapis.com/css2?family=Quicksand:wght@300;400;500;600;700&display=swap',
|
||||
@ -46,9 +45,6 @@ class AsyncLayout extends ALayout {
|
||||
window.app.initScrollBar();
|
||||
window.Scrollbar.init(document.querySelector('.mini-scrollbar'), sOption);
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -22,16 +22,9 @@ class LoginLayout extends ALayout {
|
||||
window.app.loadCSS(asyncStyleSheets);
|
||||
window.app.initNavs("Login");
|
||||
|
||||
var sOption = {
|
||||
damping: (window.getOS() == "Android") ? .06 : .04,
|
||||
thumbMinSize: 25,
|
||||
renderByPixel: true,
|
||||
alwaysShowTracks: true,
|
||||
continuousScrolling: true
|
||||
};
|
||||
|
||||
window.Scrollbar.use(window.OverscrollPlugin);
|
||||
window.app.initScrollBar();
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -44,12 +44,16 @@
|
||||
}).bind(this);
|
||||
break;
|
||||
case "Slide":
|
||||
var slideC = document.createElement("div");
|
||||
var slideC = this.params.parent.querySelector(".slideContent");
|
||||
if (slideC == null) {
|
||||
slideC = document.createElement("div");
|
||||
slideC.classList.add("slideContent");
|
||||
while (this.params.parent.childNodes.length > 0) {
|
||||
slideC.appendChild(this.params.parent.childNodes[0]);
|
||||
}
|
||||
this.params.parent.appendChild(slideC);
|
||||
}
|
||||
|
||||
|
||||
slideC.querySelectorAll(".tabcontent").forEach((el) => {
|
||||
let style = this.params.parent.currentStyle || window.getComputedStyle(this.params.parent);
|
||||
|
||||
@ -51,7 +51,6 @@ export default class Dropdown extends window.AObject {
|
||||
if (this.isLock) {
|
||||
return;
|
||||
}
|
||||
console.log("Asdasd");
|
||||
var t1 = e.currentTarget;
|
||||
var p = t1.closest('[data-dropdown]');
|
||||
var p1 = e.target.closest(".noopen");
|
||||
|
||||
@ -52,7 +52,9 @@ export default class AModal extends window.AObject {
|
||||
showModal() {
|
||||
this.overlay.showOverlay();
|
||||
}
|
||||
|
||||
removeModal() {
|
||||
this.overlay.removeOverlay();
|
||||
}
|
||||
}
|
||||
|
||||
class AModalOK {
|
||||
|
||||
@ -3,8 +3,8 @@ export default class AMultiTag extends window.AObject {
|
||||
super();
|
||||
this.parent = ele;
|
||||
this.cItems = ele.querySelector(".input-content");
|
||||
this.itemEles = [];
|
||||
this.itemDatas = [];
|
||||
this.itemEles = new Map();
|
||||
this.itemDatas = new Map();
|
||||
this.btnAdd = ele.querySelector(".btn-Add");
|
||||
this.btnAdd.addEventListener("click", ((e) => {
|
||||
this.parent.classList.add("active");
|
||||
@ -16,6 +16,11 @@ export default class AMultiTag extends window.AObject {
|
||||
}
|
||||
initGlobalVar() {
|
||||
var f = function (ev) {
|
||||
const close = ev.target.closest(".con-ico");
|
||||
if (close) {
|
||||
const t = close.closest(".item[data-id]");
|
||||
if (t) this.removeItem(1 * t.getAttribute("data-id"));
|
||||
}
|
||||
if (ev.target.closest(".amultitag") || ev.target.closest(".c-aoverlay")) {
|
||||
return;
|
||||
} else {
|
||||
@ -26,22 +31,32 @@ export default class AMultiTag extends window.AObject {
|
||||
window.AMultiTag = true;
|
||||
}
|
||||
addItem(id, name, obj, action = null) {
|
||||
var ele = this.addItem(id, name, action);
|
||||
this.itemEles.push(ele);
|
||||
this.itemDatas.push(obj);
|
||||
var ele = this.createItem(id, name, action);
|
||||
this.itemEles.set(id, ele);
|
||||
this.itemDatas.set(id, obj);
|
||||
this.cItems.appendChild(ele);
|
||||
}
|
||||
removeItem(id) {
|
||||
const t = this.itemEles.get(id);
|
||||
this.itemDatas.delete(id);
|
||||
this.itemEles.delete(id);
|
||||
t.remove();
|
||||
}
|
||||
createItem(id, name, action) {
|
||||
var p = document.createElement("div");
|
||||
p.setAttribute("data-id", id);
|
||||
p.classList.add("item");
|
||||
p.classList.add("item", "d-f", "a-i-center");
|
||||
var label = document.createElement("span");
|
||||
label.innerHTML = name;
|
||||
label.classList.add("name");
|
||||
if (action != null) {
|
||||
p.appendChild(action);
|
||||
}
|
||||
let close = document.createElement("div");
|
||||
close.classList.add("con-ico", "d-f", "a-i-center", "j-c-center");
|
||||
p.appendChild(label);
|
||||
close.innerHTML = `<span class="atg a-1x atg-x"></span>`;
|
||||
p.appendChild(close);
|
||||
return p;
|
||||
}
|
||||
}
|
||||
@ -182,6 +182,7 @@ class ASelectEle extends window.AObject {
|
||||
if (this.selectedEleItem != null) this.selectedEleItem.classList.remove("active");
|
||||
this.selectedEleItem = this.listItems[idx].element;
|
||||
this.selectedItem = this.listItems[idx];
|
||||
|
||||
this.removeAllChildNodes(this.cSelectedItem);
|
||||
this.cloneNodes(this.selectedEleItem, this.cSelectedItem);
|
||||
this.setElement(this.selectedEleItem);
|
||||
@ -398,7 +399,6 @@ class ASelectEle extends window.AObject {
|
||||
}
|
||||
if (tmp != null && tmp.classList.contains("a-option")) {
|
||||
this.updateIndex(tmp.getAttribute("index"));
|
||||
console.log(tmp.offsetTop);
|
||||
this.scroll.scrollIntoView(tmp, {
|
||||
alignToTop: false,
|
||||
offsetBottom: 0,
|
||||
|
||||
69
TWASys-App/wwwroot/js/libs/js-ASlideDown.js
Normal file
69
TWASys-App/wwwroot/js/libs/js-ASlideDown.js
Normal file
@ -0,0 +1,69 @@
|
||||
import ATransitionEffect from '/js/libs/js-ATransitionEffect.js'
|
||||
|
||||
export default class ASlideDown extends window.AObject {
|
||||
constructor(el) {
|
||||
super();
|
||||
this._eleM = [];
|
||||
if (el instanceof NodeList) {
|
||||
Array.from(el).forEach((e) => {
|
||||
this._eleM.push(new ASlideDownEle(e))
|
||||
});
|
||||
} else {
|
||||
this._eleM.push(new ASlideDownEle(el));
|
||||
}
|
||||
}
|
||||
get(i) {
|
||||
return this._eleM[i];
|
||||
}
|
||||
}
|
||||
|
||||
class ASlideDownEle extends window.AObject {
|
||||
constructor(ele) {
|
||||
super();
|
||||
this.transition = new ATransitionEffect();
|
||||
this._ele = ele;
|
||||
this._pCon = ele.closest('[data-dropdown]');
|
||||
this._subI = this._pCon.querySelector(".sub-item");
|
||||
var f = function (ev) {
|
||||
if (window.isValidPointerClick(ev)) return;
|
||||
this.onClick.call(this, ev);
|
||||
}.bind(this);
|
||||
this.addSystemEvent(this.eventName, this._ele, f);
|
||||
}
|
||||
enable() {
|
||||
this._ele.classList.remove("disabled");
|
||||
}
|
||||
disable() {
|
||||
this._ele.classList.add("disabled");
|
||||
}
|
||||
enable_Open() {
|
||||
this.enable();
|
||||
this.open();
|
||||
}
|
||||
disable_Close() {
|
||||
this.disable();
|
||||
this.close();
|
||||
}
|
||||
open() {
|
||||
if (this._ele.classList.contains("disabled")) {
|
||||
return;
|
||||
}
|
||||
this._pCon.classList.add("active");
|
||||
this.transition.expandEffect(this._subI, function () {
|
||||
this.trigger("opened");
|
||||
}.bind(this));
|
||||
}
|
||||
close() {
|
||||
this._pCon.classList.remove("active");
|
||||
this.transition.collapsedEffect(this._subI, function () {
|
||||
this.trigger("closed");
|
||||
}.bind(this));
|
||||
}
|
||||
onClick(e) {
|
||||
if (this._pCon.classList.contains("active")) {
|
||||
this.close();
|
||||
} else {
|
||||
this.open();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -34,6 +34,13 @@ export default class AWizard extends ATab {
|
||||
</button>
|
||||
</div>`;
|
||||
|
||||
const ro = new ResizeObserver((entries => {
|
||||
for (const e of entries) {
|
||||
const { width, height } = e.contentRect;
|
||||
this.aAnimation.setType(this.typeAnimation, { "parent": this.tabContents });
|
||||
}
|
||||
}).bind(this));
|
||||
ro.observe(this.tabContents);
|
||||
}
|
||||
showPage(i) {
|
||||
this.cPage = i;
|
||||
|
||||
@ -6,6 +6,7 @@
|
||||
this.pElement = e;
|
||||
this.Headers = [];
|
||||
this.lSysRows = [];
|
||||
this.labelID = "";
|
||||
this.InitStructure();
|
||||
this.InitCss();
|
||||
this.SetIdCheckBox();
|
||||
@ -18,7 +19,8 @@
|
||||
}
|
||||
}
|
||||
SetScrollBarY(height) {
|
||||
this.absContainerRows.style.height = height + "px";
|
||||
this.absContainerRows.style.height = "auto";
|
||||
this.absContainerRows.style.maxHeight = height + "px";
|
||||
}
|
||||
AddHeader(name, width, minWidth, id = "", rowTemp = null) {
|
||||
var d = document.createElement("th");
|
||||
@ -184,10 +186,15 @@
|
||||
this.data.forEach((e, i) => {
|
||||
var r = document.createElement("tr");
|
||||
r.setAttribute("data-id", i);
|
||||
this.Headers.forEach((o) => {
|
||||
this.Headers.forEach((o, j) => {
|
||||
|
||||
var td = document.createElement("td");
|
||||
if (o.rowTemp != null) {
|
||||
td.appendChild(o.rowTemp(i, e));
|
||||
const rT = o.rowTemp(i, e);
|
||||
if (this.isCheckBox && j < 1) {
|
||||
rT.setAttribute("id", (this.labelID.length >0)?e[this.labelID]:"");
|
||||
}
|
||||
td.appendChild(rT);
|
||||
} else {
|
||||
td.innerHTML = e[o.id];
|
||||
}
|
||||
|
||||
@ -429,6 +429,7 @@ window.AObject = class {
|
||||
}
|
||||
this.parentEventMap.get(parent).add({ element, eventName });
|
||||
}
|
||||
|
||||
}
|
||||
removeAllChildNodes(parent) {
|
||||
while (parent.firstChild) {
|
||||
@ -541,7 +542,6 @@ class AApp extends window.AObject {
|
||||
this.metaPage = document.head.querySelector("meta[name=idPage]");
|
||||
this.pageName = this.metaPage.getAttribute("pageName");
|
||||
this.lName = this.metaPage.getAttribute("layName");
|
||||
console.log(this.lName);
|
||||
var tmp = document.querySelector(container);
|
||||
this.mainApp = tmp.querySelector("[main-content]") ? tmp.querySelector("[main-content]") : tmp;
|
||||
var f = function (ev) {
|
||||
@ -689,7 +689,6 @@ class AApp extends window.AObject {
|
||||
doc: doc,
|
||||
dynamicF: a.dynamicF
|
||||
};
|
||||
|
||||
this.setContentPage(obj, url);
|
||||
} else {
|
||||
this.getPage(url, result)
|
||||
@ -699,17 +698,6 @@ class AApp extends window.AObject {
|
||||
this.getPage(url);
|
||||
}
|
||||
}).bind(this));
|
||||
//if (flex) {
|
||||
|
||||
//} else {
|
||||
// this.cachePage.get(url, ((result) => {
|
||||
// if (result) {
|
||||
// // Set content page từ cache
|
||||
// } else {
|
||||
// this.getPage(url); // Load mới nếu chưa có trong cache
|
||||
// }
|
||||
// }).bind(this));
|
||||
//}
|
||||
}
|
||||
loadContentPage(content) {
|
||||
const tpl = document.createElement('template');
|
||||
@ -723,9 +711,7 @@ class AApp extends window.AObject {
|
||||
document.title = page.title + " - " + this.pageName;
|
||||
var meta = document.head.querySelector("meta[name=idPage]");
|
||||
document.body.setAttribute("page", page.idPage);
|
||||
|
||||
meta.content = page.idPage;
|
||||
this.lName = page.lName;
|
||||
meta.setAttribute("layName", page.lName);
|
||||
this.loadContentPage(page.html);
|
||||
window.history.pushState({ "url": url }, page.title, url);
|
||||
@ -778,7 +764,6 @@ class AApp extends window.AObject {
|
||||
loadedPage() {
|
||||
this.metaPage = document.head.querySelector("meta[name=idPage]");
|
||||
if (this.metaPage != null && this.isLoadedLayout) {
|
||||
console.log(window.location.href);
|
||||
this.cachePage.searchFlexPage(window.getPathFromUrl(window.location.href), ((tmp) => {
|
||||
tmp = tmp.layout.info;
|
||||
if (tmp != null && tmp.dynamicF != null) {
|
||||
@ -825,7 +810,6 @@ class AApp extends window.AObject {
|
||||
}).bind(this)();
|
||||
}
|
||||
loadedLayout() {
|
||||
console.log(this.lName);
|
||||
if (this.lName !== "None") {
|
||||
const l = window.ALayout.get(this.lName);
|
||||
if (!l.isLoaded) {
|
||||
|
||||
Reference in New Issue
Block a user