Refactor project structure and remove deprecated features

- Updated README.md to include "Project Structure" section.
- Removed WeatherForecastController.cs and WeatherForecast.cs.
- Simplified Surge365.MassEmailReact.Server.csproj.
- Updated solution file to reflect new project references.
- Refactored jquery.ss.dbmanager-1.0.js and jquery.usahaulers.global.js.
- Modified logging functionalities in jquery.usahaulers.logging-1.0.js.
- Set up constants from environment variables in constants.js and constants.ts.
- Introduced new classes in Surge365.MassEmailReact.Application, Domain, and Infrastructure.
- Added UnitTest1.cs for basic unit testing structure.
- Enhanced Surge365.MassEmailReact.Web.esproj with new configurations.
- Expanded utility functions in ytb-massemail-.global.ts and ytb-massemail-utilities-1.0.ts.
This commit is contained in:
David Headrick 2025-02-20 08:09:21 -06:00
parent 2fa7b500b9
commit f8df86f1b4
22 changed files with 151 additions and 1658 deletions

View File

@ -4,27 +4,30 @@ Mass Email React Website
to clone: in command prompt, go to the directory you want to clone the project to, then type: to clone: in command prompt, go to the directory you want to clone the project to, then type:
```
git clone --branch main https://<your_username_here>@git.surge365.com/Surge365/MassEmailReact.git git clone --branch main https://<your_username_here>@git.surge365.com/Surge365/MassEmailReact.git
```
## TO DO IF YOU WANT TO BUILD THIS PROJECT ## TO DO IF YOU WANT TO BUILD THIS PROJECT
1. Install node.js v22.13.1 1. Install node.js v22.13.1
2. Recommended to install nvm for Windows, then in command prompt, type: 2. Recommended to install nvm for Windows, then in command prompt, type:
```
nvm install 22.13.1 nvm install 22.13.1
```
3. Then type: 3. Then type:
```
nvm use 22.13.1 nvm use 22.13.1
```
4. Then to verify, type: 4. Then to verify, type:
```
node -v # Should return v22.13.1 node -v # Should return v22.13.1
```
5. Then to verify npm, type: 5. Then to verify npm, type:
```
npm -v # Should return a version npm -v # Should return a version
```
## Project Structure
This project consists of multiple layers to ensure separation of concerns and maintainability.
### Project Descriptions and Dependency Order
1. **Surge365.MassEmailReact.Domain** - Contains core business logic and domain entities.
2. **Surge365.MassEmailReact.Application** - Handles application logic and use cases. Depends on `Domain`.
3. **Surge365.MassEmailReact.Infrastructure** - Provides data access, external integrations, and persistence. Depends on `Application` and `Domain`.
4. **Surge365.MassEmailReact.API** - The API layer that serves endpoints. Depends on `Application`.
5. **Surge365.MassEmailReact.Web** - The front-end application. Communicates with `API`.
6. **Surge365.MassEmailReact.UnitTests** - Contains unit tests for various layers of the application.

View File

@ -0,0 +1,7 @@
namespace Surge365.MassEmailReact.Application
{
public class Class1
{
}
}

View File

@ -0,0 +1,14 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net9.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\Surge365.MassEmailReact.Domain\Surge365.MassEmailReact.Domain.csproj" />
<ProjectReference Include="..\Surge365.MassEmailReact.Infrastructure\Surge365.MassEmailReact.Infrastructure.csproj" />
</ItemGroup>
</Project>

View File

@ -0,0 +1,7 @@
namespace Surge365.MassEmailReact.Domain
{
public class Class1
{
}
}

View File

@ -0,0 +1,9 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net9.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
</Project>

View File

@ -0,0 +1,7 @@
namespace Surge365.MassEmailReact.Infrastructure
{
public class Class1
{
}
}

View File

@ -0,0 +1,9 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net9.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
</Project>

View File

@ -1,32 +0,0 @@
using Microsoft.AspNetCore.Mvc;
namespace Surge365.MassEmailReact.Server.Controllers;
[ApiController]
[Route("[controller]")]
public class WeatherForecastController : ControllerBase
{
private static readonly string[] Summaries = new[]
{
"Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching"
};
private readonly ILogger<WeatherForecastController> _logger;
public WeatherForecastController(ILogger<WeatherForecastController> logger)
{
_logger = logger;
}
[HttpGet(Name = "GetWeatherForecast")]
public IEnumerable<WeatherForecast> Get()
{
return Enumerable.Range(1, 5).Select(index => new WeatherForecast
{
Date = DateOnly.FromDateTime(DateTime.Now.AddDays(index)),
TemperatureC = Random.Shared.Next(-20, 55),
Summary = Summaries[Random.Shared.Next(Summaries.Length)]
})
.ToArray();
}
}

View File

@ -1,4 +1,4 @@
<Project Sdk="Microsoft.NET.Sdk.Web"> <Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup> <PropertyGroup>
<TargetFramework>net9.0</TargetFramework> <TargetFramework>net9.0</TargetFramework>
@ -17,9 +17,7 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\surge365.massemailreact.client\surge365.massemailreact.client.esproj"> <ProjectReference Include="..\Surge365.MassEmailReact.Application\Surge365.MassEmailReact.Application.csproj" />
<ReferenceOutputAssembly>false</ReferenceOutputAssembly>
</ProjectReference>
</ItemGroup> </ItemGroup>
</Project> </Project>

View File

@ -1,13 +0,0 @@
namespace Surge365.MassEmailReact.Server
{
public class WeatherForecast
{
public DateOnly Date { get; set; }
public int TemperatureC { get; set; }
public int TemperatureF => 32 + (int)(TemperatureC / 0.5556);
public string? Summary { get; set; }
}
}

View File

@ -0,0 +1,29 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net9.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<IsPackable>false</IsPackable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="coverlet.collector" Version="6.0.2" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.12.0" />
<PackageReference Include="xunit" Version="2.9.2" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.8.2" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Surge365.MassEmailReact.Application\Surge365.MassEmailReact.Application.csproj" />
<ProjectReference Include="..\surge365.massemailreact.client\Surge365.MassEmailReact.Web.esproj" />
<ProjectReference Include="..\Surge365.MassEmailReact.Domain\Surge365.MassEmailReact.Domain.csproj" />
<ProjectReference Include="..\Surge365.MassEmailReact.Infrastructure\Surge365.MassEmailReact.Infrastructure.csproj" />
<ProjectReference Include="..\Surge365.MassEmailReact.Server\Surge365.MassEmailReact.API.csproj" />
</ItemGroup>
<ItemGroup>
<Using Include="Xunit" />
</ItemGroup>
</Project>

View File

@ -0,0 +1,11 @@
namespace Surge365.MassEmailReact.UnitTests
{
public class UnitTest1
{
[Fact]
public void Test1()
{
}
}
}

View File

@ -1,11 +1,24 @@
 
