Merge pull request #1195 from hargata/Hargata/1192

Hargata/1192
This commit is contained in:
Hargata Softworks 2026-01-04 22:48:15 -07:00 committed by GitHub
commit a155e3993b
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
9 changed files with 1912 additions and 1125 deletions

View File

@ -6,6 +6,7 @@ using CarCareTracker.Models;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using System.Security.Claims;
using System.Text.Json;
namespace CarCareTracker.Controllers
{
@ -103,7 +104,23 @@ namespace CarCareTracker.Controllers
}
public IActionResult Index()
{
return View();
//load up documentation
var apiDocFilePath = _fileHelper.GetFullFilePath("/defaults/api.json");
var apiDocText = _fileHelper.GetFileText(apiDocFilePath);
var apiDocData = JsonSerializer.Deserialize<List<APIDocumentation>>(apiDocText);
var apiSerializeOptions = StaticHelper.GetNoEncodingOption();
apiSerializeOptions.WriteIndented = true;
foreach(APIDocumentation apiDocumentation in apiDocData)
{
foreach(APIMethod apiMethod in apiDocumentation.Methods)
{
if (apiMethod.HasBody)
{
apiMethod.BodySampleString = JsonSerializer.Serialize(apiMethod.BodySample, apiSerializeOptions);
}
}
}
return View(apiDocData);
}
private int GetUserID()
{

10
Enum/APIMethodType.cs Normal file
View File

@ -0,0 +1,10 @@
namespace CarCareTracker.Models
{
public enum APIMethodType
{
GET = 0,
POST = 1,
PUT = 2,
DELETE = 3
}
}

View File

@ -976,5 +976,21 @@ namespace CarCareTracker.Helper
JsonSerializerOptions serializerOption = new JsonSerializerOptions { Encoder = JavaScriptEncoder.Create(UnicodeRanges.All) };
return serializerOption;
}
public static string GetAPIMethodColor(APIMethodType method)
{
switch (method)
{
case APIMethodType.GET:
return "primary";
case APIMethodType.POST:
return "success";
case APIMethodType.PUT:
return "warning";
case APIMethodType.DELETE:
return "danger";
default:
return "primary";
}
}
}
}

View File

@ -0,0 +1,41 @@
using System.Text.Json.Serialization;
namespace CarCareTracker.Models
{
public class APIDocumentation
{
[JsonPropertyName("categoryName")]
public string CategoryName { get; set; }
[JsonPropertyName("methods")]
public List<APIMethod> Methods { get; set; } = new List<APIMethod>();
}
public class APIMethod
{
[JsonPropertyName("path")]
public string Path { get; set; }
[JsonPropertyName("description")]
public string Description { get; set; }
[JsonPropertyName("methodType")]
public APIMethodType MethodType { get; set; }
[JsonPropertyName("queryParams")]
public List<APIQueryParam> QueryParams { get; set; } = new List<APIQueryParam>();
[JsonPropertyName("hasBody")]
public bool HasBody { get; set; }
[JsonPropertyName("bodySample")]
public object BodySample { get; set; } = new object();
public string BodySampleString { get; set; }
[JsonPropertyName("bodyParamName")]
public string BodyParamName { get; set; }
[JsonPropertyName("bodyIsFileUpload")]
public bool BodyIsFileUpload { get; set; } = false;
}
public class APIQueryParam
{
[JsonPropertyName("name")]
public string Name { get; set; }
[JsonPropertyName("required")]
public bool Required { get; set; }
[JsonPropertyName("description")]
public string Description { get; set; }
}
}

File diff suppressed because it is too large Load Diff

View File

@ -691,4 +691,11 @@ html[data-bs-theme="light"] .frosted {
html[data-bs-theme="dark"] .swal2-validation-message {
background-color: #2d2d2e !important;
}
.api-chevron{
transition: all 0.35s;
}
.collapsed .api-chevron {
transform: rotate(180deg);
transition: all 0.35s;
}

1649
wwwroot/defaults/api.json Normal file

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

95
wwwroot/js/swigarette.js Normal file
View File

@ -0,0 +1,95 @@
function toggleAPICollapse(sender) {
let headerElem = $(sender);
let collapseElem = headerElem.closest('.apiContainer').children('.collapse');
if ($(sender).hasClass('collapsed')) {
collapseElem.collapse('show');
$(sender).removeClass('collapsed');
} else {
collapseElem.collapse('hide');
$(sender).addClass('collapsed');
}
}
function testAPIEndpoint(sender) {
let apiTester = $(sender).closest('.collapse').children('.api-tester');
apiTester.toggleClass('d-none');
}
function executeAPIEndpoint(sender) {
let apiPath = $(sender).attr('data-endpoint');
let apiMethodType = $(sender).attr('data-method');
let apiData = {};
let hasError = false;
let isFileUpload = false;
//find result box
let apiResult = $(sender).closest('.form-group').children('.api-tester-result');
apiResult.children('.api-tester-result-text').val('');
//find body
let apiBodyElem = $(sender).closest('.form-group').children('.api-tester-body');
if (apiBodyElem.length > 0) {
if (apiBodyElem.attr('data-file') == "false") {
if (apiBodyElem.val().trim() == '') {
hasError = true;
apiBodyElem.addClass('is-invalid');
}
else {
apiBodyElem.removeClass('is-invalid');
apiData[apiBodyElem.attr('data-param')] = JSON.parse(apiBodyElem.val());
}
}
else {
isFileUpload = true;
let formData = new FormData();
let files = apiBodyElem[0].files;
if (files.length == 0) {
hasError = true;
apiBodyElem.addClass('is-invalid');
} else {
apiBodyElem.removeClass('is-invalid');
for (var x = 0; x < files.length; x++) {
formData.append(apiBodyElem.attr('data-param'), files[x]);
}
apiData = formData;
}
}
}
//find query params
let apiQueryElems = $(sender).closest('.form-group').find('.api-tester-param');
if (apiQueryElems.length > 0) {
apiQueryElems.map((index, elem) => {
if ($(elem).attr('data-required') == 'true' && $(elem).val().trim() == '') {
$(elem).addClass('is-invalid');
hasError = true;
} else {
$(elem).removeClass('is-invalid');
apiData[$(elem).attr('data-param')] = $(elem).val();
}
})
}
if (hasError) {
return;
}
let ajaxConfig = {
url: apiPath,
type: apiMethodType,
data: apiData,
success: function (response) {
apiResult.removeClass('d-none');
apiResult.children('.api-tester-result-text').val(JSON.stringify(response, null, 2));
},
error: function (xhr, status, error) {
apiResult.removeClass('d-none');
apiResult.children('.api-tester-result-text').val(JSON.stringify(xhr.responseJSON, null, 2));
}
};
if (isFileUpload) {
ajaxConfig['processData'] = false;
ajaxConfig['cache'] = false;
ajaxConfig['contentType'] = false;
}
//execute AJAX
$.ajax(ajaxConfig);
}
function copyAPIPath(sender) {
let textToCopy = $(sender).attr('data-endpoint');
navigator.clipboard.writeText(textToCopy);
successToast("Copied to Clipboard");
}