Microsoft Visual Studio Solution File, Format Version 12.00 Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17 # Visual Studio Version 17
VisualStudioVersion = 17.13.35806.99 d17.13 VisualStudioVersion = 17.13.35806.99
MinimumVisualStudioVersion = 10.0.40219.1 MinimumVisualStudioVersion = 10.0.40219.1
Project("{54A90642-561A-4BB1-A94E-469ADEE60C69}") = "surge365.massemailreact.client", "surge365.massemailreact.client\surge365.massemailreact.client.esproj", "{E719388D-D7C7-6E5A-3D56-06DBCCECFF8F}" Project("{54A90642-561A-4BB1-A94E-469ADEE60C69}") = "Surge365.MassEmailReact.Web", "surge365.massemailreact.client\Surge365.MassEmailReact.Web.esproj", "{E719388D-D7C7-6E5A-3D56-06DBCCECFF8F}"
EndProject EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Surge365.MassEmailReact.Server", "Surge365.MassEmailReact.Server\Surge365.MassEmailReact.Server.csproj", "{585F39DB-9461-48EB-9A0A-294478A9F052}" Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Surge365.MassEmailReact.API", "Surge365.MassEmailReact.Server\Surge365.MassEmailReact.API.csproj", "{585F39DB-9461-48EB-9A0A-294478A9F052}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Surge365.MassEmailReact.Domain", "Surge365.MassEmailReact.Domain\Surge365.MassEmailReact.Domain.csproj", "{6032050E-5666-4246-BA3E-4FABCD813724}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Surge365.MassEmailReact.Infrastructure", "Surge365.MassEmailReact.Infrastructure\Surge365.MassEmailReact.Infrastructure.csproj", "{F32A115E-06A6-4428-81CE-47C5943BC97D}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Surge365.MassEmailReact.Application", "Surge365.MassEmailReact.Application\Surge365.MassEmailReact.Application.csproj", "{F60998C4-3301-414E-B2FE-5E08B2F4BC9D}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Surge365.MassEmailReact.UnitTests", "Surge365.MassEmailReact.UnitTests\Surge365.MassEmailReact.UnitTests.csproj", "{A90972B7-7D32-4C1A-AB68-1043819F2A56}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{8EC462FD-D22E-90A8-E5CE-7E832BA40C5D}"
ProjectSection(SolutionItems) = preProject
README.md = README.md
EndProjectSection
EndProject EndProject
Global Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution GlobalSection(SolutionConfigurationPlatforms) = preSolution
@ -23,6 +36,22 @@ Global
{585F39DB-9461-48EB-9A0A-294478A9F052}.Debug|Any CPU.Build.0 = Debug|Any CPU {585F39DB-9461-48EB-9A0A-294478A9F052}.Debug|Any CPU.Build.0 = Debug|Any CPU
{585F39DB-9461-48EB-9A0A-294478A9F052}.Release|Any CPU.ActiveCfg = Release|Any CPU {585F39DB-9461-48EB-9A0A-294478A9F052}.Release|Any CPU.ActiveCfg = Release|Any CPU
{585F39DB-9461-48EB-9A0A-294478A9F052}.Release|Any CPU.Build.0 = Release|Any CPU {585F39DB-9461-48EB-9A0A-294478A9F052}.Release|Any CPU.Build.0 = Release|Any CPU
{6032050E-5666-4246-BA3E-4FABCD813724}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{6032050E-5666-4246-BA3E-4FABCD813724}.Debug|Any CPU.Build.0 = Debug|Any CPU
{6032050E-5666-4246-BA3E-4FABCD813724}.Release|Any CPU.ActiveCfg = Release|Any CPU
{6032050E-5666-4246-BA3E-4FABCD813724}.Release|Any CPU.Build.0 = Release|Any CPU
{F32A115E-06A6-4428-81CE-47C5943BC97D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{F32A115E-06A6-4428-81CE-47C5943BC97D}.Debug|Any CPU.Build.0 = Debug|Any CPU
{F32A115E-06A6-4428-81CE-47C5943BC97D}.Release|Any CPU.ActiveCfg = Release|Any CPU
{F32A115E-06A6-4428-81CE-47C5943BC97D}.Release|Any CPU.Build.0 = Release|Any CPU
{F60998C4-3301-414E-B2FE-5E08B2F4BC9D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{F60998C4-3301-414E-B2FE-5E08B2F4BC9D}.Debug|Any CPU.Build.0 = Debug|Any CPU
{F60998C4-3301-414E-B2FE-5E08B2F4BC9D}.Release|Any CPU.ActiveCfg = Release|Any CPU
{F60998C4-3301-414E-B2FE-5E08B2F4BC9D}.Release|Any CPU.Build.0 = Release|Any CPU
{A90972B7-7D32-4C1A-AB68-1043819F2A56}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{A90972B7-7D32-4C1A-AB68-1043819F2A56}.Debug|Any CPU.Build.0 = Debug|Any CPU
{A90972B7-7D32-4C1A-AB68-1043819F2A56}.Release|Any CPU.ActiveCfg = Release|Any CPU
{A90972B7-7D32-4C1A-AB68-1043819F2A56}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection EndGlobalSection
GlobalSection(SolutionProperties) = preSolution GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE HideSolutionNode = FALSE

View File

@ -8,11 +8,12 @@
<!-- Folder where production build objects will be placed --> <!-- Folder where production build objects will be placed -->
<BuildOutputFolder>$(MSBuildProjectDirectory)\dist</BuildOutputFolder> <BuildOutputFolder>$(MSBuildProjectDirectory)\dist</BuildOutputFolder>
</PropertyGroup> </PropertyGroup>
<ItemGroup>
<None Remove="public\content\lib\**" />
<TypeScriptConfiguration Remove="public\content\lib\**" />
</ItemGroup>
<ItemGroup> <ItemGroup>
<None Remove="src\components\layouts\LayoutLogin_Backup.tsx" /> <None Remove="src\components\layouts\LayoutLogin_Backup.tsx" />
<None Remove="src\components\layouts\Layout_backup.tsx" /> <None Remove="src\components\layouts\Layout_backup.tsx" />
</ItemGroup> </ItemGroup>
<ItemGroup>
<Folder Include="public\content\lib\" />
</ItemGroup>
</Project> </Project>

View File

@ -1,108 +0,0 @@
const INTERNAL_SECOND_MS = 60 * 1000;
const INTERNAL_MINUTE_MS = 60 * INTERNAL_SECOND_MS;
const INTERNAL_HOUR_MS = 60 * INTERNAL_MINUTE_MS;
var isIndexedDBSupported = 'indexedDB' in window;
$.dbManager = {
openDatabases: {}
}
$.dbManager.alert = function (msg) {
alert(msg);
}
$.dbManager.openDatabase = function (name, version, onUpgradeNeeded) {
let dbManager = this;
return new Promise(function (resolve, reject) {
let db = dbManager.openDatabases[name];
if (db !== undefined && db !== null) {
resolve(db);
return;
}
let request = indexedDB.open(name, version);
request.onupgradeneeded = function (event) {
//Upgrade DB? Drop DB and reload? For now, drop db
console.log("onupgradeneeded");
if (onUpgradeNeeded != null) {
onUpgradeNeeded(event);
}
else {
dbManager.deleteDatabase(name).then(
function onSuccess(db) {
resolve(db);
},
function onError(error) {
reject(error);
});
}
//reject("Upgrade Needed");
};
request.onerror = function () {
console.error("Error: ", request.error);
reject(request.error);
};
request.onblocked = function () {
console.error();
reject("Database blocked");
};
request.onsuccess = function () {
let db = request.result;
db.onversionchange = function (event) {
let isDeleted = event.newVersion === null;
db.close();
if(!isDeleted)
alert("Database is outdated, please reload the page: ", event.currentTarget.name)
};
console.log("Database opened: ", name);
if (dbManager.openDatabases == null)
dbManager.openDatabases = {};
dbManager.openDatabases[name] = db;
db.onclose = function () { //TODO: DOesn't appear to be called currently
console.log('Database connection closed: ', name);
dbManager.openDatabases[name] = null;
}
resolve(db);
};
});
}
$.dbManager.closeDatabase = function (name) {
let currentDB = this;
return new Promise(function (resolve, reject) {
let db = currentDB.openDatabases[name];
if (db != null) {
db.close();
}
currentDB.openDatabases[name] == null;
resolve();
});
}
$.dbManager.deleteDatabase = function (name) {
let currentDB = this;
return new Promise(function (resolve, reject) {
let request = indexedDB.deleteDatabase(name);
request.onerror = function () {
console.error("Error", request.error);
reject(request.error);
};
request.onsuccess = function () {
console.log("database deleted: ", name);
currentDB.openDatabases[name] = null;
resolve();
};
});
}

View File

@ -1,931 +0,0 @@
const DEFAULT_LOG_LEVELS_TO_LOG = ["debug","warn","info","error"];
const DEFAULT_LOG_AJAX_REQUESTS = true;
const DEFAULT_LOG_AJAX_REQUESTS_TO_CONSOLE = true;
const DEFAULT_LOG_AJAX_REQUESTS_TO_CONSOLE_ERROR_ONLY = true;
const DEFAULT_LOG_AJAX_REQUESTS_TO_CONSOLE_MAX_RESPONSE_CHARS = 200
///CURRENTLY THESE INDEXEDDB CONSTS ARE NOT USED, LEAVING HERE IN CASE I FIGURE OUT HOW TO WIRE THEM UP.
const DEFAULT_LOG_AJAX_REQUESTS_TO_INDEXEDDB = true;
const DEFAULT_LOG_AJAX_REQUESTS_TO_INDEXEDDB_ERROR_ONLY = true;
const DEFAULT_LOG_AJAX_REQUESTS_TO_INDEXEDDB_MAX_RESPONSE_CHARS = -1 //< 0 = log all, 0 = log none, > 0 log that # of chars
const DEFAULT_LOG_URL = 'https://usahaulerslog.solutionsmith.net/WebServices/LoggingMethods.aspx/SaveLogs';
const INTERNAL_LOG_URLS = {
DEFAULT: "https://usahaulerslogdev.solutionsmith.net/WebServices/LoggingMethods.aspx/SaveLogs",
DEV: "https://usahaulerslogdev.solutionsmith.net/WebServices/LoggingMethods.aspx/SaveLogs",
PROD: "https://usahaulerslog.solutionsmith.net/WebServices/LoggingMethods.aspx/SaveLogs"
}
const DEFAULT_LOG_CONFIG_OBJECT = {
id: 0,
defaultLogLevelsToLog: DEFAULT_LOG_LEVELS_TO_LOG,
logAjaxRequests: DEFAULT_LOG_AJAX_REQUESTS,
logAjaxRequestsToConsole: DEFAULT_LOG_AJAX_REQUESTS_TO_CONSOLE,
logAjaxRequestsToConsoleErrorOnly: DEFAULT_LOG_AJAX_REQUESTS_TO_CONSOLE_ERROR_ONLY,
logAjaxRequestsToConsoleMaxResponseChars: DEFAULT_LOG_AJAX_REQUESTS_TO_CONSOLE_MAX_RESPONSE_CHARS,
logAjaxRequestsToIndexedDB: DEFAULT_LOG_AJAX_REQUESTS_TO_INDEXEDDB,
logAjaxRequestsToIndexedDBErrorOnly: DEFAULT_LOG_AJAX_REQUESTS_TO_INDEXEDDB_ERROR_ONLY,
logAjaxRequestsToIndexedDBMaxResponseChars: DEFAULT_LOG_AJAX_REQUESTS_TO_INDEXEDDB_MAX_RESPONSE_CHARS
}
const OLD_CONSOLE_LOG = console.log;
const OLD_CONSOLE_DEBUG = console.debug;
const OLD_CONSOLE_WARN = console.warn;
const OLD_CONSOLE_INFO = console.info;
const OLD_CONSOLE_ERROR = console.error;
const USAHAULERSLOGGING_DATABASE_NAME = "usahaulerslogging";
const USAHAULERSLOGGING_DATABASE_VERSION = 1;
const INTERNAL_USAHAULERSLOGGING_USEHAULERSLOGGINGDBCONFIG_OBJECT_STORE = "usahaulersloggingdb.config";
const INTERNAL_USAHAULERSLOGGING_LOG_REFRESH_PERIOD = INTERNAL_MINUTE_MS * 5;
const INTERNAL_USAHAULERSLOGGING_LOG_OBJECT_STORE = "logs";
const INTERNAL_USAHAULERSLOGGING_LOG_INDEX_DATE = "date";
const INTERNAL_USAHAULERSLOGGING_LOG_INDEX_LEVEL = "level";
const INTERNAL_USAHAULERSLOGGING_LOG_INDEX_UPLOADED = "uploaded";
const INTERNAL_USAHAULERSLOGGING_MAXUPLOADQTY = 100
$.usaHaulersLoggingDB = {
config: DEFAULT_LOG_CONFIG_OBJECT,
shouldLogLevel: (level) => {
var config = $.usaHaulersLoggingDB.config;
if (config == null)
config = DEFAULT_LOG_CONFIG_OBJECT;
return config.defaultLogLevelsToLog.includes(level.trim().toLowerCase());
},
shouldLogAjaxRequests: function () {
var config = $.usaHaulersLoggingDB.config;
if (config == null)
config = DEFAULT_LOG_CONFIG_OBJECT;
return config.logAjaxRequests && (config.logAjaxRequestsToConsole || config.logAjaxRequestsToIndexedDB);
},
shouldLogAjaxRequestsToConsole: function () {
var config = $.usaHaulersLoggingDB.config;
if (config == null)
config = DEFAULT_LOG_CONFIG_OBJECT;
return config.logAjaxRequests && config.logAjaxRequestsToConsole;
},
shouldLogAjaxRequestsToConsoleErrorOnly: function () {
var config = $.usaHaulersLoggingDB.config;
if (config == null)
config = DEFAULT_LOG_CONFIG_OBJECT;
return config.logAjaxRequests && config.logAjaxRequestsToConsole && config.logAjaxRequestsToConsoleErrorOnly;
},
logAjaxRequestsToConsoleMaxResponseChars: function () {
var config = $.usaHaulersLoggingDB.config;
if (config == null)
config = DEFAULT_LOG_CONFIG_OBJECT;
return (config.logAjaxRequests && config.logAjaxRequestsToConsole ? config.logAjaxRequestsToConsoleMaxResponseChars : 0);
},
shouldLogAjaxRequestsToIndexedDB: function () {
var config = $.usaHaulersLoggingDB.config;
if (config == null)
config = DEFAULT_LOG_CONFIG_OBJECT;
return config.logAjaxRequests && config.logAjaxRequestsToIndexedDB && $.usaHaulersLoggingDB.dbInitialized;
},
shouldLogAjaxRequestsToIndexedDBErrorOnly: function () {
var config = $.usaHaulersLoggingDB.config;
if (config == null)
config = DEFAULT_LOG_CONFIG_OBJECT;
return config.logAjaxRequests && config.logAjaxRequestsToIndexedDB && config.logAjaxRequestsToIndexedDBErrorOnly;
},
logAjaxRequestsToIndexedDBMaxResponseChars: function () {
var config = $.usaHaulersLoggingDB.config;
if (config == null)
config = DEFAULT_LOG_CONFIG_OBJECT;
return (config.logAjaxRequests && config.logAjaxRequestsToIndexedDB ? config.logAjaxRequestsToIndexedDBMaxResponseChars : 0);
},
prepareLog: function (argumentArray) {
var LOG_PREFIX = new Date().toISOString();
var args = Array.from(argumentArray);
args.unshift(LOG_PREFIX + ": ");
return args;
},
getLogMsgFromArguments: function (argumentArray) {
if (argumentArray === undefined || argumentArray === null)
return "Unknown log request: null/undefined passed to getLogMsgFromArguments";
var args = Array.from(argumentArray);
var msg = "";
args.forEach((arg) => {
var msg1 = "";
if (arg !== undefined && arg !== null) {
if (typeof arg === 'object')
msg1 = JSON.stringify(arg);
else
msg1 = arg.toString();
if (msg.length > 0)
msg += ", ";
msg += msg1;
}
});
return msg;
},
getBoolean: function (variable) {
if ($.getBoolean)
return $.getBoolean(variable);
var vtype;
var toReturn;
if (variable != null) {
switch (typeof (variable)) {
case 'boolean':
vtype = "boolean";
return variable;
break;
case 'number':
vtype = "number";
if (variable == 0)
toReturn = false;
else toReturn = true;
break;
case 'string':
vtype = "string";
if (variable.toLowerCase() == "true" || variable.toLowerCase() == "yes")
toReturn = true;
else if (variable.toLowerCase() == "false" || variable.toLowerCase() == "no")
toReturn = false;
else if (variable.length > 0)
toReturn = true;
else if (variable.length == 0)
toReturn = false;
break;
}
return toReturn;
}
},
removeObjectMethodsForSerialization: function (obj) {
try {
return JSON.parse(JSON.stringify(obj));
}
catch (error) {
return obj;
}
}
}
console.log = console.debug = function () {
var args = $.usaHaulersLoggingDB.prepareLog(arguments);
OLD_CONSOLE_DEBUG.apply(console, args);
if ($.usaHaulersLoggingDB && $.usaHaulersLoggingDB.addLog && $.usaHaulersLoggingDB.dbInitialized && $.usaHaulersLoggingDB.shouldLogLevel("debug")) {
var msg = $.usaHaulersLoggingDB.getLogMsgFromArguments(arguments);
var dbArgs = Array.from(arguments);
$.usaHaulersLoggingDB.addLog("DEBUG", msg, dbArgs);
}
}
console.warn = function () {
var args = $.usaHaulersLoggingDB.prepareLog(arguments);
OLD_CONSOLE_WARN.apply(console, args);
if ($.usaHaulersLoggingDB && $.usaHaulersLoggingDB.addLog && $.usaHaulersLoggingDB.dbInitialized && $.usaHaulersLoggingDB.shouldLogLevel("warn")) {
var msg = $.usaHaulersLoggingDB.getLogMsgFromArguments(arguments);
var dbArgs = Array.from(arguments);
$.usaHaulersLoggingDB.addLog("WARN", msg, dbArgs);
}
}
console.info = function () {
var args = $.usaHaulersLoggingDB.prepareLog(arguments);
OLD_CONSOLE_INFO.apply(console, args);
if ($.usaHaulersLoggingDB && $.usaHaulersLoggingDB.addLog && $.usaHaulersLoggingDB.dbInitialized && $.usaHaulersLoggingDB.shouldLogLevel("info")) {
var msg = $.usaHaulersLoggingDB.getLogMsgFromArguments(arguments);
var dbArgs = Array.from(arguments);
$.usaHaulersLoggingDB.addLog("INFO", msg, dbArgs);
}
}
console.error = function () {
var args = $.usaHaulersLoggingDB.prepareLog(arguments);
OLD_CONSOLE_ERROR.apply(console, args);
if ($.usaHaulersLoggingDB && $.usaHaulersLoggingDB.addLog && $.usaHaulersLoggingDB.dbInitialized && $.usaHaulersLoggingDB.shouldLogLevel("error")) {
var msg = $.usaHaulersLoggingDB.getLogMsgFromArguments(arguments);
var dbArgs = Array.from(arguments);
$.usaHaulersLoggingDB.addLog("ERROR", msg, dbArgs);
}
}
if ($ && $.ajaxSetup) {
$(document).ready(function () {
$(document).ajaxSuccess(function (event, xhr, settings) {
if ($.usaHaulersLoggingDB.shouldLogAjaxRequests()) {
var responseText = "";
var isSuccess = true;
if (xhr.responseJson != null && xhr.responseJson.d != null && xhr.responseJson.d.success != null && !xhr.responseJson.d.success)
isSuccess = false;
if (!$.usaHaulersLoggingDB.shouldLogAjaxRequestsToConsoleErrorOnly() || !isSuccess) {
if (xhr.responseText && xhr.responseText != null) {
if ($.usaHaulersLoggingDB.logAjaxRequestsToConsoleMaxResponseChars() <= 0 || xhr.responseText.length <= $.usaHaulersLoggingDB.logAjaxRequestsToConsoleMaxResponseChars())
responseText = "response = '" + xhr.responseText + "';";
else
responseText = "responseSnippet='" + xhr.responseText.substring(0, $.usaHaulersLoggingDB.logAjaxRequestsToConsoleMaxResponseChars()) + "';";
}
}
else {
return;
}
if ($.usaHaulersLoggingDB.shouldLogAjaxRequestsToConsole()) {
if (!isSuccess)
console.debug("Ajax Success, returned success:false", {
url: settings.url,
httpMethod: settings.type,
responseText: responseText
});
else {
console.debug("Ajax Success", {
url: settings.url,
httpMethod: settings.type,
responseText: responseText
});
}
}
}
if (xhr.responseJson != null && xhr.responseJson.d != null && xhr.responseJson.d.success != null && xhr.responseJson.d.success) {
var lg_session_guid = request.getResponseHeader('lg_session_guid');
var lg_access_token = $.getBoolean(request.getResponseHeader('lg_access_token'));
var lg_application_code = $.getBoolean(request.getResponseHeader('lg_application_code'));
var lg_application_user_id = $.getBoolean(request.getResponseHeader('lg_application_user_id'));
if ($.cookie) {
$.cookie.raw = true;
$.cookie('lg_session_guid', lg_session_guid, { path: '/' });
$.cookie('lg_access_token', lg_access_token, { path: '/' });
$.cookie('lg_application_code', lg_application_code, { path: '/' });
$.cookie('lg_application_user_id', lg_application_user_id, { path: '/' });
}
}
});
$(document).ajaxError(function (event, xhr, settings) {
if ($.usaHaulersLoggingDB.shouldLogAjaxRequests()) {
var responseText = "";
if (xhr.responseText && xhr.responseText != null) {
if ($.usaHaulersLoggingDB.logAjaxRequestsToConsoleMaxResponseChars() <= 0 || xhr.responseText.length <= $.usaHaulersLoggingDB.logAjaxRequestsToConsoleMaxResponseChars())
responseText = "response = '" + xhr.responseText + "';";
else
responseText = "responseSnippet='" + xhr.responseText.substring(0, $.usaHaulersLoggingDB.logAjaxRequestsToConsoleMaxResponseChars()) + "';";
}
if ($.usaHaulersLoggingDB.shouldLogAjaxRequestsToConsole()) {
console.error("Ajax Error", {
url: settings.url,
httpMethod: settings.type,
responseText: responseText,
xhr: $.usaHaulersLoggingDB.removeObjectMethodsForSerialization(xhr),
settings: $.usaHaulersLoggingDB.removeObjectMethodsForSerialization(settings)
});
}
}
});
});
}
const INTERNAL_USAHAULERSLOGGING_ONUPGRADEDNEEDED = function (event) {
const db = event.target.result;
const transaction = event.currentTarget.transaction;
let oldVersion = event.oldVersion;
let newVersion = event.newVersion;
if (oldVersion < 1 && newVersion >= 1) {
//setup object stores
db.createObjectStore(INTERNAL_USAHAULERSLOGGING_USEHAULERSLOGGINGDBCONFIG_OBJECT_STORE, { keyPath: 'id' });
if (db.objectStoreNames.contains(INTERNAL_USAHAULERSLOGGING_LOG_OBJECT_STORE)) {
db.deleteObjectStore(INTERNAL_USAHAULERSLOGGING_LOG_OBJECT_STORE);
}
db.createObjectStore(INTERNAL_USAHAULERSLOGGING_LOG_OBJECT_STORE, { keyPath: 'id' });
//setup indexes
let store = transaction.objectStore(INTERNAL_USAHAULERSLOGGING_LOG_OBJECT_STORE);
if (store.indexNames.contains(INTERNAL_USAHAULERSLOGGING_LOG_INDEX_DATE)) {
store.deleteIndex(INTERNAL_USAHAULERSLOGGING_LOG_INDEX_DATE);
}
store.createIndex(INTERNAL_USAHAULERSLOGGING_LOG_INDEX_DATE, "date", { unique: false });
if (store.indexNames.contains(INTERNAL_USAHAULERSLOGGING_LOG_INDEX_LEVEL)) {
store.deleteIndex(INTERNAL_USAHAULERSLOGGING_LOG_INDEX_LEVEL);
}
store.createIndex(INTERNAL_USAHAULERSLOGGING_LOG_INDEX_LEVEL, "level", { unique: false });
if (store.indexNames.contains(INTERNAL_USAHAULERSLOGGING_LOG_INDEX_UPLOADED)) {
store.deleteIndex(INTERNAL_USAHAULERSLOGGING_LOG_INDEX_UPLOADED);
}
store.createIndex(INTERNAL_USAHAULERSLOGGING_LOG_INDEX_UPLOADED, "upload_status", { unique: false });
}
if (oldVersion < 2 && newVersion >= 2) {
//
}
}
$.extend($.usaHaulersLoggingDB, {
dbInitialized: false,
database: null,
initializeDB: function () {
let currentDB = this;
return new Promise(function (resolve, reject) {
if (currentDB.dbInitialized) {
resolve();
return;
}
currentDB.refreshConfigObject().then(function () {
currentDB.dbInitialized = true;
resolve();
});
});
},
createConfigObject: function () {
let currentDB = this;
var config = (!currentDB.config || currentDB.config == null ? DEFAULT_LOG_CONFIG_OBJECT : currentDB.config);
return config;
},
refreshConfigObject: function () {
let currentDB = this;
return new Promise(async function (resolve, reject) {
try {
let config = await currentDB.getObjects(INTERNAL_USAHAULERSLOGGING_USEHAULERSLOGGINGDBCONFIG_OBJECT_STORE);
let configDefault = currentDB.createConfigObject();
if (!config || config.length == 0) {
currentDB.config = configDefault;
await currentDB.persistConfigObject();
}
else {
currentDB.config = config[0];
let updatedConfig = false;
for (const prop in configDefault) {
if (prop !== "id" || currentDB.config[prop] === undefined) {
updatedConfig = true;
currentDB.config[prop] = configDefault[prop];
}
}
if (updatedConfig)
await currentDB.persistConfigObject();
}
resolve();
}
catch (error) {
reject(error);
}
});
},
persistConfigObject: function () {
let currentDB = this;
return currentDB.runTransactionReadWrite(INTERNAL_USAHAULERSLOGGING_USEHAULERSLOGGINGDBCONFIG_OBJECT_STORE, async function (transaction) {
const configStore = transaction.objectStore(INTERNAL_USAHAULERSLOGGING_USEHAULERSLOGGINGDBCONFIG_OBJECT_STORE);
configStore.put(currentDB.config);
return transaction.complete;
});
}
});
//#region basic indexeddb methods
$.extend($.usaHaulersLoggingDB, {
create: function (deleteIfExists = true) {
return new Promise(async function (resolve, reject) {
if (deleteIfExists === true) {
try {
await $.dbManager.deleteDatabase(USAHAULERSLOGGING_DATABASE_NAME);
}
catch (error) {
reject(error);
return;
}
}
try {
await $.dbManager.openDatabase(USAHAULERSLOGGING_DATABASE_NAME, USAHAULERSLOGGING_DATABASE_VERSION, INTERNAL_USAHAULERSLOGGING_ONUPGRADEDNEEDED);
}
catch (error) {
reject(error);
return;
}
resolve();
});
},
delete: function () {
let currentDB = this;
return $.dbManager.deleteDatabase(USAHAULERSLOGGING_DATABASE_NAME);
},
open: function () {
let currentDB = this;
return $.dbManager.openDatabase(USAHAULERSLOGGING_DATABASE_NAME, USAHAULERSLOGGING_DATABASE_VERSION, INTERNAL_USAHAULERSLOGGING_ONUPGRADEDNEEDED).then(
function onSuccessInternal(db) {
currentDB.database = db;
if (!currentDB.dbInitialized)
return currentDB.initializeDB();
else
return currentDB.refreshConfigObject();
},
function onErrorInternal(error) {
}
);
},
close: function () {
let currentDB = this;
return $.dbManager.closeDatabase(USAHAULERSLOGGING_DATABASE_NAME).then(
function onSuccessInternal(db) {
currentDB.database = null;
},
function onErrorInternal(error) {
}
);
},
runTransactionReadOnly: function (objectNames, transactionCode) {
let currentDB = this;
return new Promise(function (resolve, reject) {
if (transactionCode != null) {
let didOpenDB = false;
var onSuccessInternal = function () {
let transaction = currentDB.database.transaction(objectNames, "readonly");
transactionCode(transaction);
//if (didOpenDB)
// currentDB.close();
transaction.oncomplete = function (event) {
resolve();
};
transaction.onerror = function (event) {
reject(error.error);
};
//Transactions auto-commit after scope ends, cannot manually commit
};
if ($.usaHaulersLoggingDB.database == null) {
didOpenDB = true;
currentDB.open().then(
onSuccessInternal,
function onErrorInternal(error) {
reject(error);
});
}
else {
onSuccessInternal();
}
}
else {
reject("No transactionCode passed");
}
});
},
runTransactionReadWrite: function (objectNames, transactionCode) {
let currentDB = this;
return new Promise(function (resolve, reject) {
if (transactionCode != null) {
let didOpenDB = false;
var onSuccessInternal = function () {
let transaction = currentDB.database.transaction(objectNames, "readwrite");
transactionCode(transaction);
//if (didOpenDB)
// currentDB.close();
transaction.oncomplete = function (event) {
resolve();
};
transaction.onerror = function (event) {
reject(error.error);
};
//Transactions auto-commit after scope ends, cannot manually commit
};
if ($.usaHaulersLoggingDB.database == null) {
didOpenDB = true;
currentDB.open().then(
onSuccessInternal,
function onErrorInternal(error) {
reject(error);
});
}
else {
onSuccessInternal();
}
}
else {
reject("No transactionCode passed");
}
});
},
getObjects: function (objectName, query, indexes) {
let currentDB = this;
return new Promise(function (resolve, reject) {
currentDB.runTransactionReadOnly(objectName, function (transaction) {
const objectStore = transaction.objectStore(objectName);
let request = {};
if (indexes && ((typeof indexes === "string" || indexes instanceof String) == false || indexes.length > 0))
if (query
&& (typeof query === "IDBKeyRange" || query instanceof IDBKeyRange || typeof query === "string" || query instanceof String))
request = objectStore.index(indexes).getAll(query);
else
request = objectStore.index(indexes).getAll();
else
if (query
&& (typeof query === "IDBKeyRange" || query instanceof IDBKeyRange || typeof query === "string" || query instanceof String))
request = objectStore.getAll(query);
else
request = objectStore.getAll()
request.onsuccess = function () {
if (request.result !== undefined) {
objects = request.result;
resolve(objects);
}
else {
console.log("no objects found: ", objectName);
reject("no objects found: ", objectName);
}
};
request.onerror = function (error) {
console.log("Error getting objects(", objectName, ") from db: ", error);
reject(error);
};
});
});
},
getObjectsCustom: function (objectName, query, indexes, predicateBlock) {
let currentDB = this;
return new Promise(function (resolve, reject) {
currentDB.runTransactionReadOnly(objectName, function (transaction) {
const objectStore = transaction.objectStore(objectName);
let request = {};
if (indexes && ((typeof indexes === "string" || indexes instanceof String) == false || indexes.length > 0))
request = (query && ((typeof query === "string" || query instanceof String) == false || query.length > 0) ? objectStore.index(indexes).getAll(query) : objectStore.index(indexes).getAll());
else
request = (query && ((typeof query === "string" || query instanceof String) == false || query.length > 0) ? objectStore.getAll(query) : objectStore.getAll());
request.onsuccess = function () {
if (request.result !== undefined) {
let objectsUnfiltered = request.result;
let objects = [];
for (ix in objectsUnfiltered) {
if (!predicateBlock || predicateBlock(objectsUnfiltered[ix])) {
objects.push(objectsUnfiltered[ix]);
}
}
resolve(objects);
}
else {
console.log("no objects found: ", objectName);
reject("no objects found: ", objectName);
}
};
request.onerror = function (error) {
console.log("Error getting objects(", objectName, ") from db: ", error);
reject(error);
};
});
});
},
deleteAllObjects: function () {
let currentDB = this;
var error = null;
var objectNames = INTERNAL_USAHAULERSLOGGING_LOG_OBJECT_STORE;
return this.runTransactionReadWrite(objectNames, async function (transaction) {
const logStore = transaction.objectStore(INTERNAL_USAHAULERSLOGGING_LOG_OBJECT_STORE);
try {
await logStore.clear();
}
catch (error2) {
error = error2;
}
return transaction.complete;
});
if (error) {
throw error;
}
}
});
//#endregion
//ADD NON-GENERIC METHODS
$.extend($.usaHaulersLoggingDB, {
newGuid: function () {
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
const r = Math.random() * 16 | 0,
v = c == 'x' ? r : (r & 0x3 | 0x8);
return v.toString(16);
});
},
createLogObjectInternal: function (id, level, msg, args, date) {
return {
id: (id == null ? this.newGuid() : id),
version: '1.0',
url: window.location.href,
application_code: $.cookie('lg_application_code'),
application_user_id: $.cookie('lg_application_user_id'),
environment_code: $.cookie('lg_environment_code'),
level: level,
msg: msg,
arguments: args,
date: (date == null ? new Date() : date),
time: (date == null ? new Date() : date).toISOString(),
uploaded: false,
upload_status: 'Not Uploaded',
upload_date: null
}
},
createLogObject: function (level, msg, args) {
return this.createLogObjectInternal(null, level, msg, args, null);
},
addLog: async function (level, msg, args) {
let currentDB = this;
args = currentDB.removeObjectMethodsForSerialization(args);
try {
await currentDB.refreshConfigObject();
var error = null;
var log = currentDB.createLogObject(level, msg, args);
return this.runTransactionReadWrite(INTERNAL_USAHAULERSLOGGING_LOG_OBJECT_STORE, async function (transaction) {
const logStore = transaction.objectStore(INTERNAL_USAHAULERSLOGGING_LOG_OBJECT_STORE);
logStore.put(log);
return transaction.complete;
}).then(
function () {
},
function (errorInternal) {
error = errorInternal;
}
);
if (error) {
throw error;
}
}
catch (error) {
console.log(error);
throw error;
}
},
deleteLogs: async function (logs) {
let currentDB = this;
try {
await currentDB.refreshConfigObject();
var error = null;
return this.runTransactionReadWrite(INTERNAL_USAHAULERSLOGGING_LOG_OBJECT_STORE, async function (transaction) {
const logStore = transaction.objectStore(INTERNAL_USAHAULERSLOGGING_LOG_OBJECT_STORE);
logs.forEach((log) => {
logStore.delete(log.id);
});
return transaction.complete;
}).then(
function () {
},
function (errorInternal) {
error = errorInternal;
}
);
if (error) {
throw error;
}
}
catch (error) {
console.log(error);
throw error;
}
},
getLogsByLevel: async function (level, startDate, endDate) {
let currentDB = this;
let levelText = "";
if (level != undefined && level != null)
levelText = level.toUpperCase();
let query = levelText;
let indexes = INTERNAL_USAHAULERSLOGGING_LOG_INDEX_LEVEL;
let logs = await currentDB.getObjects(INTERNAL_USAHAULERSLOGGING_LOG_OBJECT_STORE, query, indexes);
let logs2 = [];
logs.forEach((log) => {
if ((startDate == null || log.date >= startDate) && (endDate == null || log.date <= endDate))
logs2.push(log);
});
logs2.sort(function (l1, l2) {
return l1.date - l2.date;
});
return logs2;
},
getLogsAll: async function (startDate, endDate) {
let currentDB = this;
let query = "";
let logs = await currentDB.getObjects(INTERNAL_USAHAULERSLOGGING_LOG_OBJECT_STORE, query);
let logs2 = [];
logs.forEach((log) => {
if ((startDate == null || log.date >= startDate) && (endDate == null || log.date <= endDate))
logs2.push(log);
});
logs2.sort(function (l1, l2) {
return l1.date - l2.date;
});
return logs2;
},
getLogsByUploaded: async function (uploaded, startDate, endDate) {
let currentDB = this;
let query = uploaded ? "Uploaded" : "Not Uploaded";
let indexes = INTERNAL_USAHAULERSLOGGING_LOG_INDEX_UPLOADED;
let logs = await currentDB.getObjects(INTERNAL_USAHAULERSLOGGING_LOG_OBJECT_STORE, query, indexes);
let logs2 = [];
logs.forEach((log) => {
if ((startDate == null || log.date >= startDate) && (endDate == null || log.date <= endDate))
logs2.push(log);
});
logs2.sort(function (l1, l2) {
return l1.date - l2.date;
});
return logs2;
},
getLogsByUploadStatus: async function (uploadStatus, startDate, endDate) {
let currentDB = this;
let query = uploadStatus
let indexes = INTERNAL_USAHAULERSLOGGING_LOG_INDEX_UPLOADED;
let logs = await currentDB.getObjects(INTERNAL_USAHAULERSLOGGING_LOG_OBJECT_STORE, query, indexes);
let logs2 = [];
logs.forEach((log) => {
if ((startDate == null || log.date >= startDate) && (endDate == null || log.date <= endDate))
logs2.push(log);
});
logs2.sort(function (l1, l2) {
return l1.date - l2.date;
});
return logs2;
},
markLogsUploaded: async function (logs) {
let currentDB = this;
try {
await currentDB.refreshConfigObject();
var error = null;
logs.forEach((log) => {
log.uploaded = true;
log.upload_status = "Uploaded";
log.upload_date = new Date();
});
return this.runTransactionReadWrite(INTERNAL_USAHAULERSLOGGING_LOG_OBJECT_STORE, async function (transaction) {
const logStore = transaction.objectStore(INTERNAL_USAHAULERSLOGGING_LOG_OBJECT_STORE);
logs.forEach((log) => {
logStore.put(log);
});
return transaction.complete;
}).then(
function () {
},
function (errorInternal) {
error = errorInternal;
}
);
if (error) {
throw error;
}
}
catch (error) {
console.error(error);
//throw error;
}
},
uploadLogs: async function () {
var currentDB = this;
try {
await currentDB.refreshConfigObject();
var logs = null;
var maxUploadQty = INTERNAL_USAHAULERSLOGGING_MAXUPLOADQTY;
if (maxUploadQty <= 0)
maxUploadQty = 999999;
do {
logs = await currentDB.getLogsByUploaded(false, maxUploadQty);
if (logs != null && logs.length > 0) {
var success = false;
//try {
success = await currentDB.uploadLogChunk(logs);
//}
//catch {
// throw;
//}
if (!success) {
console.debug("currentDB.uploadLogChunk returned false");
return false;
}
//await currentDB.markLogsUploaded(logs);
await currentDB.deleteLogs(logs);
if (logs.length < maxUploadQty)
break;
}
} while (logs != null && logs.length > 0);
return true;
}
catch (error) {
if (!(error instanceof Error))
console.error(JSON.stringify(error));
else
console.error(error);
return false;
//throw error;
}
},
getLogURL: function () {
var environmentCode = $.cookie('lg_environment_code');
if (environmentCode === null || environmentCode.trim().length == 0)
environmentCode = "DEFAULT";
environmentCode = environmentCode.toUpperCase();
var logUrl = INTERNAL_LOG_URLS[environmentCode];
if (logUrl === null || logUrl.trim().length == 0)
logUrl = INTERNAL_LOG_URLS['DEFAULT'];
return logUrl;
},
uploadLogChunk: async function (logs) {
var currentDB = this;
var success = false;
await $.ajax({
type: "POST",
url: currentDB.getLogURL(),
data: JSON.stringify({ "jsonData": JSON.stringify(logs) }),
contentType: 'application/json; charset=utf-8',
dataType: 'json',
async: true,
cache: false,
timeout: 30000,
disable_auth_token:true,
headers: {
lg_session_id: $.cookie('lg_session_guid'),
lg_access_token: $.cookie('lg_access_token')
},
success: function (value, textStatus, request) {
var json = value.hasOwnProperty("d") ? $.parseJSON(value.d) : $.parseJSON(value);
if (currentDB.getBoolean(json.success)) {
success = true;
return true;
}
success = false;
return false;
},
error: function (xhr, error, errorThrown) {
//if ((error instanceof jqXHR)
// console.error(JSON.stringify(error));
//else if (!(error instanceof Error))
// console.error(JSON.stringify(error));
//else
// console.error(error);
success = false;
return false;
}
});
return success;
}
});
//TODO: Decide what to do here. This PROBABLY should be a method call that the UI calls on page load, otherwise some calls could happen before this is done/ready. Can't put await on this method, jquery .ready queue will not wait correctly.
$(document).ready(function () {
$.usaHaulersLoggingDB.open().then(() => {
console.log("$.usaHaulersLoggingDB.open() success");
return $.usaHaulersLoggingDB.initializeDB();
})
.then(() => {
console.log("$.usaHaulersLoggingDB.initializeDB() success");
return $.usaHaulersLoggingDB.uploadLogs();
},
(error) => {
console.error(error);
});
});
$(document).ajaxSend(function (event, xhr, settings) {
if (settings.disable_auth_token) {
xhr.setRequestHeader('Auth-Token', null);
xhr.setRequestHeader('Auth-Impersonate-Guid', null);
xhr.setRequestHeader('Auth-Current-Franchise', null);
}
});

View File

@ -1,404 +0,0 @@

$.webauthn = {
methodCodeRegister: "Register",
methodCodeLogin: "Login",
isSupported: function () {// Availability of `window.PublicKeyCredential` means webauthn is usable.
if (window.PublicKeyCredential && PublicKeyCredential.isConditionalMediationAvailable) {
return true;
}
return false;
},
abortController: new AbortController(),
getPublicKey: async function (method, type, username) {
let jsonData = {};
let error = null;
await $.webMethodAsync({
'methodPage': 'Webauthn/GetPublicKey',
'parameters': { "method": method, "type": type, "username": username },
success: function (json) {
if (json.success === true || json.success === "true") {
jsonData = json.data;
}
else {
error = "success=false";
}
},
error: function (errorInternal) {
error = errorInternal;
}
});
if (error)
throw error;////
return jsonData;
},
getPublicKeyForLogin: async function (username) {
return $.webauthn.getPublicKey($.webauthn.methodCodeLogin, "Any", username);
},
authenticate: async function (publicKey) {
if (!this.isSupported())
throw new Error("webauthn is not supported");
var publicKeyMain = JSON.parse(JSON.stringify(publicKey));
if (publicKey.publicKey !== undefined) {
publicKey = publicKey.publicKey;
}
var manager = this;
if (publicKey.challenge !== undefined)
publicKey.challenge = $.webauthn.coerceToArrayBuffer(publicKey.challenge);
if (publicKey.user !== undefined && publicKey.user.id !== undefined)
publicKey.user.id = $.webauthn.coerceToArrayBuffer(publicKey.user.id);
if (publicKey.excludeCredentials !== undefined && publicKey.excludeCredentials !== null) {
for (var exKey of publicKey.excludeCredentials) {
if (exKey.id !== undefined && exKey.id !== null)
exKey.id = $.webauthn.coerceToArrayBuffer(exKey.id);
}
}
if (publicKey.allowCredentials !== undefined && publicKey.allowCredentials !== null) {
for (var allowCred of publicKey.allowCredentials) {
if (allowCred.id !== undefined && allowCred.id !== null)
allowCred.id = $.webauthn.coerceToArrayBuffer(allowCred.id);
}
}
var clientResponse;
try {
assertedCredential = await navigator.credentials.get({
publicKey: publicKey,
signal: $.webauthn.abortController.signal
});
}
catch (error) {
console.error(error);
showAlert("error", error);
return null;
}
let authData = new Uint8Array(assertedCredential.response.authenticatorData);
let clientDataJSON = new Uint8Array(assertedCredential.response.clientDataJSON);
let rawId = new Uint8Array(assertedCredential.rawId);
let sig = new Uint8Array(assertedCredential.response.signature);
const data = {
id: assertedCredential.id,
rawId: $.webauthn.coerceToBase64Url(rawId),
type: assertedCredential.type,
extensions: assertedCredential.getClientExtensionResults(),
response: {
authenticatorData: $.webauthn.coerceToBase64Url(authData),
clientDataJSON: $.webauthn.coerceToBase64Url(clientDataJSON),
signature: $.webauthn.coerceToBase64Url(sig)
}
};
return await $.webauthn.verifyKey(data);
},
saveKey: async function (type, publicKey, newKey) {
let error = null;
var outputJson = null;
await $.webMethodAsync({
'methodPage': 'Webauthn/SaveKey',
'parameters': { "type": type, "publicKey": publicKey, "newKey": newKey },
success: function (json) {
if (json.success === true || json.success === "true") {
outputJson = json;
}
else {
error = "success=false";
}
},
error: function (errorInternal) {
error = errorInternal;
}
});
if (error)
throw error;
return outputJson;
},
verifyKey: async function (clientResponse) {
let error = null;
var outputJson = null;
await $.webMethodAsync({
'methodPage': 'Webauthn/VerifyKey',
'parameters': { "clientResponse": clientResponse },
success: function (json) {
if (json.success === true || json.success === "true") {
outputJson = json;
}
else {
error = "success=false";
}
},
error: function (errorInternal) {
error = errorInternal;
}
});
if (error)
throw error;
return outputJson;
},
passkeys: {
typeCode: "passkey",
abortController: new AbortController(),
isSupported: function () {
if ($.webauthn.isSupported()) {
return true;
//// Check if conditional mediation is available.
//const isCMA = await PublicKeyCredential.isConditionalMediationAvailable();
//if (isCMA) {
// return true;
//}
}
return false;
},
getPublicKeyForRegister: async function (username) {
return $.webauthn.getPublicKey($.webauthn.methodCodeRegister, this.typeCode, username);
},
getPublicKeyForLogin: async function (username) {
return $.webauthn.getPublicKey($.webauthn.methodCodeLogin, this.typeCode, username);
},
authenticate: async function (publicKey) {
if (!this.isSupported())
throw new Error("webauthn/passkeys is not supported");
return $.webauthn.authenticate(publicKey);
},
create: async function (publicKey) {
if (!this.isSupported())
throw new Error("webauthn/passkeys is not supported");
var publicKeyMain = JSON.parse(JSON.stringify(publicKey));
if (publicKey.publicKey !== undefined) {
publicKey = publicKey.publicKey;
}
var manager = this;
if (publicKey.challenge !== undefined)
publicKey.challenge = $.webauthn.coerceToArrayBuffer(publicKey.challenge);
if (publicKey.user !== undefined && publicKey.user.id !== undefined)
publicKey.user.id = $.webauthn.coerceToArrayBuffer(publicKey.user.id);
if (publicKey.excludeCredentials !== undefined && publicKey.excludeCredentials !== null) {
for (var exKey of publicKey.excludeCredentials) {
if (exKey.id !== undefined && exKey.id !== null)
exKey.id = $.webauthn.coerceToArrayBuffer(exKey.id);
}
}
try {
var credential = await navigator.credentials.create({
publicKey: publicKey,
signal: $.webauthn.abortController.signal
});
}
catch (error) {
console.error(error);
showAlert("error", error);
return null;
}
var credential2 = {
authenticatorAttachment: credential.authenticatorAttachment,
id: credential.id,
rawId: $.webauthn.coerceToBase64Url(credential.rawId),
type: credential.type,
extensions: credential.getClientExtensionResults(),
response: {
attestationObject: $.webauthn.coerceToBase64Url(credential.response.attestationObject),
clientDataJSON: $.webauthn.coerceToBase64Url(credential.response.clientDataJSON),
transports: credential.response.getTransports()
},
type: credential.type
}
var publicKey2 = JSON.parse(JSON.stringify(publicKey));
publicKey2.user.id = publicKeyMain.publicKey.user.id;
publicKey2.challenge = publicKeyMain.publicKey.challenge;
var keySaved = await $.webauthn.saveKey(this.typeCode, publicKey2, credential2);
if ($.getBoolean(keySaved.success))
showAlert("success", "Key created");
else
showAlert("error", "Key creation failed");
}
},
securityKeys: {
typeCode: "securitykey",
abortController: new AbortController(),
isSupported: function () {
if ($.webauthn.isSupported()) {
return true;
//// Check if conditional mediation is available.
//const isCMA = await PublicKeyCredential.isConditionalMediationAvailable();
//if (isCMA) {
// return true;
//}
}
return false;
},
getPublicKeyForRegister: async function (username) {
return $.webauthn.getPublicKey($.webauthn.methodCodeRegister, this.typeCode, username);
},
getPublicKeyForLogin: async function (username) {
return $.webauthn.getPublicKey($.webauthn.methodCodeLogin, this.typeCode, username);
},
saveKey: async function (publicKey, newKey) {
return $.webauthn.saveKey(this.typeCode, publicKey, newKey);
},
authenticate: async function (publicKey) {
if (!this.isSupported())
throw new Error("webauthn/securityKeys is not supported");
return $.webauthn.authenticate(publicKey);
},
create: async function (publicKey) {
if (!this.isSupported())
throw new Error("webauthn/securityKeys is not supported");
var publicKeyMain = JSON.parse(JSON.stringify(publicKey));
if (publicKey.publicKey !== undefined) {
publicKey = publicKey.publicKey;
}
var manager = this;
if (publicKey.challenge !== undefined)
publicKey.challenge = $.webauthn.coerceToArrayBuffer(publicKey.challenge);
if (publicKey.user !== undefined && publicKey.user.id !== undefined)
publicKey.user.id = $.webauthn.coerceToArrayBuffer(publicKey.user.id);
if (publicKey.excludeCredentials !== undefined && publicKey.excludeCredentials !== null) {
for (var exKey of publicKey.excludeCredentials) {
if (exKey.id !== undefined && exKey.id !== null)
exKey.id = $.webauthn.coerceToArrayBuffer(exKey.id);
}
}
try {
var credential = await navigator.credentials.create({
publicKey: publicKey,
signal: $.webauthn.abortController.signal
});
}
catch (error) {
console.error(error);
showAlert("error", error);
return null;
}
var credential2 = {
authenticatorAttachment: credential.authenticatorAttachment,
id: credential.id,
rawId: $.webauthn.coerceToBase64Url(credential.rawId),
type: credential.type,
extensions: credential.getClientExtensionResults(),
response: {
attestationObject: $.webauthn.coerceToBase64Url(credential.response.attestationObject),
clientDataJSON: $.webauthn.coerceToBase64Url(credential.response.clientDataJSON),
transports: credential.response.getTransports()
},
type: credential.type
}
var publicKey2 = JSON.parse(JSON.stringify(publicKey));
publicKey2.user.id = publicKeyMain.publicKey.user.id;
publicKey2.challenge = publicKeyMain.publicKey.challenge;
var keySaved = await $.webauthn.saveKey(this.typeCode, publicKey2, credential2);
if ($.getBoolean(keySaved.success))
showAlert("success", "Key created");
else
showAlert("error", "Key creation failed");
}
},
stringToArrayBuffer: function (string) {
var string2 = (typeof string !== "string" ? string.toString() : string);
return Uint8Array.from(string2, c => c.charCodeAt(0));
},
arrayBufferToString: function (buffer) {
return String.fromCharCode.apply(null, new Uint8Array(buffer));
},
arrayBufferToBase64String: function (buffer) {
return window.btoa(String.fromCharCode.apply(null, new Uint8Array(buffer)));
},
coerceToArrayBuffer: function (thing, name) {
if (thing === undefined || thing === null)
return null;
if (typeof thing === "string") {
// base64url to base64
thing = thing.replace(/-/g, "+").replace(/_/g, "/");
// base64 to Uint8Array
var str = window.atob(thing);
var bytes = new Uint8Array(str.length);
for (var i = 0; i < str.length; i++) {
bytes[i] = str.charCodeAt(i);
}
thing = bytes;
}
// Array to Uint8Array
if (Array.isArray(thing)) {
thing = new Uint8Array(thing);
}
// Uint8Array to ArrayBuffer
if (thing instanceof Uint8Array) {
thing = thing.buffer;
}
// error if none of the above worked
if (!(thing instanceof ArrayBuffer)) {
throw new TypeError("could not coerce '" + name + "' to ArrayBuffer");
}
return thing;
},
coerceToBase64Url: function (thing) {
if (thing === undefined || thing === null)
return null;
// Array or ArrayBuffer to Uint8Array
if (Array.isArray(thing)) {
thing = Uint8Array.from(thing);
}
if (thing instanceof ArrayBuffer) {
thing = new Uint8Array(thing);
}
// Uint8Array to base64
if (thing instanceof Uint8Array) {
var str = "";
var len = thing.byteLength;
for (var i = 0; i < len; i++) {
str += String.fromCharCode(thing[i]);
}
thing = window.btoa(str);
}
if (typeof thing !== "string") {
throw new Error("could not coerce to string");
}
// base64 to base64url
// NOTE: "=" at the end of challenge is optional, strip it off here
//thing = thing.replace(/\+/g, "-").replace(/\//g, "_").replace(/=*$/g, "");
return thing;
}
}

View File

@ -1,149 +0,0 @@

async function CheckAuthToken() {
var data = null;
return new Promise((resolve, reject) => {
try {
callMethod("CheckAuthToken", {}).then((data) => {
//return the first element in the array for this call.
resolve(data[0]);
}).catch((data) => {
reject(data);
});
} catch (error) {
reject(error);
}
});
}
async function GetVehicles() {
var data = null;
return new Promise((resolve, reject) => {
try {
callMethod("GetVehicles", {}).then((data) => {
//return the first element in the array for this call.
resolve(data);
}).catch((data) => {
reject(data);
});
} catch (error) {
reject(error);
}
});
}
async function SaveVehicle(vehicleId, vehicleData)
{
var data = null;
return new Promise((resolve, reject) => {
try {
callMethod("SaveVehicle", {"vehicleId":vehicleId, "jsonData": JSON.stringify(vehicle) }).then((data) => {
//return the first element in the array for this call.
resolve(data);
}).catch((data) => {
reject(data);
});
} catch (error) {
reject(error);
}
});
}
async function GetVehicleImages(vehicleID) {
var data = null;
return new Promise((resolve, reject) => {
try {
callMethod("GetVehicleImages", { "vehicleID": vehicleID }).then((data) => {
//return the first element in the array for this call.
resolve(data);
}).catch((data) => {
reject(data);
});
} catch (error) {
reject(error);
}
});
}
async function SaveCurrentUser() {
user = currentUser;
return new Promise((resolve, reject) => {
try {
callMethod("SaveUser", { "userJson": JSON.stringify(user) }).then((data) => {
resolve(data);
}).catch((data) => {
reject(data);
});
} catch (error) {
reject(error);
}
});
}
async function ServerHealthCheck() {
return new Promise((resolve, reject) => {
$.webMethod({
'methodPage': 'UserMethods/',
'methodName': "ServerHealthCheck",
'parameters': {},
'timeout': 3000,
success: function (json) {
if ($.getBoolean(json.success)) {
data = json;
resolve(data);
}
else {
data = json;
reject(data);
}
},
error: function (data) {
reject(data);
}
});
});
}
async function callMethod(methodName, parameters) {
return new Promise((resolve, reject) => {
$.webMethod({
'methodPage': 'UserMethods',
'methodName': methodName,
'parameters': parameters,
'timeout': 60000,
success: function (json) {
if (json.data != null) {
data = json.data;
}
else {
data = json;
}
if ($.getBoolean(json.success)) {
resolve(data);
}
else {
reject(data);
}
},
error: function (data) {
}
});
});
}

View File

@ -7,6 +7,12 @@ export const API_BASE_URL = import.meta.env.VITE_API_BASE_URL;
// Add global values to window object for use in static JS // Add global values to window object for use in static JS
declare global {
interface Window {
API_BASE_URL: object
}
}
if (typeof window !== 'undefined') { if (typeof window !== 'undefined') {
window.API_BASE_URL = API_BASE_URL; window.API_BASE_URL = API_BASE_URL;
} }

View File

@ -44,8 +44,8 @@ const utils = {
baseMethodPath?: string; baseMethodPath?: string;
methodPage?: string; methodPage?: string;
methodName?: string; methodName?: string;
parameters?: Record<string, any>;
contentType?: string; contentType?: string;
parameters?: Record<string, any>;
timeout?: number; timeout?: number;
success?: (data: any) => void; success?: (data: any) => void;
error?: (err: any) => void; error?: (err: any) => void;