Commit 9546b45b by Mac Stephens

added showtoast, replacing shownotification on all but login, updated users to…

added showtoast, replacing shownotification on all but login, updated users to work correctly and populate correct, lots of other changes, fixed pdf popup block situation
parent 94cbacc0
...@@ -200,44 +200,6 @@ object FViewAddCustomer: TFViewAddCustomer ...@@ -200,44 +200,6 @@ object FViewAddCustomer: TFViewAddCustomer
WidthPercent = 100.000000000000000000 WidthPercent = 100.000000000000000000
OnClick = btnEditClick OnClick = btnEditClick
end end
object pnlMessage: TWebPanel
Left = 324
Top = 19
Width = 121
Height = 33
ElementID = 'view.login.message'
ChildOrder = 5
ElementPosition = epRelative
Role = 'null'
TabOrder = 16
object lblMessage: TWebLabel
Left = 28
Top = 9
Width = 46
Height = 15
Caption = 'Message'
ElementID = 'view.login.message.label'
ElementPosition = epRelative
HeightPercent = 100.000000000000000000
WidthPercent = 100.000000000000000000
end
object btnCloseNotification: TWebButton
Left = 96
Top = 3
Width = 22
Height = 25
ChildOrder = 1
ElementID = 'view.login.message.button'
ElementFont = efCSS
ElementPosition = epRelative
HeightStyle = ssAuto
HeightPercent = 100.000000000000000000
Role = 'null'
WidthStyle = ssAuto
WidthPercent = 100.000000000000000000
OnClick = btnCloseNotificationClick
end
end
object edtCustomerID: TWebDBEdit object edtCustomerID: TWebDBEdit
Left = 151 Left = 151
Top = 12 Top = 12
...@@ -393,7 +355,6 @@ object FViewAddCustomer: TFViewAddCustomer ...@@ -393,7 +355,6 @@ object FViewAddCustomer: TFViewAddCustomer
SelLength = 0 SelLength = 0
SelStart = 0 SelStart = 0
WidthPercent = 100.000000000000000000 WidthPercent = 100.000000000000000000
OnChange = memoAddressBlockChange
end end
object btnAdd: TWebButton object btnAdd: TWebButton
Left = 19 Left = 19
......
<nav class="navbar navbar-expand navbar-light bg-light sticky-top" style="z-index: 100;"> <nav class="navbar navbar-expand navbar-light bg-light sticky-top" style="z-index: 100;">
<div class="container-fluid ps-0"> <div class="container-fluid ps-0">
<div id="view.login.message" class="alert alert-danger"
style="padding: 0.25rem 0.5rem; font-size: 0.875rem; line-height: 1.5; display: flex; align-items: center; margin: 0 0 0 60px; height: 32px; width: 400px;">
<button id="view.login.message.button" type="button" class="btn-close" aria-label="Close"></button>
<span id="view.login.message.label"></span>
</div>
<ul class="navbar-nav me-auto ps-2"> <ul class="navbar-nav me-auto ps-2">
<li class="nav-item pe-2"> <li class="nav-item pe-2">
<button id="btnadd" class="btn btn-primary btn-sm">Add</button> <button id="btnadd" class="btn btn-primary btn-sm">Add</button>
......
...@@ -9,7 +9,7 @@ uses ...@@ -9,7 +9,7 @@ uses
WEBLib.Forms, WEBLib.Dialogs, WEBLib.Menus, WEBLib.ExtCtrls, WEBLib.StdCtrls, WEBLib.Forms, WEBLib.Dialogs, WEBLib.Menus, WEBLib.ExtCtrls, WEBLib.StdCtrls,
WEBLib.JSON, Auth.Service, XData.Web.Client, WebLib.Storage, WEBLib.JSON, Auth.Service, XData.Web.Client, WebLib.Storage,
ConnectionModule, App.Types, Vcl.StdCtrls, Vcl.Controls, WEBLib.DBCtrls, ConnectionModule, App.Types, Vcl.StdCtrls, Vcl.Controls, WEBLib.DBCtrls,
Data.DB, XData.Web.JsonDataset, XData.Web.Dataset, WEBLib.DB, WEBLib.Grids; Data.DB, XData.Web.JsonDataset, XData.Web.Dataset, WEBLib.DB, WEBLib.Grids, VCL.Forms;
type type
TFViewAddCustomer = class(TWebForm) TFViewAddCustomer = class(TWebForm)
...@@ -29,9 +29,6 @@ type ...@@ -29,9 +29,6 @@ type
btnDelete: TWebButton; btnDelete: TWebButton;
btnClose: TWebButton; btnClose: TWebButton;
btnEdit: TWebButton; btnEdit: TWebButton;
pnlMessage: TWebPanel;
lblMessage: TWebLabel;
btnCloseNotification: TWebButton;
XDataWebClient1: TXDataWebClient; XDataWebClient1: TXDataWebClient;
WebDataSource1: TWebDataSource; WebDataSource1: TWebDataSource;
XDataWebDataSet1: TXDataWebDataSet; XDataWebDataSet1: TXDataWebDataSet;
...@@ -83,7 +80,6 @@ type ...@@ -83,7 +80,6 @@ type
XDataWebDataSet1REP_USER_ID: TStringField; XDataWebDataSet1REP_USER_ID: TStringField;
xdwdsUsersfull_name: TStringField; xdwdsUsersfull_name: TStringField;
procedure WebFormShow(Sender: TObject); procedure WebFormShow(Sender: TObject);
procedure btnCloseNotificationClick(Sender: TObject);
procedure btnSaveClick(Sender: TObject); procedure btnSaveClick(Sender: TObject);
procedure btnCancelClick(Sender: TObject); procedure btnCancelClick(Sender: TObject);
procedure xdwdsShipToAfterEdit(DataSet: TDataSet); procedure xdwdsShipToAfterEdit(DataSet: TDataSet);
...@@ -92,7 +88,6 @@ type ...@@ -92,7 +88,6 @@ type
procedure btnEditClick(Sender: TObject); procedure btnEditClick(Sender: TObject);
procedure wdbtcAddressesDblClickCell(Sender: TObject; ACol, ARow: Integer); procedure wdbtcAddressesDblClickCell(Sender: TObject; ACol, ARow: Integer);
procedure btnClearClick(Sender: TObject); procedure btnClearClick(Sender: TObject);
procedure memoAddressBlockChange(Sender: TObject);
procedure AddressEditMode(); procedure AddressEditMode();
procedure edtShippingAddressChange(Sender: TObject); procedure edtShippingAddressChange(Sender: TObject);
procedure btnAddClick(Sender: TObject); procedure btnAddClick(Sender: TObject);
...@@ -105,9 +100,6 @@ type ...@@ -105,9 +100,6 @@ type
procedure btnShipDeleteClick(Sender: TObject); procedure btnShipDeleteClick(Sender: TObject);
private private
{ Private declarations } { Private declarations }
procedure HideNotification();
procedure ShowNotification(Notification: string);
procedure ViewMode(); procedure ViewMode();
procedure EditMode(); procedure EditMode();
[async] procedure GetCustomer(); [async] procedure GetCustomer();
...@@ -159,6 +151,7 @@ begin ...@@ -159,6 +151,7 @@ begin
newform.Caption := 'Select Customer and Order Type'; newform.Caption := 'Select Customer and Order Type';
newForm.Popup := True; newForm.Popup := True;
newForm.Border := fbDialog; newForm.Border := fbDialog;
newForm.Position := poScreenCenter;
// used to manage Back button handling to close subform // used to manage Back button handling to close subform
window.location.hash := 'subform'; window.location.hash := 'subform';
...@@ -180,7 +173,7 @@ begin ...@@ -180,7 +173,7 @@ begin
Response := await(XDataWebClient1.RawInvokeAsync('ILookupService.DelShippingAddress', Response := await(XDataWebClient1.RawInvokeAsync('ILookupService.DelShippingAddress',
[xdwdsShipTo.FieldByName('ship_id').AsString, customerID])); [xdwdsShipTo.FieldByName('ship_id').AsString, customerID]));
notification := TJSObject(Response.Result); notification := TJSObject(Response.Result);
ShowNotification(string(notification['status'])); ShowToast(string(notification['status']));
xdwdsShipTo.Close; xdwdsShipTo.Close;
xdwdsShipTo.SetJSONData(notification['ADDRESS']); xdwdsShipTo.SetJSONData(notification['ADDRESS']);
xdwdsShipTo.Open; xdwdsShipTo.Open;
...@@ -222,7 +215,7 @@ begin ...@@ -222,7 +215,7 @@ begin
[AddressJSON.ToString])); [AddressJSON.ToString]));
notification := TJSObject(Response.Result); notification := TJSObject(Response.Result);
ShowNotification(string(notification['status'])); ShowToast(string(notification['status']));
xdwdsShipTo.Close; xdwdsShipTo.Close;
xdwdsShipTo.SetJSONData(notification['ADDRESS']); xdwdsShipTo.SetJSONData(notification['ADDRESS']);
xdwdsShipTo.Open; xdwdsShipTo.Open;
...@@ -241,8 +234,16 @@ begin ...@@ -241,8 +234,16 @@ begin
document.getElementById('btn_confirm_cancel').innerText := 'No'; document.getElementById('btn_confirm_cancel').innerText := 'No';
document.getElementById('btn_confirm_delete').innerText := 'Yes'; document.getElementById('btn_confirm_delete').innerText := 'Yes';
asm asm
var confirmationModal = new bootstrap.Modal(document.getElementById('confirmation_modal'), { var modal = document.getElementById('confirmation_modal');
keyboard: false });
// Ensure modal is a direct child of <body> to avoid z-index/backdrop issues
if (modal && modal.parentNode !== document.body) {
document.body.appendChild(modal);
}
var confirmationModal = new bootstrap.Modal(modal, {
keyboard: false
});
confirmationModal.show(); confirmationModal.show();
end; end;
end; end;
...@@ -259,11 +260,6 @@ begin ...@@ -259,11 +260,6 @@ begin
FViewMain.ShowForm(TFViewCustomers) FViewMain.ShowForm(TFViewCustomers)
end; end;
procedure TFViewAddCustomer.btnCloseNotificationClick(Sender: TObject);
// Closes a Notification.
begin
HideNotification();
end;
procedure TFViewAddCustomer.btnDeleteClick(Sender: TObject); procedure TFViewAddCustomer.btnDeleteClick(Sender: TObject);
// Eventually will delete customers after a confirmation // Eventually will delete customers after a confirmation
...@@ -460,7 +456,7 @@ begin ...@@ -460,7 +456,7 @@ begin
edtCustomerID.Text := CustomerID; edtCustomerID.Text := CustomerID;
ShowNotification(msg); ShowToast(msg);
//TODO update the BILL_ADDRESS_BLOCK memo after saving. //TODO update the BILL_ADDRESS_BLOCK memo after saving.
...@@ -646,10 +642,10 @@ begin ...@@ -646,10 +642,10 @@ begin
else else
mode := 'EDIT'; mode := 'EDIT';
if notification = '' then if notification <> '' then
hideNotification() begin
else showToast(notification);
showNotification(notification); end;
if mode = 'ADD' then if mode = 'ADD' then
EditMode() EditMode()
...@@ -672,43 +668,6 @@ begin ...@@ -672,43 +668,6 @@ begin
EditMode(); EditMode();
end; end;
procedure TFViewAddCustomer.HideNotification;
begin
pnlMessage.ElementHandle.hidden := True;
end;
procedure TFViewAddCustomer.memoAddressBlockChange(Sender: TObject);
begin
EditMode();
end;
procedure TFViewAddCustomer.ShowNotification(Notification: string);
var
splitNotification: TArray<string>;
begin
if Notification <> '' then
begin
splitNotification := Notification.Split([':']);
if(splitNotification[0] = 'Success') then
begin
asm
var messageDiv = document.getElementById('view.login.message');
messageDiv.classList.remove('alert-danger');
messageDiv.classList.add('alert-success');
end;
end
else
begin
asm
var messageDiv = document.getElementById('view.login.message');
messageDiv.classList.remove('alert-success');
messageDiv.classList.add('alert-danger');
end;
end;
lblMessage.Caption := splitNotification[1];
pnlMessage.ElementHandle.hidden := False;
end;
end;
procedure TFViewAddCustomer.tmrReturnTimer(Sender: TObject); procedure TFViewAddCustomer.tmrReturnTimer(Sender: TObject);
// Timer to returnto the customer page because it takes slightly too long to // Timer to returnto the customer page because it takes slightly too long to
......
...@@ -175,10 +175,10 @@ begin ...@@ -175,10 +175,10 @@ begin
Exit(''); Exit('');
Result := ''; Result := '';
asm asm
var Token = AToken.split('.'); const parts = AToken.split('.');
if (Token.length = 3) { if (parts.length === 3) { // <- strict compare
Result = Token[1]; // JWTs use url-safe base64; convert before atob
Result = atob(Result); Result = atob(parts[1].replace(/-/g,'+').replace(/_/g,'/'));
} }
end; end;
end; end;
......
...@@ -13,6 +13,7 @@ procedure ShowErrorModal(msg: string); ...@@ -13,6 +13,7 @@ procedure ShowErrorModal(msg: string);
function CalculateAge(DateOfBirth: TDateTime): Integer; function CalculateAge(DateOfBirth: TDateTime): Integer;
function FormatPhoneNumber(PhoneNumber: string): string; function FormatPhoneNumber(PhoneNumber: string): string;
procedure ApplyReportTitle(CurrentReportType: string); procedure ApplyReportTitle(CurrentReportType: string);
procedure ShowToast(const MessageText: string; const ToastType: string = 'success');
// function FormatDollarValue(ValueStr: string): string; // function FormatDollarValue(ValueStr: string): string;
...@@ -155,6 +156,64 @@ begin ...@@ -155,6 +156,64 @@ begin
end; end;
procedure ShowToast(const MessageText: string; const ToastType: string = 'success');
var
ParsedText, ToastKind, MsgPrefix: string;
Parts: TArray<string>;
begin
ParsedText := MessageText.Trim;
ToastKind := ToastType.ToLower;
// Check for "Success:" or "Failure:" at the start of message
if ParsedText.Contains(':') then
begin
Parts := ParsedText.Split([':'], 2);
MsgPrefix := Parts[0].Trim.ToLower;
if (MsgPrefix = 'success') or (MsgPrefix = 'failure') then
begin
ParsedText := Parts[1].Trim;
if MsgPrefix = 'success' then
ToastKind := 'success'
else
ToastKind := 'danger';
end;
end;
asm
var toastEl = document.getElementById('bootstrapToast');
var toastBody = document.getElementById('bootstrapToastBody');
if (!toastEl || !toastBody) return;
toastBody.innerText = ParsedText;
toastEl.classList.remove('bg-success', 'bg-danger', 'bg-warning', 'bg-info');
switch (ToastKind) {
case 'danger':
toastEl.classList.add('bg-danger');
break;
case 'warning':
toastEl.classList.add('bg-warning');
break;
case 'info':
toastEl.classList.add('bg-info');
break;
default:
toastEl.classList.add('bg-success');
}
var toast = new bootstrap.Toast(toastEl, { delay: 2500 });
toast.show();
end;
end;
procedure ApplyReportTitle(CurrentReportType: string); procedure ApplyReportTitle(CurrentReportType: string);
var var
CrimeTitleElement: TJSHTMLElement; CrimeTitleElement: TJSHTMLElement;
......
<div class="container h-100 d-flex flex-column mt-0" style="max-width: 100%; padding-bottom: 0;"> <div class="container h-100 d-flex flex-column mt-0" style="max-width: 100%; padding-bottom: 0;">
<!-- Alert Section -->
<div class="row">
<div class=col-sm>
<div id="view.login.message" class="alert alert-danger">
<button id="view.login.message.button" type="button" class="btn-close" aria-label="Close"></button>
<span id="view.login.message.label"></span>
</div>
</div>
</div>
<!-- Actions Row --> <!-- Actions Row -->
<div class="row mt-3 justify-content-center align-items-end"> <div class="row mt-3 justify-content-center align-items-end">
<div class="col-auto"> <div class="col-auto">
......
...@@ -13,7 +13,7 @@ uses ...@@ -13,7 +13,7 @@ uses
WEBLib.Grids, VCL.TMSFNCTypes, VCL.TMSFNCUtils, VCL.TMSFNCGraphics, WEBLib.Grids, VCL.TMSFNCTypes, VCL.TMSFNCUtils, VCL.TMSFNCGraphics,
VCL.TMSFNCGraphicsTypes, VCL.TMSFNCGridCell, VCL.TMSFNCGridOptions, VCL.TMSFNCGraphicsTypes, VCL.TMSFNCGridCell, VCL.TMSFNCGridOptions,
VCL.TMSFNCCustomControl, VCL.TMSFNCCustomScrollControl, VCL.TMSFNCGridData, VCL.TMSFNCCustomControl, VCL.TMSFNCCustomScrollControl, VCL.TMSFNCGridData,
VCL.TMSFNCCustomGrid, VCL.TMSFNCGrid; VCL.TMSFNCCustomGrid, VCL.TMSFNCGrid, VCL.Forms;
type type
TFViewCustomers = class(TWebForm) TFViewCustomers = class(TWebForm)
...@@ -42,7 +42,6 @@ type ...@@ -42,7 +42,6 @@ type
[async] procedure GetCustomers(searchOptions: string); [async] procedure GetCustomers(searchOptions: string);
function GenerateSearchOptions(): string; function GenerateSearchOptions(): string;
procedure HideNotification(); procedure HideNotification();
procedure ShowNotification(Notification: string);
procedure ShowSelectCustomerForm(); procedure ShowSelectCustomerForm();
var var
...@@ -75,6 +74,7 @@ begin ...@@ -75,6 +74,7 @@ begin
newform.Caption := 'Select Customer and Order Type'; newform.Caption := 'Select Customer and Order Type';
newForm.Popup := True; newForm.Popup := True;
newForm.Border := fbDialog; newForm.Border := fbDialog;
newForm.Position := poScreenCenter;
// used to manage Back button handling to close subform // used to manage Back button handling to close subform
window.location.hash := 'subform'; window.location.hash := 'subform';
...@@ -173,34 +173,6 @@ begin ...@@ -173,34 +173,6 @@ begin
end; end;
procedure TFViewCustomers.ShowNotification(Notification: string);
var
splitNotification: TArray<string>;
begin
if Notification <> '' then
begin
splitNotification := Notification.Split([':']);
if(splitNotification[0] = 'Success') then
begin
asm
var messageDiv = document.getElementById('view.login.message');
messageDiv.classList.remove('alert-danger');
messageDiv.classList.add('alert-success');
end;
end
else
begin
asm
var messageDiv = document.getElementById('view.login.message');
messageDiv.classList.remove('alert-success');
messageDiv.classList.add('alert-danger');
end;
end;
lblMessage.Caption := splitNotification[1];
pnlMessage.ElementHandle.hidden := False;
end;
end;
procedure TFViewCustomers.wdbtcCustomersDblClickCell(Sender: TObject; ACol, procedure TFViewCustomers.wdbtcCustomersDblClickCell(Sender: TObject; ACol,
ARow: Integer); ARow: Integer);
begin begin
......
...@@ -108,6 +108,7 @@ object FViewEditUser: TFViewEditUser ...@@ -108,6 +108,7 @@ object FViewEditUser: TFViewEditUser
ElementID = 'edtconfirmpassword' ElementID = 'edtconfirmpassword'
HeightPercent = 100.000000000000000000 HeightPercent = 100.000000000000000000
WidthPercent = 100.000000000000000000 WidthPercent = 100.000000000000000000
OnChange = edtConfirmPasswordChange
end end
object edtEmail: TWebEdit object edtEmail: TWebEdit
Left = 96 Left = 96
...@@ -128,6 +129,7 @@ object FViewEditUser: TFViewEditUser ...@@ -128,6 +129,7 @@ object FViewEditUser: TFViewEditUser
ElementID = 'edtpassword' ElementID = 'edtpassword'
HeightPercent = 100.000000000000000000 HeightPercent = 100.000000000000000000
WidthPercent = 100.000000000000000000 WidthPercent = 100.000000000000000000
OnChange = edtPasswordChange
end end
object btnConfirm: TWebButton object btnConfirm: TWebButton
Left = 96 Left = 96
...@@ -187,48 +189,6 @@ object FViewEditUser: TFViewEditUser ...@@ -187,48 +189,6 @@ object FViewEditUser: TFViewEditUser
WidthPercent = 100.000000000000000000 WidthPercent = 100.000000000000000000
OnClick = btnCancelClick OnClick = btnCancelClick
end end
object btnConfirmChanges: TWebButton
Left = 100
Top = 330
Width = 96
Height = 25
Caption = 'Confirm'
ChildOrder = 16
ElementID = 'btn_confirm_changes'
HeightPercent = 100.000000000000000000
WidthPercent = 100.000000000000000000
OnClick = btnConfirmChangesClick
end
object pnlMessage: TWebPanel
Left = 482
Top = 4
Width = 121
Height = 33
ElementID = 'view.login.message'
ChildOrder = 17
TabOrder = 8
object lblMessage: TWebLabel
Left = 16
Top = 11
Width = 46
Height = 15
Caption = 'Message'
ElementID = 'view.login.message.label'
HeightPercent = 100.000000000000000000
WidthPercent = 100.000000000000000000
end
object btnCloseNotification: TWebButton
Left = 96
Top = 3
Width = 22
Height = 25
ChildOrder = 1
ElementID = 'view.login.message.button'
HeightPercent = 100.000000000000000000
WidthPercent = 100.000000000000000000
OnClick = btnCloseNotificationClick
end
end
object cbStatus: TWebCheckBox object cbStatus: TWebCheckBox
Left = 96 Left = 96
Top = 162 Top = 162
......
<div class="row"> <div class="container">
<div class="col-12">
<div class="container mt-4"> <!-- Edit-User form -->
<div class="row justify-content-center"> <div class="row">
<div class="col-12 col-md-8"> <div class="col-lg-10 col-xl-8 mx-auto">
<div class="row"> <form id="edituserform" class="row g-3 needs-validation" novalidate>
<div class=col-sm>
<div id="view.login.message" class="alert alert-danger"> <div class="col-md-6">
<button id="view.login.message.button" type="button" class="btn-close" aria-label="Close"></button> <label id="lblfullname" for="edtfullname" class="form-label">Full&nbsp;Name</label>
<span id="view.login.message.label"></span> <input id="edtfullname" class="form-control" required>
</div> <div class="invalid-feedback">Full Name is required.</div>
</div>
</div>
<form class="form-inline">
<div class="row">
<div class="col-sm">
<label class= 'pe-2' style="font-weight: 700;font-size: 15px;"id="lblfullname">Full Name:</label>
<input id="edtfullname" class= "form-control input-sm" width='50%'/>
</div>
<div class="col-sm">
<label class= 'pe-2' style="font-weight: 700;font-size: 15px"id="lblusername">Username:</label>
<input id="edtusername" class="form-control input-sm" width='50%'>
</div>
</div>
</form>
<form class="form-inline">
<div class="row">
<div class="col-sm">
<label class='pe-2' style="font-weight: 700;font-size: 15px;"id="lblpassword">Password:</label>
<input id="edtpassword" class= "form-control input-sm" width='50%'/>
</div>
<div class="col-sm">
<label class= 'pe-2' style="font-weight: 700;font-size: 15px"id="lblconfirm">Confirm Password:</label>
<input class="form-control input-sm" id="edtconfirmpassword">
</div>
</div>
</form>
<form class="form-inline">
<div class="row">
<div class="col-sm">
<label class='pe-2' style="font-weight: 700;font-size: 15px;" id="lblemail">Email Address:</label>
<input id="edtemail" class= "form-control input-sm" width='50%'/>
</div>
<div class="col-sm">
<label class= 'pe-2' style="font-weight: 700;font-size: 15px"id="lblQB">Quickbook ID:</label>
<input class="form-control input-sm" id="edtQB">
</div>
</div>
</form>
<div class="row">
<div class="col-6">
<label class='pe-2' style="font-weight: 700;font-size: 15px;" id="lblrights">System Rights:</label>
<input id="edtrights" class= "form-control input-sm" width='50%'/>
</div>
</div>
<div class="row">
<div class="col-sm py-3">
<label class= 'pe-2' style="font-weight: 700;font-size: 15px"id="lblaccess">Access Type:</label>
<select class="custom-select-large" id="cbaccess" style="font-size: 1.00rem;"></select>
</div>
</div>
<div class="row">
<div class="col-sm">
<form class='form-inline'>
<div class="col-sm">
<div class="form-cells"><input type="checkbox" id="cbstatus"></div>
<div class="form-cells ps-1 py-2"><label style="font-weight: 700;font-size: 15px" id="lblactive">Active></label></div>
</div>
</form>
</div>
<div class="col-sm-12 py-2">
<button class="py-2" id="btnconfirm" style="font-weight: 700;font-size: 15px";>Confirm</button>
<button class="py-2" id="btncancel" style="font-weight: 700;font-size: 15px";>Cancel</button>
</div>
</div>
</div>
</div>
</div> </div>
<div class="col-md-6">
<label id="lblusername" for="edtusername" class="form-label">Username</label>
<input id="edtusername" class="form-control" required>
<div class="invalid-feedback">Username is required.</div>
</div>
<div class="col-md-6">
<label id="lblpassword" for="edtpassword" class="form-label">Password</label>
<input id="edtpassword" type="password" class="form-control" required>
<div class="invalid-feedback">Passwords must match.</div>
</div>
<div class="col-md-6">
<label id="lblconfirm" for="edtconfirmpassword" class="form-label">Confirm&nbsp;Password</label>
<input id="edtconfirmpassword" type="password" class="form-control" required disabled>
<div class="invalid-feedback">Passwords must match.</div>
</div>
<div class="col-md-6">
<label id="lblemail" for="edtemail" class="form-label">Email&nbsp;Address</label>
<input id="edtemail" type="email" class="form-control" required>
<div class="invalid-feedback">Valid email is required.</div>
</div>
<div class="col-md-6">
<label id="lblQB" for="edtQB" class="form-label">QuickBooks&nbsp;ID</label>
<input id="edtQB" class="form-control">
</div>
<div class="col-md-6">
<label id="lblrights" for="edtrights" class="form-label">System&nbsp;Rights</label>
<input id="edtrights" class="form-control">
</div>
<div class="col-md-6">
<label id="lblaccess" for="cbaccess" class="form-label">Access&nbsp;Type</label>
<select id="cbaccess" class="form-select" required>
<option selected disabled value="">Choose...</option>
<option value="ALL">All</option>
<option value="LIMITED">Limited</option>
</select>
<div class="invalid-feedback">Please select an access type.</div>
</div>
<div class="col-md-6">
<div class="form-check pt-2">
<input id="cbstatus" class="form-check-input" type="checkbox">
<label id="lblactive" for="cbstatus" class="form-check-label">Active</label>
</div>
</div>
<div class="d-flex gap-2 mt-4">
<button id="btnconfirm" type="button" class="btn btn-primary flex-grow-1">
Confirm
</button>
<button id="btncancel" type="button" class="btn btn-outline-secondary flex-grow-1">
Cancel
</button>
</div>
</form>
</div> </div>
</div>
</div> </div>
<!-- Confirmation modal -->
<div class="modal fade" id="confirmation_modal" tabindex="-1" aria-labelledby="confirmation_modal_label" aria-hidden="true"> <div class="modal fade" id="confirmation_modal" tabindex="-1" aria-labelledby="confirmation_modal_label" aria-hidden="true">
<div class="modal-dialog"> <div class="modal-dialog">
<div class="modal-content"> <div class="modal-content">
...@@ -95,3 +94,4 @@ ...@@ -95,3 +94,4 @@
</div> </div>
</div> </div>
</div> </div>
...@@ -26,10 +26,6 @@ type ...@@ -26,10 +26,6 @@ type
XDataWebClient1: TXDataWebClient; XDataWebClient1: TXDataWebClient;
btnCancel: TWebButton; btnCancel: TWebButton;
WebTimer1: TWebTimer; WebTimer1: TWebTimer;
btnConfirmChanges: TWebButton;
pnlMessage: TWebPanel;
lblMessage: TWebLabel;
btnCloseNotification: TWebButton;
lblactive: TWebLabel; lblactive: TWebLabel;
cbStatus: TWebCheckBox; cbStatus: TWebCheckBox;
lblRights: TWebLabel; lblRights: TWebLabel;
...@@ -42,8 +38,8 @@ type ...@@ -42,8 +38,8 @@ type
procedure btnConfirmClick(Sender: TObject); procedure btnConfirmClick(Sender: TObject);
procedure btnCancelClick(Sender: TObject); procedure btnCancelClick(Sender: TObject);
procedure WebTimer1Timer(Sender: TObject); procedure WebTimer1Timer(Sender: TObject);
procedure btnConfirmChangesClick(Sender: TObject); procedure edtPasswordChange(Sender: TObject);
procedure btnCloseNotificationClick(Sender: TObject); procedure edtConfirmPasswordChange(Sender: TObject);
private private
{ Private declarations } { Private declarations }
FMessage: string; FMessage: string;
...@@ -59,8 +55,7 @@ type ...@@ -59,8 +55,7 @@ type
QB: string; QB: string;
[async] procedure EditUser(); [async] procedure EditUser();
[async] function AddUser(): string; [async] function AddUser(): string;
procedure HideNotification(); procedure ValidatePasswords;
procedure ShowNotification(notification: string);
public public
{ Public declarations } { Public declarations }
Info: string; Info: string;
...@@ -84,24 +79,10 @@ Utils; ...@@ -84,24 +79,10 @@ Utils;
procedure TFViewEditUser.btnCancelClick(Sender: TObject); procedure TFViewEditUser.btnCancelClick(Sender: TObject);
// Cancels the edit or addition // Cancels the edit or addition
begin begin
Info := 'Failure:Changes discarded!'; Info := 'Failure: Changes discarded!';
FViewMain.ShowUserForm(Info); FViewMain.ShowUserForm(Info);
end; end;
procedure TFViewEditUser.btnCloseNotificationClick(Sender: TObject);
begin
HideNotification;
end;
procedure TFViewEditUSer.btnConfirmChangesClick(Sender: TObject);
begin
if Mode = 'Edit' then
EditUser()
else
AddUser();
WebTimer1.Enabled := true;
Utils.ShowSpinner('spinner');
end;
function TFViewEditUser.AddUser: string; function TFViewEditUser.AddUser: string;
// Sends UserInfo over to the server so it can be added to the database // Sends UserInfo over to the server so it can be added to the database
...@@ -131,20 +112,6 @@ begin ...@@ -131,20 +112,6 @@ begin
end; end;
procedure TFViewEditUser.HideNotification;
begin
pnlMessage.ElementHandle.hidden := True;
end;
procedure TFViewEditUser.ShowNotification(Notification: string);
begin
if Notification <> '' then
begin
lblMessage.Caption := Notification;
pnlMessage.ElementHandle.hidden := False;
end;
end;
procedure TFViewEditUser.EditUser(); procedure TFViewEditUser.EditUser();
// Sends EditOptions over to the server so the given user can be editted // Sends EditOptions over to the server so the given user can be editted
var var
...@@ -172,6 +139,16 @@ begin ...@@ -172,6 +139,16 @@ begin
end; end;
procedure TFViewEditUser.edtConfirmPasswordChange(Sender: TObject);
begin
ValidatePasswords;
end;
procedure TFViewEditUser.edtPasswordChange(Sender: TObject);
begin
ValidatePasswords;
end;
class function TFViewEditUser.CreateForm(AElementID, Mode, Username, Password, Name, Status, Email, class function TFViewEditUser.CreateForm(AElementID, Mode, Username, Password, Name, Status, Email,
Access, Rights, Perspective, QB: string): TWebForm; Access, Rights, Perspective, QB: string): TWebForm;
// Autofills known information about a user on create // Autofills known information about a user on create
...@@ -199,9 +176,7 @@ procedure TFViewEditUser.WebFormCreate(Sender: TObject); ...@@ -199,9 +176,7 @@ procedure TFViewEditUser.WebFormCreate(Sender: TObject);
// Autofills known information about a user on create // Autofills known information about a user on create
begin begin
if FMessage <> '' then if FMessage <> '' then
ShowNotification(FMessage) ShowToast(FMessage);
else
HideNotification;
edtUsername.Text := Username; edtUsername.Text := Username;
edtFullName.Text := FullName; edtFullName.Text := FullName;
if Mode = 'Edit' then if Mode = 'Edit' then
...@@ -226,132 +201,79 @@ begin ...@@ -226,132 +201,79 @@ begin
FViewMain.ShowUserForm(Info); FViewMain.ShowUserForm(Info);
end end
else else
showNotification(Info); showToast(Info);
console.log('Info at Timer:' + Info); console.log('Info at Timer:' + Info);
end; end;
procedure TFViewEditUser.btnConfirmClick(Sender: TObject); procedure TFViewEditUser.btnConfirmClick(Sender: TObject);
// Confirms the edit or addition
var var
checkString: string; FormEl: TJSHTMLFormElement;
charIndex: integer;
phoneNum: string;
begin begin
{ checkString := edtFullName.Text + edtUsername.Text + edtPassword.Text FormEl := TJSHTMLFormElement(document.getElementById('edituserform'));
+ edtConfirmPassword.Text + edtPhoneNumber.Text + edtEmail.Text;
if string(edtFullName.Text).IsEmpty then
begin
ShowNotification('Full Name field is blank!');
exit;
end;
if string(edtUsername.Text).IsEmpty then
begin
ShowNotification('Username field is blank!');
exit;
end;
if string(edtPassword.Text).IsEmpty then
begin
ShowNotification('Password field is blank!');
exit;
end;
if string(edtConfirmPassword.Text).IsEmpty then
begin
ShowNotification('Please confirm your password!');
exit;
end;
if string(edtPhoneNumber.Text).IsEmpty then if not FormEl.checkValidity then
begin begin
ShowNotification('Phone Number field is blank!'); FormEl.classList.add('was-validated');
exit; Exit;
end; end;
if string(edtEmail.Text).IsEmpty then Utils.ShowSpinner('spinner');
begin
ShowNotification('Email field is blank!');
exit;
end;
if checkString.Contains('&') then if Mode = 'Edit' then
begin EditUser
ShowNotification('No fields may contain "&&"!'); else
exit; AddUser;
end;
if string(edtEmail.Text).Contains('@') = false then WebTimer1.Enabled := True;
begin end;
ShowNotification('Please enter a valid email address');
exit;
end;
if (length(string(edtEmail.Text).Split(['@'])) <> 2) or (string(edtEmail.text).CountChar('@') > 1) then
begin
ShowNotification('Please enter a valid email address');
exit;
end;
phoneNum := edtPhoneNumber.Text; procedure TFViewEditUser.ValidatePasswords;
var
Pwd, Confirm: string;
PwdInput, ConfirmInput: TJSHTMLInputElement;
begin
PwdInput := TJSHTMLInputElement(edtPassword.ElementHandle);
ConfirmInput := TJSHTMLInputElement(edtConfirmPassword.ElementHandle);
if (not phoneNum.Contains('(')) or (not phoneNum.Contains(')')) or (not phoneNum.Contains('-')) then Pwd := PwdInput.value.Trim;
begin Confirm := ConfirmInput.value.Trim;
ShowNotification('Please enter a valid phone number');
exit;
end;
if (phoneNum.CountChar('(') <> 1) or (phoneNum.CountChar(')') <> 1) or (phoneNum.CountChar('-') <> 1) or (phoneNum.CountChar(' ') > 1) then // Disable confirm until password exists
if Pwd = '' then
begin begin
ShowNotification('Please enter a valid phone number'); ConfirmInput.disabled := True;
exit; ConfirmInput.value := '';
end; ConfirmInput.setCustomValidity('');
ConfirmInput.classList.remove('is-invalid');
phoneNum := phoneNum.Replace('(', ''); ConfirmInput.classList.remove('is-valid');
phoneNum := phoneNum.Replace(')', ''); end
phoneNum := phoneNum.Replace('-', ''); else
phoneNum := phoneNum.Replace(' ', '');
if(length(phoneNum) <> 10) then
begin begin
ShowNotification('Please enter a valid phone number'); ConfirmInput.disabled := False;
exit;
end;
for CharIndex := 1 to Length(phoneNum) do // Live match check
begin if Confirm = '' then
if not (phoneNum[CharIndex] in ['0' .. '9']) then begin
ConfirmInput.setCustomValidity('');
ConfirmInput.classList.remove('is-invalid');
ConfirmInput.classList.remove('is-valid');
end
else if Confirm = Pwd then
begin
ConfirmInput.setCustomValidity('');
ConfirmInput.classList.add('is-valid');
ConfirmInput.classList.remove('is-invalid');
end
else
begin begin
console.log('here'); ConfirmInput.setCustomValidity('Passwords must match');
ShowNotification('Please enter a valid phone number'); ConfirmInput.classList.add('is-invalid');
exit; ConfirmInput.classList.remove('is-valid');
end; end;
end; end;
if edtPassword.Text <> edtConfirmPassword.Text then
begin
ShowNotification('Passwords must match!');
exit;
end;
if (length(edtPassword.Text) > 20) or (length(edtPassword.Text) < 6) then
begin
ShowNotification('Passwords must be between 6-20 characters!');
exit;
end;
}
asm
var modal = document.getElementById('confirmation_modal');
// ensure the modal is directly under <body>
if (modal && modal.parentNode !== document.body) {
document.body.appendChild(modal);
}
var bsModal = new bootstrap.Modal(modal, {
keyboard: false
});
bsModal.show();
end;
end; end;
end. end.
...@@ -50,7 +50,6 @@ object FViewItems: TFViewItems ...@@ -50,7 +50,6 @@ object FViewItems: TFViewItems
ChildOrder = 7 ChildOrder = 7
ElementID = 'btnadd' ElementID = 'btnadd'
ElementFont = efCSS ElementFont = efCSS
Enabled = False
HeightStyle = ssAuto HeightStyle = ssAuto
HeightPercent = 100.000000000000000000 HeightPercent = 100.000000000000000000
WidthPercent = 100.000000000000000000 WidthPercent = 100.000000000000000000
...@@ -97,51 +96,6 @@ object FViewItems: TFViewItems ...@@ -97,51 +96,6 @@ object FViewItems: TFViewItems
HeightPercent = 100.000000000000000000 HeightPercent = 100.000000000000000000
WidthPercent = 100.000000000000000000 WidthPercent = 100.000000000000000000
end end
object pnlMessage: TWebPanel
Left = 0
Top = 27
Width = 121
Height = 33
ElementClassName = 'card'
ElementID = 'view.login.message'
ChildOrder = 5
ElementBodyClassName = 'card-body'
ElementFont = efCSS
ElementPosition = epRelative
Role = 'null'
TabOrder = 5
Visible = False
object lblMessage: TWebLabel
Left = 28
Top = 9
Width = 42
Height = 13
Caption = 'Message'
ElementID = 'view.login.message.label'
ElementFont = efCSS
ElementPosition = epRelative
HeightStyle = ssAuto
HeightPercent = 100.000000000000000000
WidthPercent = 100.000000000000000000
end
object btnCloseNotification: TWebButton
Left = 96
Top = 3
Width = 22
Height = 25
ChildOrder = 1
ElementClassName = 'btn btn-light'
ElementID = 'view.login.message.button'
ElementFont = efCSS
ElementPosition = epRelative
HeightStyle = ssAuto
HeightPercent = 100.000000000000000000
Role = 'null'
WidthStyle = ssAuto
WidthPercent = 100.000000000000000000
OnClick = btnCloseNotificationClick
end
end
object btnSave: TWebButton object btnSave: TWebButton
Left = 565 Left = 565
Top = 228 Top = 228
......
<nav class="navbar navbar-expand navbar-light bg-light sticky-top" style="z-index: 100;"> <nav class="navbar navbar-expand navbar-light bg-light sticky-top" style="z-index: 100;">
<div class="container-fluid ps-0"> <div class="container-fluid ps-0">
<div id="view.login.message" class="alert alert-danger"
style="padding: 0.25rem 0.5rem; font-size: 0.875rem; line-height: 1.5; display: flex; align-items: center; margin: 0 0 0 60px; height: 32px; width: 400px;">
<button id="view.login.message.button" type="button" class="btn-close" aria-label="Close"></button>
<span id="view.login.message.label"></span>
</div>
<ul class="navbar-nav me-auto ps-2"> <ul class="navbar-nav me-auto ps-2">
<li class="nav-item pe-2"> <li class="nav-item pe-2">
<button id="btnadd" class="btn btn-primary btn-sm">Add</button> <button id="btnadd" class="btn btn-primary btn-sm">Add</button>
......
...@@ -24,9 +24,6 @@ type ...@@ -24,9 +24,6 @@ type
edtName: TWebEdit; edtName: TWebEdit;
edtDescription: TWebEdit; edtDescription: TWebEdit;
cbStatus: TWebCheckBox; cbStatus: TWebCheckBox;
pnlMessage: TWebPanel;
lblMessage: TWebLabel;
btnCloseNotification: TWebButton;
btnSave: TWebButton; btnSave: TWebButton;
btnCancel: TWebButton; btnCancel: TWebButton;
btnDelete: TWebButton; btnDelete: TWebButton;
...@@ -34,7 +31,6 @@ type ...@@ -34,7 +31,6 @@ type
procedure WebFormCreate(Sender: TObject); procedure WebFormCreate(Sender: TObject);
procedure btnAddClick(Sender: TObject); procedure btnAddClick(Sender: TObject);
procedure wcbPageSizeChange(Sender: TObject); procedure wcbPageSizeChange(Sender: TObject);
procedure btnCloseNotificationClick(Sender: TObject);
procedure btnEditClick(Sender: TObject); procedure btnEditClick(Sender: TObject);
procedure btnSaveClick(Sender: TObject); procedure btnSaveClick(Sender: TObject);
procedure btnDeleteClick(Sender: TObject); procedure btnDeleteClick(Sender: TObject);
...@@ -45,8 +41,6 @@ type ...@@ -45,8 +41,6 @@ type
procedure ClearTable(); procedure ClearTable();
procedure GeneratePagination(TotalPages: Integer); procedure GeneratePagination(TotalPages: Integer);
function GenerateSearchOptions(): string; function GenerateSearchOptions(): string;
procedure HideNotification();
procedure ShowNotification(Notification: string);
procedure ViewMode(); procedure ViewMode();
procedure EditMode(); procedure EditMode();
[async] procedure GetItems(searchOptions: string); [async] procedure GetItems(searchOptions: string);
...@@ -412,6 +406,7 @@ begin ...@@ -412,6 +406,7 @@ begin
newform.Caption := 'Select Customer and Order Type'; newform.Caption := 'Select Customer and Order Type';
newForm.Popup := True; newForm.Popup := True;
newForm.position:= poScreenCenter;
newForm.Border := fbDialog; newForm.Border := fbDialog;
// used to manage Back button handling to close subform // used to manage Back button handling to close subform
...@@ -427,64 +422,28 @@ end; ...@@ -427,64 +422,28 @@ end;
procedure TFViewItems.btnCancelClick(Sender: TObject); procedure TFViewItems.btnCancelClick(Sender: TObject);
begin begin
ShowMessage('Editting Items is not yet implemented'); ShowToast('Editing items is not yet implemented.', 'info');
end; end;
procedure TFViewItems.btnCloseNotificationClick(Sender: TObject);
begin
HideNotification();
end;
procedure TFViewItems.btnDeleteClick(Sender: TObject); procedure TFViewItems.btnDeleteClick(Sender: TObject);
begin begin
ShowMessage('Deleting Items is no yet implemented'); ShowToast('Deleting items is no yet implemented.', 'info');
end; end;
procedure TFViewItems.btnEditClick(Sender: TObject); procedure TFViewItems.btnEditClick(Sender: TObject);
begin begin
ShowMessage('Editting Items is not yet implemented'); ShowToast('Editing items is not yet implemented.', 'info');
//EditMode(); //EditMode();
end; end;
procedure TFViewItems.btnSaveClick(Sender: TObject); procedure TFViewItems.btnSaveClick(Sender: TObject);
//TODO implement editting items //TODO implement editting items
begin begin
ShowMessage('Editting Items is not yet implemented'); ShowToast('Editing items is not yet implemented.', 'info');
//ViewMode(); //ViewMode();
end; end;
procedure TFViewItems.ShowNotification(Notification: string);
var
splitNotification: TArray<string>;
begin
if Notification <> '' then
begin
splitNotification := Notification.Split([':']);
if(splitNotification[0] = 'Success') then
begin
asm
var messageDiv = document.getElementById('view.login.message');
messageDiv.classList.remove('alert-danger');
messageDiv.classList.add('alert-success');
end;
end
else
begin
asm
var messageDiv = document.getElementById('view.login.message');
messageDiv.classList.remove('alert-success');
messageDiv.classList.add('alert-danger');
end;
end;
lblMessage.Caption := splitNotification[1];
pnlMessage.ElementHandle.hidden := False;
end;
end;
procedure TFViewItems.HideNotification;
begin
pnlMessage.ElementHandle.hidden := True;
end;
procedure TFViewItems.AddItem(itemOptions: string); procedure TFViewItems.AddItem(itemOptions: string);
// adds an item to the database. // adds an item to the database.
......
...@@ -57,7 +57,7 @@ object FViewMain: TFViewMain ...@@ -57,7 +57,7 @@ object FViewMain: TFViewMain
end end
object lblAppTitle: TWebLabel object lblAppTitle: TWebLabel
Left = 57 Left = 57
Top = 31 Top = 33
Width = 75 Width = 75
Height = 14 Height = 14
Caption = 'Koehler-Gibson' Caption = 'Koehler-Gibson'
......
...@@ -47,7 +47,23 @@ ...@@ -47,7 +47,23 @@
</div> </div>
</div> </div>
</nav> </nav>
<!-- Toast wrapper directly under navbar -->
<div id="toast-wrapper"
class="position-fixed start-50 translate-middle-x mt-2"
style="z-index: 1080; top: 60px; min-width: 300px; max-width: 500px;">
<div id="bootstrapToast"
class="toast align-items-center text-white bg-success border-0 shadow"
role="alert" aria-live="assertive" aria-atomic="true">
<div class="d-flex">
<div class="toast-body" id="bootstrapToastBody">
Success message
</div>
<button type="button" class="btn-close btn-close-white me-2 m-auto"
data-bs-dismiss="toast" aria-label="Close"></button>
</div>
</div>
</div>
<div class="container-fluid"> <div class="container-fluid">
<div class="row"> <div class="row">
<div id="main.webpanel" class="col-12"></div> <div id="main.webpanel" class="col-12"></div>
...@@ -86,6 +102,28 @@ ...@@ -86,6 +102,28 @@
</div> </div>
</div> </div>
<div class="modal fade" id="confirmation_modal" tabindex="-1" aria-labelledby="confirmation_modal_label" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content shadow-lg">
<div class="modal-header">
<h5 class="modal-title" id="confirmation_modal_label">Confirm</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body fs-6 fw-bold" id="modal_body">
Are you sure you want to delete this order?
</div>
<div class="modal-footer justify-content-center">
<button type="button" class="btn btn-secondary me-3" data-bs-dismiss="modal" id="btn_confirm_cancel">Cancel</button>
<button type="button" class="btn btn-primary" data-bs-dismiss="modal" id="btn_confirm_delete">Delete</button>
</div>
</div>
</div>
</div>
<div class="position-fixed bottom-0 end-0 p-3" style="z-index: 1100">
</div>
......
...@@ -46,6 +46,8 @@ type ...@@ -46,6 +46,8 @@ type
//procedure EditUser( AParam, BParam, CParam, DParam, EParam: string); //procedure EditUser( AParam, BParam, CParam, DParam, EParam: string);
function GetUserInfo: string; function GetUserInfo: string;
procedure setActive(page: string); procedure setActive(page: string);
procedure ConfirmLogout;
procedure OnConfirmLogout(Event: TJSEvent);
public public
{ Public declarations } { Public declarations }
class procedure Display(LogoutProc: TLogoutProc); class procedure Display(LogoutProc: TLogoutProc);
...@@ -199,15 +201,55 @@ end; ...@@ -199,15 +201,55 @@ end;
procedure TFViewMain.mnuLogoutClick(Sender: TObject); procedure TFViewMain.mnuLogoutClick(Sender: TObject);
begin begin
FLogoutProc; ConfirmLogout;
end; end;
procedure TFViewMain.wllblLogoutClick(Sender: TObject); procedure TFViewMain.wllblLogoutClick(Sender: TObject);
begin begin
FLogoutProc; ConfirmLogout;
end; end;
procedure TFViewMain.ConfirmLogout;
var
yesBtn: TJSElement;
begin
document.getElementById('modal_body').innerHTML := 'Are you sure you want to log out?';
document.getElementById('btn_confirm_cancel').innerText := 'No';
document.getElementById('btn_confirm_delete').innerText := 'Yes';
asm
var modal = document.getElementById('confirmation_modal');
if (modal && modal.parentNode !== document.body) {
document.body.appendChild(modal);
}
end;
// Detach any existing click handler (optional cleanup if reused often)
yesBtn := document.getElementById('btn_confirm_delete');
if Assigned(yesBtn) then
begin
TJSElement(yesBtn).removeEventListener('click', @OnConfirmLogout);
TJSElement(yesBtn).addEventListener('click', @OnConfirmLogout);
end;
asm
var confirmationModal = new bootstrap.Modal(document.getElementById('confirmation_modal'), {
keyboard: false
});
confirmationModal.show();
end;
end;
procedure TFViewMain.OnConfirmLogout(Event: TJSEvent);
begin
if Assigned(FLogoutProc) then
FLogoutProc('');
end;
procedure TFViewMain.wllblUserProfileClick(Sender: TObject); procedure TFViewMain.wllblUserProfileClick(Sender: TObject);
begin begin
......
...@@ -99,41 +99,6 @@ object FOrderEntryCorrugated: TFOrderEntryCorrugated ...@@ -99,41 +99,6 @@ object FOrderEntryCorrugated: TFOrderEntryCorrugated
Visible = False Visible = False
WidthPercent = 100.000000000000000000 WidthPercent = 100.000000000000000000
end end
object pnlMessage: TWebPanel
Left = 324
Top = 19
Width = 121
Height = 33
ElementID = 'view.login.message'
ChildOrder = 5
ElementPosition = epRelative
Role = 'null'
TabOrder = 0
object lblMessage: TWebLabel
Left = 28
Top = 9
Width = 44
Height = 14
Caption = 'Message'
ElementID = 'view.login.message.label'
ElementPosition = epRelative
HeightPercent = 100.000000000000000000
WidthPercent = 100.000000000000000000
end
object btnCloseNotification: TWebButton
Left = 96
Top = 3
Width = 22
Height = 25
ChildOrder = 1
ElementID = 'view.login.message.button'
ElementPosition = epRelative
HeightPercent = 100.000000000000000000
Role = 'null'
WidthPercent = 100.000000000000000000
OnClick = btnCloseNotificationClick
end
end
object dtpOrderDate: TWebDateTimePicker object dtpOrderDate: TWebDateTimePicker
Left = 22 Left = 22
Top = 218 Top = 218
......
<nav class="navbar navbar-expand navbar-light bg-light border-light sticky-top" style="z-index: 100;"> <nav class="navbar navbar-expand navbar-light bg-light border-light sticky-top" style="z-index: 100;">
<div class="container-fluid ps-0"> <div class="container-fluid ps-0">
<div id="view.login.message" class="alert alert-danger"
style="padding: 0.25rem 0.5rem; font-size: 0.875rem; line-height: 1.5; display: flex; align-items: center; margin: 0 0 0 60px; height: 32px; width: 400px;">
<button id="view.login.message.button" type="button" class="btn-close" aria-label="Close"></button>
<span id="view.login.message.label"></span>
</div>
<ul class="navbar-nav me-auto ps-2"> <ul class="navbar-nav me-auto ps-2">
<li class="nav-item pe-2"> <li class="nav-item pe-2">
<button id="btnadd" class="btn btn-primary btn-sm">Add</button> <button id="btnadd" class="btn btn-primary btn-sm">Add</button>
......
...@@ -9,13 +9,10 @@ uses ...@@ -9,13 +9,10 @@ uses
WEBLib.Forms, WEBLib.Dialogs, WEBLib.Menus, WEBLib.ExtCtrls, WEBLib.StdCtrls, WEBLib.Forms, WEBLib.Dialogs, WEBLib.Menus, WEBLib.ExtCtrls, WEBLib.StdCtrls,
WEBLib.JSON, Auth.Service, XData.Web.Client, WebLib.Storage, WEBLib.JSON, Auth.Service, XData.Web.Client, WebLib.Storage,
ConnectionModule, App.Types, Vcl.StdCtrls, Vcl.Controls, WEBLib.DBCtrls, ConnectionModule, App.Types, Vcl.StdCtrls, Vcl.Controls, WEBLib.DBCtrls,
Data.DB, XData.Web.JsonDataset, XData.Web.Dataset, WEBLib.DB; Data.DB, XData.Web.JsonDataset, XData.Web.Dataset, WEBLib.DB, VCL.Forms;
type type
TFOrderEntryCorrugated = class(TWebForm) TFOrderEntryCorrugated = class(TWebForm)
pnlMessage: TWebPanel;
lblMessage: TWebLabel;
btnCloseNotification: TWebButton;
dtpOrderDate: TWebDateTimePicker; dtpOrderDate: TWebDateTimePicker;
dtpProofDate: TWebDateTimePicker; dtpProofDate: TWebDateTimePicker;
dtpShipDate: TWebDateTimePicker; dtpShipDate: TWebDateTimePicker;
...@@ -204,8 +201,6 @@ type ...@@ -204,8 +201,6 @@ type
btnAdd: TWebButton; btnAdd: TWebButton;
WebButton2: TWebButton; WebButton2: TWebButton;
procedure WebFormCreate(Sender: TObject); procedure WebFormCreate(Sender: TObject);
procedure HideNotification();
procedure ShowNotification(Notification: string);
procedure WebFormShow(Sender: TObject); procedure WebFormShow(Sender: TObject);
[async] procedure getOrder(Order_ID: string); [async] procedure getOrder(Order_ID: string);
[async] procedure getCustomer(customerID: string); [async] procedure getCustomer(customerID: string);
...@@ -221,7 +216,6 @@ type ...@@ -221,7 +216,6 @@ type
procedure btnCopyClick(Sender: TObject); procedure btnCopyClick(Sender: TObject);
procedure sendOrderToServer(); procedure sendOrderToServer();
procedure btnCloseClick(Sender: TObject); procedure btnCloseClick(Sender: TObject);
procedure btnCloseNotificationClick(Sender: TObject);
procedure btnDeleteClick(Sender: TObject); procedure btnDeleteClick(Sender: TObject);
procedure btn_confirm_deleteClick(Sender: TObject); procedure btn_confirm_deleteClick(Sender: TObject);
procedure tmrReturnTimer(Sender: TObject); procedure tmrReturnTimer(Sender: TObject);
...@@ -486,7 +480,7 @@ begin ...@@ -486,7 +480,7 @@ begin
dtpApprovedDate.Date := 0; dtpApprovedDate.Date := 0;
edtOrderNum.Text := ''; edtOrderNum.Text := '';
EditMode(); EditMode();
ShowNotification('Success: Order Successfully Copied'); ShowToast('Success: Order Successfully Copied');
window.scrollTo(0, 0); window.scrollTo(0, 0);
end; end;
...@@ -520,7 +514,7 @@ begin ...@@ -520,7 +514,7 @@ begin
if mode = 'EDIT' then if mode = 'EDIT' then
GenerateReportPDF GenerateReportPDF
else else
showNotification('Failure: Cannot Generate PDF when Adding an Order'); ShowToast('Failure: Cannot Generate PDF when Adding an Order');
end; end;
procedure TFOrderEntryCorrugated.btn_confirm_deleteClick(Sender: TObject); procedure TFOrderEntryCorrugated.btn_confirm_deleteClick(Sender: TObject);
...@@ -592,7 +586,7 @@ begin ...@@ -592,7 +586,7 @@ begin
edtOrderNum.Text := OrderID; edtOrderNum.Text := OrderID;
mode := 'EDIT'; mode := 'EDIT';
console.log(jsObj); console.log(jsObj);
ShowNotification(string(jsObj.Properties['status'])); ShowToast(string(jsObj.Properties['status']));
end; end;
procedure TFOrderEntryCorrugated.DelOrder(); procedure TFOrderEntryCorrugated.DelOrder();
...@@ -722,7 +716,7 @@ begin ...@@ -722,7 +716,7 @@ begin
[AddressJSON.ToString])); [AddressJSON.ToString]));
notification := TJSObject(Response.Result); notification := TJSObject(Response.Result);
ShowNotification(string(notification['status'])); ShowToast(string(notification['status']));
xdwdsShipTo.Close; xdwdsShipTo.Close;
xdwdsShipTo.SetJSONData(notification['ADDRESS']); xdwdsShipTo.SetJSONData(notification['ADDRESS']);
xdwdsShipTo.Open; xdwdsShipTo.Open;
...@@ -739,6 +733,7 @@ begin ...@@ -739,6 +733,7 @@ begin
newform.Caption := 'Input Shipping Information'; newform.Caption := 'Input Shipping Information';
newForm.Popup := True; newForm.Popup := True;
newForm.Position := poScreenCenter;
newForm.Border := fbDialog; newForm.Border := fbDialog;
// used to manage Back button handling to close subform // used to manage Back button handling to close subform
...@@ -784,6 +779,7 @@ begin ...@@ -784,6 +779,7 @@ begin
newform.Caption := 'Select Customer and Order Type'; newform.Caption := 'Select Customer and Order Type';
newForm.Popup := True; newForm.Popup := True;
newForm.Position := poScreenCenter;
newForm.Border := fbDialog; newForm.Border := fbDialog;
// used to manage Back button handling to close subform // used to manage Back button handling to close subform
...@@ -840,10 +836,6 @@ begin ...@@ -840,10 +836,6 @@ begin
FViewMain.ViewOrders(''); FViewMain.ViewOrders('');
end; end;
procedure TFOrderEntryCorrugated.btnCloseNotificationClick(Sender: TObject);
begin
hideNotification();
end;
procedure TFOrderEntryCorrugated.WebFormCreate(Sender: TObject); procedure TFOrderEntryCorrugated.WebFormCreate(Sender: TObject);
begin begin
...@@ -1062,13 +1054,9 @@ begin ...@@ -1062,13 +1054,9 @@ begin
EditMode(); EditMode();
end; end;
edtOrderNum.Text := OrderID; edtOrderNum.Text := OrderID;
if notification = '' then if notification <> '' then
begin
HideNotification;
end
else
begin begin
ShowNotification(notification); ShowToast(notification);
end; end;
end; end;
...@@ -1087,41 +1075,6 @@ begin ...@@ -1087,41 +1075,6 @@ begin
EditMode(); EditMode();
end; end;
procedure TFOrderEntryCorrugated.HideNotification;
begin
pnlMessage.ElementHandle.hidden := True;
end;
procedure TFOrderEntryCorrugated.ShowNotification(Notification: string);
var
splitNotification: TArray<string>;
begin
console.log(notification);
if Notification <> '' then
begin
splitNotification := Notification.Split([':']);
if(splitNotification[0] = 'Success') then
begin
asm
var messageDiv = document.getElementById('view.login.message');
messageDiv.classList.remove('alert-danger');
messageDiv.classList.add('alert-success');
end;
end
else
begin
asm
var messageDiv = document.getElementById('view.login.message');
messageDiv.classList.remove('alert-success');
messageDiv.classList.add('alert-danger');
end;
end;
console.log(splitNotification[1]) ;
lblMessage.Caption := splitNotification[1];
pnlMessage.ElementHandle.hidden := False;
end;
end;
procedure TFOrderEntryCorrugated.tmrReturnTimer(Sender: TObject); procedure TFOrderEntryCorrugated.tmrReturnTimer(Sender: TObject);
begin begin
......
...@@ -228,43 +228,6 @@ object FOrderEntryCuttingDie: TFOrderEntryCuttingDie ...@@ -228,43 +228,6 @@ object FOrderEntryCuttingDie: TFOrderEntryCuttingDie
WidthPercent = 100.000000000000000000 WidthPercent = 100.000000000000000000
OnClick = btnCancelClick OnClick = btnCancelClick
end end
object pnlMessage: TWebPanel
Left = 324
Top = 19
Width = 121
Height = 33
ElementID = 'view.login.message'
ChildOrder = 5
ElementPosition = epRelative
Role = 'alert'
TabOrder = 15
object lblMessage: TWebLabel
Left = 28
Top = 9
Width = 46
Height = 15
Caption = 'Message'
ElementID = 'view.login.message.label'
ElementPosition = epRelative
HeightPercent = 100.000000000000000000
WidthPercent = 100.000000000000000000
end
object btnCloseNotification: TWebButton
Left = 96
Top = 3
Width = 22
Height = 25
ChildOrder = 1
ElementID = 'view.login.message.button'
ElementFont = efCSS
ElementPosition = epRelative
HeightStyle = ssAuto
HeightPercent = 100.000000000000000000
Role = 'button'
WidthStyle = ssAuto
WidthPercent = 100.000000000000000000
end
end
object edtCompanyName: TWebDBEdit object edtCompanyName: TWebDBEdit
Left = 26 Left = 26
Top = 92 Top = 92
......
<nav class="navbar navbar-expand navbar-light bg-light sticky-top" style="z-index: 100;"> <nav class="navbar navbar-expand navbar-light bg-light sticky-top" style="z-index: 100;">
<div class="container-fluid ps-0"> <div class="container-fluid ps-0">
<div id="view.login.message" class="alert alert-danger"
style="padding: 0.25rem 0.5rem; font-size: 0.875rem; line-height: 1.5; display: flex; align-items: center; margin: 0 0 0 60px; height: 32px; width: 400px;">
<button id="view.login.message.button" type="button" class="btn-close" aria-label="Close"></button>
<span id="view.login.message.label"></span>
</div>
<ul class="navbar-nav me-auto ps-2"> <ul class="navbar-nav me-auto ps-2">
<li class="nav-item pe-2"> <li class="nav-item pe-2">
<button id="btnadd" class="btn btn-primary btn-sm">Add</button> <button id="btnadd" class="btn btn-primary btn-sm">Add</button>
......
...@@ -7,7 +7,7 @@ uses ...@@ -7,7 +7,7 @@ uses
WEBLib.Forms, WEBLib.Dialogs, WEBLib.Menus, WEBLib.ExtCtrls, WEBLib.StdCtrls, WEBLib.Forms, WEBLib.Dialogs, WEBLib.Menus, WEBLib.ExtCtrls, WEBLib.StdCtrls,
WEBLib.JSON, Auth.Service, XData.Web.Client, WebLib.Storage, WEBLib.JSON, Auth.Service, XData.Web.Client, WebLib.Storage,
ConnectionModule, App.Types, Vcl.StdCtrls, Vcl.Controls, WEBLib.DBCtrls, ConnectionModule, App.Types, Vcl.StdCtrls, Vcl.Controls, WEBLib.DBCtrls,
Data.DB, XData.Web.JsonDataset, XData.Web.Dataset, WEBLib.DB; Data.DB, XData.Web.JsonDataset, XData.Web.Dataset, WEBLib.DB, VCL.Forms;
type type
TFOrderEntryCuttingDie = class(TWebForm) TFOrderEntryCuttingDie = class(TWebForm)
...@@ -52,9 +52,6 @@ type ...@@ -52,9 +52,6 @@ type
edtSpecialInstructions: TWebDBEdit; edtSpecialInstructions: TWebDBEdit;
btnSave: TWebButton; btnSave: TWebButton;
btnCancel: TWebButton; btnCancel: TWebButton;
pnlMessage: TWebPanel;
lblMessage: TWebLabel;
btnCloseNotification: TWebButton;
edtCompanyName: TWebDBEdit; edtCompanyName: TWebDBEdit;
XDataWebDataSet1NAME: TStringField; XDataWebDataSet1NAME: TStringField;
XDataWebDataSet1staff_fields_quickbooks_item: TStringField; XDataWebDataSet1staff_fields_quickbooks_item: TStringField;
...@@ -76,9 +73,7 @@ type ...@@ -76,9 +73,7 @@ type
WebButton2: TWebButton; WebButton2: TWebButton;
procedure btnSaveClick(Sender: TObject); procedure btnSaveClick(Sender: TObject);
procedure btnCancelClick(Sender: TObject); procedure btnCancelClick(Sender: TObject);
procedure WebFormCreate(Sender: TObject); procedure WebFormCreate(Sender: TObject);
procedure HideNotification();
procedure ShowNotification(Notification: string);
procedure WebFormShow(Sender: TObject); procedure WebFormShow(Sender: TObject);
[async] procedure GetCuttingDieOrder(Order_ID: string); [async] procedure GetCuttingDieOrder(Order_ID: string);
[async] procedure GetCustomer(customerID: string); [async] procedure GetCustomer(customerID: string);
...@@ -141,7 +136,7 @@ begin ...@@ -141,7 +136,7 @@ begin
[AddressJSON.ToString])); [AddressJSON.ToString]));
notification := TJSObject(Response.Result); notification := TJSObject(Response.Result);
ShowNotification(string(notification['status'])); ShowToast(string(notification['status']));
xdwdsShipTo.Close; xdwdsShipTo.Close;
xdwdsShipTo.SetJSONData(notification['ADDRESS']); xdwdsShipTo.SetJSONData(notification['ADDRESS']);
xdwdsShipTo.Open; xdwdsShipTo.Open;
...@@ -159,6 +154,7 @@ begin ...@@ -159,6 +154,7 @@ begin
newform.Caption := 'Shipping Information'; newform.Caption := 'Shipping Information';
newForm.Popup := True; newForm.Popup := True;
newForm.Border := fbDialog; newForm.Border := fbDialog;
newForm.Position := poScreenCenter;
// used to manage Back button handling to close subform // used to manage Back button handling to close subform
window.location.hash := 'subform'; window.location.hash := 'subform';
...@@ -296,9 +292,9 @@ begin ...@@ -296,9 +292,9 @@ begin
orderJSON.AddPair('ORDER_ID', orderID); orderJSON.AddPair('ORDER_ID', orderID);
if mode = 'ADD' then if mode = 'ADD' then
ShowNotification('Success:Order Added Successfully!') ShowToast('Success: Order Added Successfully!')
else else
ShowNotification('Success:Order Edited Successfully'); ShowToast('Success: Order Edited Successfully');
AddCuttingDieOrder(orderJSON); AddCuttingDieOrder(orderJSON);
...@@ -321,7 +317,7 @@ begin ...@@ -321,7 +317,7 @@ begin
dtpOrderDate.Date := 0; dtpOrderDate.Date := 0;
dtpProofDate.Date := 0; dtpProofDate.Date := 0;
edtOrderNum.Text := ''; edtOrderNum.Text := '';
ShowNotification('Success:Order Successfully Copied'); ShowToast('Success: Order Successfully Copied');
EditMode(); EditMode();
window.scrollTo(0, 0); window.scrollTo(0, 0);
end; end;
...@@ -370,7 +366,7 @@ begin ...@@ -370,7 +366,7 @@ begin
FViewMain.change := false; FViewMain.change := false;
if OrderID <> '' then if OrderID <> '' then
begin begin
FViewMain.ViewOrderEntryCuttingDie(OrderID, '', 'EDIT', 'Failure:Changes Discarded'); FViewMain.ViewOrderEntryCuttingDie(OrderID, '', 'EDIT', 'Failure: Changes Discarded');
end end
else else
FViewMain.ViewOrders(''); FViewMain.ViewOrders('');
...@@ -450,7 +446,6 @@ begin ...@@ -450,7 +446,6 @@ begin
begin begin
with TFOrderEntryCuttingDie(AForm) do with TFOrderEntryCuttingDie(AForm) do
begin begin
HideNotification;
TFOrderEntryCuttingDie(AForm).customerID := customerInfo; TFOrderEntryCuttingDie(AForm).customerID := customerInfo;
TFOrderEntryCuttingDie(AForm).orderID := orderInfo; TFOrderEntryCuttingDie(AForm).orderID := orderInfo;
TFOrderEntryCuttingDie(AForm).mode := localMode; TFOrderEntryCuttingDie(AForm).mode := localMode;
...@@ -470,6 +465,7 @@ begin ...@@ -470,6 +465,7 @@ begin
newform.Caption := 'Select Customer and Order Type'; newform.Caption := 'Select Customer and Order Type';
newForm.Popup := True; newForm.Popup := True;
newForm.Border := fbDialog; newForm.Border := fbDialog;
newForm.Position := poScreenCenter;
// used to manage Back button handling to close subform // used to manage Back button handling to close subform
window.location.hash := 'subform'; window.location.hash := 'subform';
...@@ -637,46 +633,9 @@ begin ...@@ -637,46 +633,9 @@ begin
EditMode(); EditMode();
end; end;
edtOrderNum.Text := OrderID; edtOrderNum.Text := OrderID;
if notification = '' then if notification <> '' then
begin begin
HideNotification; ShowToast(notification);
end
else
begin
ShowNotification(notification);
end;
end;
procedure TFOrderEntryCuttingDie.HideNotification;
begin
pnlMessage.ElementHandle.hidden := True;
end;
procedure TFOrderEntryCuttingDie.ShowNotification(Notification: string);
var
splitNotification: TArray<string>;
begin
if Notification <> '' then
begin
splitNotification := Notification.Split([':']);
if(splitNotification[0] = 'Success') then
begin
asm
var messageDiv = document.getElementById('view.login.message');
messageDiv.classList.remove('alert-danger');
messageDiv.classList.add('alert-success');
end;
end
else
begin
asm
var messageDiv = document.getElementById('view.login.message');
messageDiv.classList.remove('alert-success');
messageDiv.classList.add('alert-danger');
end;
end;
lblMessage.Caption := splitNotification[1];
pnlMessage.ElementHandle.hidden := False;
end; end;
end; end;
......
...@@ -112,44 +112,6 @@ object FOrderEntryWeb: TFOrderEntryWeb ...@@ -112,44 +112,6 @@ object FOrderEntryWeb: TFOrderEntryWeb
Visible = False Visible = False
WidthPercent = 100.000000000000000000 WidthPercent = 100.000000000000000000
end end
object pnlMessage: TWebPanel
Left = 324
Top = 19
Width = 121
Height = 33
ElementID = 'view.login.message'
ChildOrder = 5
ElementPosition = epRelative
Role = 'alert'
TabOrder = 0
object lblMessage: TWebLabel
Left = 28
Top = 9
Width = 46
Height = 15
Caption = 'Message'
ElementID = 'view.login.message.label'
ElementPosition = epRelative
HeightPercent = 100.000000000000000000
WidthPercent = 100.000000000000000000
end
object btnCloseNotification: TWebButton
Left = 96
Top = 3
Width = 22
Height = 25
ChildOrder = 1
ElementID = 'view.login.message.button'
ElementFont = efCSS
ElementPosition = epRelative
HeightStyle = ssAuto
HeightPercent = 100.000000000000000000
Role = 'button'
WidthStyle = ssAuto
WidthPercent = 100.000000000000000000
OnClick = btnCloseNotificationClick
end
end
object edtCompanyName: TWebDBEdit object edtCompanyName: TWebDBEdit
Left = 24 Left = 24
Top = 92 Top = 92
......
<nav class="navbar navbar-expand navbar-light bg-light sticky-top" style="z-index: 100;"> <nav class="navbar navbar-expand navbar-light bg-light sticky-top" style="z-index: 100;">
<div class="container-fluid ps-0"> <div class="container-fluid ps-0">
<div id="view.login.message" class="alert alert-danger"
style="padding: 0.25rem 0.5rem; font-size: 0.875rem; line-height: 1.5; display: flex; align-items: center; margin: 0 0 0 60px; height: 32px; width: 400px;">
<button id="view.login.message.button" type="button" class="btn-close" aria-label="Close"></button>
<span id="view.login.message.label"></span>
</div>
<ul class="navbar-nav me-auto ps-2"> <ul class="navbar-nav me-auto ps-2">
<li class="nav-item pe-2"> <li class="nav-item pe-2">
<button id="btnadd" class="btn btn-primary btn-sm">Add</button> <button id="btnadd" class="btn btn-primary btn-sm">Add</button>
......
...@@ -7,14 +7,11 @@ uses ...@@ -7,14 +7,11 @@ uses
WEBLib.Forms, WEBLib.Dialogs, WEBLib.Menus, WEBLib.ExtCtrls, WEBLib.StdCtrls, WEBLib.Forms, WEBLib.Dialogs, WEBLib.Menus, WEBLib.ExtCtrls, WEBLib.StdCtrls,
WEBLib.JSON, Auth.Service, XData.Web.Client, WebLib.Storage, WEBLib.JSON, Auth.Service, XData.Web.Client, WebLib.Storage,
ConnectionModule, App.Types, Vcl.StdCtrls, Vcl.Controls, WEBLib.DBCtrls, ConnectionModule, App.Types, Vcl.StdCtrls, Vcl.Controls, WEBLib.DBCtrls,
Data.DB, XData.Web.JsonDataset, XData.Web.Dataset, WEBLib.DB; Data.DB, XData.Web.JsonDataset, XData.Web.Dataset, WEBLib.DB, VCL.Forms;
type type
TFOrderEntryWeb = class(TWebForm) TFOrderEntryWeb = class(TWebForm)
WebLabel2: TWebLabel; WebLabel2: TWebLabel;
pnlMessage: TWebPanel;
lblMessage: TWebLabel;
btnCloseNotification: TWebButton;
edtCompanyName: TWebDBEdit; edtCompanyName: TWebDBEdit;
edtCompanyAccountName: TWebDBEdit; edtCompanyAccountName: TWebDBEdit;
edtInQuickBooks: TWebDBEdit; edtInQuickBooks: TWebDBEdit;
...@@ -208,8 +205,6 @@ type ...@@ -208,8 +205,6 @@ type
btnAdd: TWebButton; btnAdd: TWebButton;
WebButton2: TWebButton; WebButton2: TWebButton;
procedure WebFormCreate(Sender: TObject); procedure WebFormCreate(Sender: TObject);
procedure HideNotification();
procedure ShowNotification(Notification: string);
procedure WebFormShow(Sender: TObject); procedure WebFormShow(Sender: TObject);
[async] procedure getOrder(Order_ID: string); [async] procedure getOrder(Order_ID: string);
[async] procedure getCustomer(customerID: string); [async] procedure getCustomer(customerID: string);
...@@ -226,7 +221,6 @@ type ...@@ -226,7 +221,6 @@ type
procedure btnCloseClick(Sender: TObject); procedure btnCloseClick(Sender: TObject);
procedure btnDeleteClick(Sender: TObject); procedure btnDeleteClick(Sender: TObject);
[async] procedure DelOrder; [async] procedure DelOrder;
procedure btnCloseNotificationClick(Sender: TObject);
procedure tmrReturnTimer(Sender: TObject); procedure tmrReturnTimer(Sender: TObject);
procedure btn_confirm_deleteClick(Sender: TObject); procedure btn_confirm_deleteClick(Sender: TObject);
function VerifyOrder(): boolean; function VerifyOrder(): boolean;
...@@ -277,7 +271,7 @@ begin ...@@ -277,7 +271,7 @@ begin
[AddressJSON.ToString])); [AddressJSON.ToString]));
notification := TJSObject(Response.Result); notification := TJSObject(Response.Result);
ShowNotification(string(notification['status'])); ShowToast(string(notification['status']));
xdwdsShipTo.Close; xdwdsShipTo.Close;
xdwdsShipTo.SetJSONData(notification['ADDRESS']); xdwdsShipTo.SetJSONData(notification['ADDRESS']);
xdwdsShipTo.Open; xdwdsShipTo.Open;
...@@ -295,6 +289,7 @@ begin ...@@ -295,6 +289,7 @@ begin
newform.Caption := 'Input Shipping Information'; newform.Caption := 'Input Shipping Information';
newForm.Popup := True; newForm.Popup := True;
newForm.Border := fbDialog; newForm.Border := fbDialog;
newForm.Position := poScreenCenter;
// used to manage Back button handling to close subform // used to manage Back button handling to close subform
window.location.hash := 'subform'; window.location.hash := 'subform';
...@@ -413,7 +408,7 @@ begin ...@@ -413,7 +408,7 @@ begin
dtpDigitalColorDate.Date := 0; dtpDigitalColorDate.Date := 0;
edtOrderNum.Text := ''; edtOrderNum.Text := '';
EditMode(); EditMode();
ShowNotification('Success:Order Successfully Copied'); ShowToast('Success: Order Successfully Copied');
window.scrollTo(0, 0); window.scrollTo(0, 0);
end; end;
...@@ -555,7 +550,7 @@ begin ...@@ -555,7 +550,7 @@ begin
else else
info := 'Success:Order Successfully Added'; info := 'Success:Order Successfully Added';
AddWebOrder(orderJSON); AddWebOrder(orderJSON);
ShowNotification(info); ShowToast(info);
end; end;
procedure TFOrderEntryWeb.btnPDFClick(Sender: TObject); procedure TFOrderEntryWeb.btnPDFClick(Sender: TObject);
...@@ -648,7 +643,6 @@ begin ...@@ -648,7 +643,6 @@ begin
begin begin
with TFOrderEntryWeb(AForm) do with TFOrderEntryWeb(AForm) do
begin begin
HideNotification;
TFOrderEntryWeb(AForm).customerID := customerInfo; TFOrderEntryWeb(AForm).customerID := customerInfo;
TFOrderEntryWeb(AForm).orderID := orderInfo; TFOrderEntryWeb(AForm).orderID := orderInfo;
TFOrderEntryWeb(AForm).mode := localMode; TFOrderEntryWeb(AForm).mode := localMode;
...@@ -747,6 +741,7 @@ begin ...@@ -747,6 +741,7 @@ begin
newform.Caption := 'Select Customer and Order Type'; newform.Caption := 'Select Customer and Order Type';
newForm.Popup := True; newForm.Popup := True;
newForm.Border := fbDialog; newForm.Border := fbDialog;
newForm.Position := poScreenCenter;
// used to manage Back button handling to close subform // used to manage Back button handling to close subform
window.location.hash := 'subform'; window.location.hash := 'subform';
...@@ -801,10 +796,6 @@ begin ...@@ -801,10 +796,6 @@ begin
FViewMain.ViewOrders(''); FViewMain.ViewOrders('');
end; end;
procedure TFOrderEntryWeb.btnCloseNotificationClick(Sender: TObject);
begin
hideNotification();
end;
procedure TFOrderEntryWeb.WebFormCreate(Sender: TObject); procedure TFOrderEntryWeb.WebFormCreate(Sender: TObject);
begin begin
...@@ -992,13 +983,9 @@ begin ...@@ -992,13 +983,9 @@ begin
EditMode(); EditMode();
end; end;
edtOrderNum.Text := OrderID; edtOrderNum.Text := OrderID;
if notification = '' then if notification <> '' then
begin
HideNotification;
end
else
begin begin
ShowNotification(notification); ShowToast(notification);
end; end;
end; end;
...@@ -1007,39 +994,6 @@ begin ...@@ -1007,39 +994,6 @@ begin
EditMode(); EditMode();
end; end;
procedure TFOrderEntryWeb.HideNotification;
begin
pnlMessage.ElementHandle.hidden := True;
end;
procedure TFOrderEntryWeb.ShowNotification(Notification: string);
var
splitNotification: TArray<string>;
begin
if Notification <> '' then
begin
splitNotification := Notification.Split([':']);
if(splitNotification[0] = 'Success') then
begin
asm
var messageDiv = document.getElementById('view.login.message');
messageDiv.classList.remove('alert-danger');
messageDiv.classList.add('alert-success');
end;
end
else
begin
asm
var messageDiv = document.getElementById('view.login.message');
messageDiv.classList.remove('alert-success');
messageDiv.classList.add('alert-danger');
end;
end;
lblMessage.Caption := splitNotification[1];
pnlMessage.ElementHandle.hidden := False;
end;
end;
procedure TFOrderEntryWeb.tmrReturnTimer(Sender: TObject); procedure TFOrderEntryWeb.tmrReturnTimer(Sender: TObject);
begin begin
......
...@@ -309,36 +309,6 @@ object FViewOrders: TFViewOrders ...@@ -309,36 +309,6 @@ object FViewOrders: TFViewOrders
HeightPercent = 100.000000000000000000 HeightPercent = 100.000000000000000000
WidthPercent = 100.000000000000000000 WidthPercent = 100.000000000000000000
end end
object pnlMessage: TWebPanel
Left = 12
Top = 16
Width = 121
Height = 33
ElementID = 'view.login.message'
ChildOrder = 17
TabOrder = 8
object lblMessage: TWebLabel
Left = 16
Top = 11
Width = 42
Height = 13
Caption = 'Message'
ElementID = 'view.login.message.label'
HeightPercent = 100.000000000000000000
WidthPercent = 100.000000000000000000
end
object btnCloseNotification: TWebButton
Left = 96
Top = 3
Width = 22
Height = 25
ChildOrder = 1
ElementID = 'view.login.message.button'
HeightPercent = 100.000000000000000000
WidthPercent = 100.000000000000000000
OnClick = btnCloseNotificationClick
end
end
object XDataWebClient1: TXDataWebClient object XDataWebClient1: TXDataWebClient
Connection = DMConnection.ApiConnection Connection = DMConnection.ApiConnection
Left = 28 Left = 28
......
<div class="container h-100 d-flex flex-column mt-0 py-0" style="max-width: 100%;"> <div class="container h-100 d-flex flex-column mt-0 py-0" style="max-width: 100%;">
<!-- Alert Section -->
<div class="row">
<div class=col-sm>
<div id="view.login.message" class="alert alert-danger">
<button id="view.login.message.button" type="button" class="btn-close" aria-label="Close"></button>
<span id="view.login.message.label"></span>
</div>
</div>
</div>
<!-- Actions Row --> <!-- Actions Row -->
<div class="row mt-2 justify-content-center"> <div class="row mt-2 justify-content-center">
<div class="col-auto d-flex align-items-center"> <div class="col-auto d-flex align-items-center">
......
...@@ -14,7 +14,7 @@ uses ...@@ -14,7 +14,7 @@ uses
WEBLib.JSON, Auth.Service, XData.Web.Client, WebLib.Storage, WEBLib.JSON, Auth.Service, XData.Web.Client, WebLib.Storage,
ConnectionModule, App.Types, Vcl.StdCtrls, Vcl.Controls, WEBLib.DBCtrls, ConnectionModule, App.Types, Vcl.StdCtrls, Vcl.Controls, WEBLib.DBCtrls,
XData.Web.JsonDataset, WEBLib.DB, Data.DB, XData.Web.Dataset, XData.Web.DatasetCommon, XData.Web.JsonDataset, WEBLib.DB, Data.DB, XData.Web.Dataset, XData.Web.DatasetCommon,
WEBLib.Grids; WEBLib.Grids, VCL.Forms;
type type
TFViewOrders = class(TWebForm) TFViewOrders = class(TWebForm)
...@@ -56,15 +56,11 @@ type ...@@ -56,15 +56,11 @@ type
wcbPageSize: TWebComboBox; wcbPageSize: TWebComboBox;
wlcbOrderBy: TWebLookupComboBox; wlcbOrderBy: TWebLookupComboBox;
edtSearch: TWebEdit; edtSearch: TWebEdit;
pnlMessage: TWebPanel;
lblMessage: TWebLabel;
btnCloseNotification: TWebButton;
xdwdsOrdersDBID: TStringField; xdwdsOrdersDBID: TStringField;
tmrReturn: TWebTimer; tmrReturn: TWebTimer;
procedure WebFormCreate(Sender: TObject); procedure WebFormCreate(Sender: TObject);
procedure btnAddOrderClick(Sender: TObject); procedure btnAddOrderClick(Sender: TObject);
procedure btnSearchClick(Sender: TObject); procedure btnSearchClick(Sender: TObject);
procedure btnCloseNotificationClick(Sender: TObject);
procedure WebFormShow(Sender: TObject); procedure WebFormShow(Sender: TObject);
procedure btnPDFClick(Sender: TObject); procedure btnPDFClick(Sender: TObject);
procedure wcbPageSizeChange(Sender: TObject); procedure wcbPageSizeChange(Sender: TObject);
...@@ -73,19 +69,17 @@ type ...@@ -73,19 +69,17 @@ type
procedure wdbtcOrdersClickCell(Sender: TObject; ACol, ARow: Integer); procedure wdbtcOrdersClickCell(Sender: TObject; ACol, ARow: Integer);
procedure WebButton1Click(Sender: TObject); procedure WebButton1Click(Sender: TObject);
procedure tmrReturnTimer(Sender: TObject); procedure tmrReturnTimer(Sender: TObject);
[async] procedure GenerateReportPDFAsync(APdfTab: TJSWindow);
private private
FChildForm: TWebForm; FChildForm: TWebForm;
procedure ClearTable(); procedure ClearTable();
procedure GeneratePagination(TotalPages: Integer); procedure GeneratePagination(TotalPages: Integer);
function GenerateSearchOptions(): string; function GenerateSearchOptions(): string;
procedure orderEntry(orderInfo, customerInfo, mode, orderType: string); procedure orderEntry(orderInfo, customerInfo, mode, orderType: string);
procedure HideNotification();
procedure ShowNotification(Notification: string);
procedure ShowAddOrderForm(); procedure ShowAddOrderForm();
procedure ShowSearchForm(); procedure ShowSearchForm();
procedure ShowSetStatusForm(); procedure ShowSetStatusForm();
[async] procedure GetOrders(searchOptions: string); [async] procedure GetOrders(searchOptions: string);
[async] procedure GenerateReportPDF;
[async] procedure SetStatus(statusInfo: string); [async] procedure SetStatus(statusInfo: string);
var var
PageNumber: integer; PageNumber: integer;
...@@ -144,43 +138,57 @@ begin ...@@ -144,43 +138,57 @@ begin
end; end;
procedure TFViewOrders.btnPDFClick(Sender: TObject); procedure TFViewOrders.btnPDFClick(Sender: TObject);
var
pdfTab: TJSWindow; // handle for the new tab
begin begin
pdfTab := window.open('', '_blank');
if Assigned(pdfTab) then
pdfTab.document.write('<html><body style="font-family:Arial;padding:2rem;">'
+'Generating PDF</body></html>');
Utils.ShowSpinner('spinner'); Utils.ShowSpinner('spinner');
GenerateReportPDF; GenerateReportPDFAsync(pdfTab); // pass the handle along
end; end;
[async] procedure TFViewOrders.GenerateReportPDF;
// sends the search to the server which then sends back a pdf of the results [async] procedure TFViewOrders.GenerateReportPDFAsync(APdfTab: TJSWindow);
var var
xdcResponse: TXDataClientResponse; xdcResponse: TXDataClientResponse;
searchOptions, pdfURL: string; searchOptions, pdfURL: string;
jsObject: TJSObject; jsObject: TJSObject;
begin begin
Utils.ShowSpinner('spinner');
try try
searchOptions := edtSearch.Text; searchOptions := edtSearch.Text;
// Call the server method to generate the PDF xdcResponse := await(
xdcResponse := await(XDataWebClient1.RawInvokeAsync('ILookupService.GenerateOrderListPDF', [searchOptions])); XDataWebClient1.RawInvokeAsync('ILookupService.GenerateOrderListPDF',
jsObject := JS.TJSObject(xdcResponse.Result); [searchOptions]));
pdfURL := JS.toString(jsObject.Properties['value']); jsObject := TJSObject(xdcResponse.Result);
pdfURL := String(jsObject.Properties['value']);
// Open the PDF in a new browser tab if Assigned(APdfTab) then
window.open(pdfURL, '_blank'); APdfTab.location.href := pdfURL;
except except
on E: EXDataClientRequestException do on E: EXDataClientRequestException do
Utils.ShowErrorModal('Could not generate report PDF: ' + E.ErrorResult.ErrorMessage); begin
Utils.ShowErrorModal('Could not generate report PDF: ' +
E.ErrorResult.ErrorMessage);
if Assigned(APdfTab) then
APdfTab.close; // close the blank tab on failure
end;
end; end;
Utils.HideSpinner('spinner'); Utils.HideSpinner('spinner');
end; end;
procedure TFViewOrders.WebButton1Click(Sender: TObject); procedure TFViewOrders.WebButton1Click(Sender: TObject);
begin begin
if OrderID <> '' then if OrderID <> '' then
ShowSetStatusForm() ShowSetStatusForm()
else else
ShowNotification('Failure:Please select an order'); ShowToast('Failure: Please select an order');
end; end;
procedure TFViewOrders.WebFormCreate(Sender: TObject); procedure TFViewOrders.WebFormCreate(Sender: TObject);
...@@ -263,9 +271,7 @@ end; ...@@ -263,9 +271,7 @@ end;
procedure TFViewOrders.WebFormShow(Sender: TObject); procedure TFViewOrders.WebFormShow(Sender: TObject);
begin begin
if info <> '' then if info <> '' then
ShowNotification(info) ShowToast(info)
else
HideNotification();
end; end;
...@@ -286,6 +292,7 @@ begin ...@@ -286,6 +292,7 @@ begin
newform.Caption := 'Select Customer and Order Type'; newform.Caption := 'Select Customer and Order Type';
newForm.Popup := True; newForm.Popup := True;
newForm.position:= poScreenCenter;
newForm.Border := fbDialog; newForm.Border := fbDialog;
// used to manage Back button handling to close subform // used to manage Back button handling to close subform
...@@ -318,6 +325,7 @@ begin ...@@ -318,6 +325,7 @@ begin
newform.Caption := 'Input Search Options'; newform.Caption := 'Input Search Options';
newForm.Popup := True; newForm.Popup := True;
newForm.Border := fbDialog; newForm.Border := fbDialog;
newForm.position:= poScreenCenter;
newForm.searchOptions := FViewMain.search; newForm.searchOptions := FViewMain.search;
// used to manage Back button handling to close subform // used to manage Back button handling to close subform
...@@ -368,6 +376,7 @@ begin ...@@ -368,6 +376,7 @@ begin
newform.Caption := 'Input Search Options'; newform.Caption := 'Input Search Options';
newForm.Popup := True; newForm.Popup := True;
newForm.Border := fbDialog; newForm.Border := fbDialog;
newForm.Position := poScreenCenter;
newForm.OrderID := OrderID; newForm.OrderID := OrderID;
newForm.JobName := wdbtcOrders.Cells[3, row]; newForm.JobName := wdbtcOrders.Cells[3, row];
if wdbtcOrders.Cells[14, row] <> '' then if wdbtcOrders.Cells[14, row] <> '' then
...@@ -720,10 +729,6 @@ begin ...@@ -720,10 +729,6 @@ begin
FViewMain.ViewOrderEntryCuttingDie(orderInfo, customerInfo, mode, ''); FViewMain.ViewOrderEntryCuttingDie(orderInfo, customerInfo, mode, '');
end; end;
procedure TFViewOrders.btnCloseNotificationClick(Sender: TObject);
begin
HideNotification();
end;
procedure TFViewOrders.btnSearchClick(Sender: TObject); procedure TFViewOrders.btnSearchClick(Sender: TObject);
var var
...@@ -796,39 +801,5 @@ begin ...@@ -796,39 +801,5 @@ begin
end; end;
procedure TFViewOrders.HideNotification;
begin
pnlMessage.ElementHandle.hidden := True;
info := '';
end;
procedure TFViewOrders.ShowNotification(Notification: string);
var
splitNotification: TArray<string>;
begin
if Notification <> '' then
begin
splitNotification := Notification.Split([':']);
if(splitNotification[0] = 'Success') then
begin
asm
var messageDiv = document.getElementById('view.login.message');
messageDiv.classList.remove('alert-danger');
messageDiv.classList.add('alert-success');
end;
end
else
begin
asm
var messageDiv = document.getElementById('view.login.message');
messageDiv.classList.remove('alert-success');
messageDiv.classList.add('alert-danger');
end;
end;
lblMessage.Caption := splitNotification[1];
pnlMessage.ElementHandle.hidden := False;
end;
end;
end. end.
...@@ -216,6 +216,7 @@ object FSelectCustomer: TFSelectCustomer ...@@ -216,6 +216,7 @@ object FSelectCustomer: TFSelectCustomer
ChildOrder = 5 ChildOrder = 5
HeightPercent = 100.000000000000000000 HeightPercent = 100.000000000000000000
WidthPercent = 100.000000000000000000 WidthPercent = 100.000000000000000000
OnClick = btnCancelClick
end end
object btnConfirm: TWebButton object btnConfirm: TWebButton
Left = 440 Left = 440
......
...@@ -47,6 +47,7 @@ type ...@@ -47,6 +47,7 @@ type
procedure btnConfirmClick(Sender: TObject); procedure btnConfirmClick(Sender: TObject);
procedure TMSFNCGrid1CellClick(Sender: TObject; ACol, ARow: Integer); procedure TMSFNCGrid1CellClick(Sender: TObject; ACol, ARow: Integer);
procedure edtSearchChange(Sender: TObject); procedure edtSearchChange(Sender: TObject);
procedure btnCancelClick(Sender: TObject);
private private
{ Private declarations } { Private declarations }
[Async] procedure GetCustomers(); [Async] procedure GetCustomers();
...@@ -81,6 +82,11 @@ begin ...@@ -81,6 +82,11 @@ begin
getCustomers(); getCustomers();
end; end;
procedure TFSelectCustomer.btnCancelClick(Sender: TObject);
begin
Close();
end;
procedure TFSelectCustomer.btnConfirmClick(Sender: TObject); procedure TFSelectCustomer.btnConfirmClick(Sender: TObject);
begin begin
if edtID.Text = '' then if edtID.Text = '' then
......
...@@ -5,7 +5,7 @@ interface ...@@ -5,7 +5,7 @@ interface
uses uses
System.SysUtils, System.Classes, JS, Web, WEBLib.Graphics, WEBLib.Controls, System.SysUtils, System.Classes, JS, Web, WEBLib.Graphics, WEBLib.Controls,
WEBLib.Forms, WEBLib.Dialogs, Vcl.Controls, Vcl.StdCtrls, WEBLib.ExtCtrls, WEBLib.Forms, WEBLib.Dialogs, Vcl.Controls, Vcl.StdCtrls, WEBLib.ExtCtrls,
WEBLib.StdCtrls; WEBLib.StdCtrls, Utils;
type type
TFSetStatus = class(TWebForm) TFSetStatus = class(TWebForm)
...@@ -41,8 +41,6 @@ type ...@@ -41,8 +41,6 @@ type
procedure btnCancelClick(Sender: TObject); procedure btnCancelClick(Sender: TObject);
private private
{ Private declarations } { Private declarations }
procedure HideNotification;
procedure ShowNotification(Notification: string);
public public
{ Public declarations } { Public declarations }
confirm: boolean; confirm: boolean;
...@@ -65,11 +63,11 @@ end; ...@@ -65,11 +63,11 @@ end;
procedure TFSetStatus.btnConfirmClick(Sender: TObject); procedure TFSetStatus.btnConfirmClick(Sender: TObject);
begin begin
if ( (dtpDate.Date = 0 ) or ( wlcbStatus.value = '' ) ) then if ( (dtpDate.Date = 0 ) or ( wlcbStatus.value = '' ) ) then
ShowNotification('Failure:Please fill in all information') ShowToast('Failure: Please fill in all information')
else if ( ( OrderType = 'web plate' ) and ( wlcbStatus.Value = 'MOUNT' ) ) then else if ( ( OrderType = 'web plate' ) and ( wlcbStatus.Value = 'MOUNT' ) ) then
ShowNotification('Failure:Web Plate Orders do not have Mount Due/Done dates') ShowToast('Failure: Web Plate Orders do not have Mount Due/Done dates')
else if ( ( OrderType = 'cutting die' ) and ( wlcbStatus.Value = 'MOUNT' ) or ( wlcbStatus.Value = 'ART' ) or (wlcbStatus.Value = 'PLATE') ) then else if ( ( OrderType = 'cutting die' ) and ( wlcbStatus.Value = 'MOUNT' ) or ( wlcbStatus.Value = 'ART' ) or (wlcbStatus.Value = 'PLATE') ) then
ShowNotification('Failure:Cutting Die Orders do not have Art/Plate/Mount Due or Done Dates') ShowToast('Failure: Cutting Die Orders do not have Art/Plate/Mount Due or Done Dates')
else else
begin begin
confirm := true; confirm := true;
...@@ -83,7 +81,6 @@ var ...@@ -83,7 +81,6 @@ var
i: integer; i: integer;
filteredItems: TJSArray; filteredItems: TJSArray;
begin begin
HideNotification();
edtOrderID.Text := OrderID; edtOrderID.Text := OrderID;
dtpDate.Date := 0; dtpDate.Date := 0;
edtJobName.Text := JobName; edtJobName.Text := JobName;
...@@ -137,17 +134,5 @@ begin ...@@ -137,17 +134,5 @@ begin
end; end;
end; end;
procedure TFSetStatus.HideNotification;
begin
//pnlMessage.ElementHandle.hidden := True;
end;
procedure TFSetStatus.ShowNotification(Notification: string);
begin
if Notification <> '' then
begin
edtNotification.Text := Notification;
end;
end;
end. end.
\ No newline at end of file
<div class="row"> <div class="container">
<div class="col-lg-12"> <!-- Profile form -->
<div class="row"> <div class="row">
<div class=col-sm> <div class="col-lg-8 col-xl-6 mx-auto">
<div id="view.login.message" class="alert alert-danger"> <form id="userprofileform" class="needs-validation" role="form" autocomplete="off" novalidate>
<button id="view.login.message.button" type="button" class="btn-close" aria-label="Close"></button>
<span id="view.login.message.label"></span> <div class="mb-3">
</div> <label id="view.userprofile.form.lblUserID"
for="view.userprofile.form.edtUserID"
class="form-label">User&nbsp;ID</label>
<input id="view.userprofile.form.edtUserID"
class="form-control"
readonly>
</div>
<div class="mb-3">
<label id="view.userprofile.form.lblUserName"
for="view.userprofile.form.edtUsername"
class="form-label">Username</label>
<input id="view.userprofile.form.edtUsername"
class="form-control"
required>
<div class="invalid-feedback">Username is required.</div>
</div>
<div class="mb-3">
<label id="view.userprofile.form.lblFullName"
for="view.userprofile.form.edtFullName"
class="form-label">Full&nbsp;Name</label>
<input id="view.userprofile.form.edtFullName"
class="form-control"
required>
<div class="invalid-feedback">Full Name is required.</div>
</div>
<div class="mb-3">
<label id="view.userprofile.form.lblEmail"
for="view.userprofile.form.edtEmail"
class="form-label">Email&nbsp;Address</label>
<input id="view.userprofile.form.edtEmail"
type="email"
class="form-control"
required>
<div class="invalid-feedback">Valid email is required.</div>
</div>
<div class="form-check mb-4">
<input type="checkbox"
id="view.userprofile.form.chkAdminUser"
class="form-check-input">
<label for="view.userprofile.form.chkAdminUser"
class="form-check-label">
Admin&nbsp;User
</label>
</div> </div>
<div role="form">
<div class="form-group"> <div class="d-flex gap-2 mb-4">
<label id="view.userprofile.form.lblUserID">User ID:</label> <button id="view.userprofile.form.btnconfirm"
<input id="view.userprofile.form.edtUserID" class="form-control"> class="btn btn-primary flex-grow-1"
</div> type="button">
<div class="form-group"> Confirm&nbsp;Changes
<label id="view.userprofile.form.lblUserName">Username:</label> </button>
<input id="view.userprofile.form.edtUsername" class="form-control"> <button id="view.userprofile.form.btncancel"
</div> class="btn btn-outline-secondary flex-grow-1"
<div class="form-group"> type="button">
<label id="view.userprofile.form.lblFullName">Full Name:</label> Cancel&nbsp;Changes
<input id="view.userprofile.form.edtFullName" class="form-control"> </button>
</div>
<div class="form-group">
<label id="view.userprofile.form.lblPhone">Phone Number:</label>
<input id="view.userprofile.form.edtPhone" class="form-control">
</div>
<div class="form-group">
<label id="view.userprofile.form.lblEmail">Email Address:</label>
<input id="view.userprofile.form.edtEmail" class="form-control">
</div>
<div class="custom-control custom-checkbox">
<input type="checkbox" class="custom-control-input" id="view.userprofile.form.chkAdminUser">
<label class="custom-control-label" for="view.userprofile.form.chkAdminUser">Admin User</label>
</div>
<div class="form-group">
<button class="btn btn-primary" id="view.userprofile.form.btnconfirm">Confirm Changes</button>
<button class="btn btn-primary" id="view.userprofile.form.btncancel">Xancel Changes</button>
</div>
<div class="form-group">
<label id="view.userprofile.form.lblresult"></label>
</div>
</div> </div>
<label id="view.userprofile.form.lblresult" class="form-text"></label>
</form>
</div> </div>
</div>
</div> </div>
...@@ -45,36 +45,6 @@ object FViewUsers: TFViewUsers ...@@ -45,36 +45,6 @@ object FViewUsers: TFViewUsers
WidthPercent = 100.000000000000000000 WidthPercent = 100.000000000000000000
OnClick = btnConfirmDeleteClick OnClick = btnConfirmDeleteClick
end end
object pnlMessage: TWebPanel
Left = 12
Top = 16
Width = 121
Height = 33
ElementID = 'view.login.message'
ChildOrder = 17
TabOrder = 2
object lblMessage: TWebLabel
Left = 16
Top = 11
Width = 46
Height = 15
Caption = 'Message'
ElementID = 'view.login.message.label'
HeightPercent = 100.000000000000000000
WidthPercent = 100.000000000000000000
end
object btnCloseNotification: TWebButton
Left = 96
Top = 3
Width = 22
Height = 25
ChildOrder = 1
ElementID = 'view.login.message.button'
HeightPercent = 100.000000000000000000
WidthPercent = 100.000000000000000000
OnClick = btnCloseNotificationClick
end
end
object XDataWebClient1: TXDataWebClient object XDataWebClient1: TXDataWebClient
Connection = DMConnection.ApiConnection Connection = DMConnection.ApiConnection
Left = 462 Left = 462
......
...@@ -5,10 +5,6 @@ ...@@ -5,10 +5,6 @@
<div class="col-12 col-md-8"> <div class="col-12 col-md-8">
<div class="row"> <div class="row">
<div class=col-sm> <div class=col-sm>
<div id="view.login.message" class="alert alert-danger">
<button id="view.login.message.button" type="button" class="btn-close" aria-label="Close"></button>
<span id="view.login.message.label"></span>
</div>
</div> </div>
</div> </div>
</div> </div>
......
...@@ -16,9 +16,6 @@ type ...@@ -16,9 +16,6 @@ type
btnAddUser: TWebButton; btnAddUser: TWebButton;
WebDataSource1: TWebDataSource; WebDataSource1: TWebDataSource;
btnConfirmDelete: TWebButton; btnConfirmDelete: TWebButton;
pnlMessage: TWebPanel;
lblMessage: TWebLabel;
btnCloseNotification: TWebButton;
XDataWebDataSet1userID: TStringField; XDataWebDataSet1userID: TStringField;
XDataWebDataSet1username: TStringField; XDataWebDataSet1username: TStringField;
XDataWebDataSet1full_name: TStringField; XDataWebDataSet1full_name: TStringField;
...@@ -34,7 +31,6 @@ type ...@@ -34,7 +31,6 @@ type
//AField: TField; AValue: string; AElement: TJSHTMLElementRecord); //AField: TField; AValue: string; AElement: TJSHTMLElementRecord);
procedure btnConfirmDeleteClick(Sender: TObject); procedure btnConfirmDeleteClick(Sender: TObject);
procedure btnAddUserClick(Sender: TObject); procedure btnAddUserClick(Sender: TObject);
procedure btnCloseNotificationClick(Sender: TObject);
//procedure btnApplyClick(Sender: TObject); //procedure btnApplyClick(Sender: TObject);
//procedure btnSearchClick(Sender: TObject); //procedure btnSearchClick(Sender: TObject);
private private
...@@ -46,8 +42,6 @@ type ...@@ -46,8 +42,6 @@ type
[async] procedure DelUser(username: string); [async] procedure DelUser(username: string);
[async] procedure EditUser(row: TJSHTMLElement); [async] procedure EditUser(row: TJSHTMLElement);
[async] procedure GetUsers(searchOptions: string); [async] procedure GetUsers(searchOptions: string);
procedure HideNotification;
procedure ShowNotification(Notification: string);
procedure AddRowToTable(UserID, Username, Password, Full_Name, Status, procedure AddRowToTable(UserID, Username, Password, Full_Name, Status,
Email, AType, PID, QBID: string; Rights: integer); Email, AType, PID, QBID: string; Rights: integer);
//[async] procedure addUser(); //[async] procedure addUser();
...@@ -98,10 +92,7 @@ begin ...@@ -98,10 +92,7 @@ begin
PageSize := 10; PageSize := 10;
GetUsers(''); GetUsers('');
if Info <> '' then if Info <> '' then
ShowNotification(Info) ShowToast(Info)
else
HideNotification();
end; end;
procedure TFViewUsers.DelUser(username: string); procedure TFViewUsers.DelUser(username: string);
...@@ -112,7 +103,7 @@ begin ...@@ -112,7 +103,7 @@ begin
xdcResponse := await(XDataWebClient1.RawInvokeAsync('ILookupService.DelUser', xdcResponse := await(XDataWebClient1.RawInvokeAsync('ILookupService.DelUser',
[username])); [username]));
responseString := TJSObject(xdcResponse.Result); responseString := TJSObject(xdcResponse.Result);
ShowNotification(string(responseString['value'])); ShowToast(string(responseString['value']));
getUsers(''); getUsers('');
end; end;
...@@ -449,7 +440,7 @@ begin ...@@ -449,7 +440,7 @@ begin
Cell := TJSHTMLElement(document.createElement('td')); Cell := TJSHTMLElement(document.createElement('td'));
Cell.setAttribute('data-label', 'Edit'); Cell.setAttribute('data-label', 'Edit');
Button := TJSHTMLElement(document.createElement('a')); Button := TJSHTMLElement(document.createElement('a'));
Button.className := 'btn btn-primary'; Button.className := 'btn btn-sm btn-primary';
Button.innerHTML := '<i class="far fa-edit fa-fw"></i><span>Edit</span>'; Button.innerHTML := '<i class="far fa-edit fa-fw"></i><span>Edit</span>';
Button.addEventListener('click', procedure(Event: TJSMouseEvent) Button.addEventListener('click', procedure(Event: TJSMouseEvent)
begin begin
...@@ -468,43 +459,6 @@ begin ...@@ -468,43 +459,6 @@ begin
FViewMain.EditUser('Add', '', '', '', '', '', '', '', '', ''); FViewMain.EditUser('Add', '', '', '', '', '', '', '', '', '');
end; end;
procedure TFViewUsers.btnCloseNotificationClick(Sender: TObject);
begin
HideNotification;
end;
procedure TFViewUsers.HideNotification;
begin
pnlMessage.ElementHandle.hidden := True;
end;
procedure TFViewUsers.ShowNotification(Notification: string);
var
splitNotification: TArray<string>;
begin
if Notification <> '' then
begin
splitNotification := Notification.Split([':']);
if(splitNotification[0] = 'Success') then
begin
asm
var messageDiv = document.getElementById('view.login.message');
messageDiv.classList.remove('alert-danger');
messageDiv.classList.add('alert-success');
end;
end
else
begin
asm
var messageDiv = document.getElementById('view.login.message');
messageDiv.classList.remove('alert-success');
messageDiv.classList.add('alert-danger');
end;
end;
lblMessage.Caption := splitNotification[1];
pnlMessage.ElementHandle.hidden := False;
end;
end;
procedure TFViewUsers.btnConfirmDeleteClick(Sender: TObject); procedure TFViewUsers.btnConfirmDeleteClick(Sender: TObject);
begin begin
......
<!DOCTYPE html> <!DOCTYPE html>
<html> <html>
<head> <head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
<meta name="viewport" content="width=device-width, initial-scale=1"/> <meta content="width=device-width, initial-scale=1" name="viewport"/>
<noscript>Your browser does not support JavaScript!</noscript> <noscript>Your browser does not support JavaScript!</noscript>
<link href="data:;base64,=" rel="icon"/> <link href="data:;base64,=" rel="icon"/>
...@@ -11,22 +11,22 @@ ...@@ -11,22 +11,22 @@
<link href="https://cdnjs.cloudflare.com/ajax/libs/flag-icon-css/2.3.1/css/flag-icon.min.css" rel="stylesheet"/> <link href="https://cdnjs.cloudflare.com/ajax/libs/flag-icon-css/2.3.1/css/flag-icon.min.css" rel="stylesheet"/>
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet"/> <link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet"/>
<link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.0/css/all.min.css" rel="stylesheet"/> <link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.0/css/all.min.css" rel="stylesheet"/>
<link crossorigin="anonymous" href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.1/dist/css/bootstrap.min.css" rel="stylesheet"/>
<link href="css/app.css" rel="stylesheet" type="text/css"/> <link href="css/app.css" rel="stylesheet" type="text/css"/>
<link href="css/spinner.css" rel="stylesheet" type="text/css"/> <link href="css/spinner.css" rel="stylesheet" type="text/css"/>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.1/dist/js/bootstrap.bundle.min.js" type="text/javascript"></script>
<script crossorigin="anonymous" integrity="sha256-eKhayi8LEQwp4NKxN+CfCh+3qOVUtJn3QNZ0TciWLP4=" src="https://code.jquery.com/jquery-3.7.1.js"></script> <script crossorigin="anonymous" integrity="sha256-eKhayi8LEQwp4NKxN+CfCh+3qOVUtJn3QNZ0TciWLP4=" src="https://code.jquery.com/jquery-3.7.1.js"></script>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.1/dist/js/bootstrap.bundle.min.js" type="text/javascript"></script>
<link crossorigin="anonymous" href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.1/dist/css/bootstrap.min.css" rel="stylesheet"/>
<script src="$(ProjectName).js" type="text/javascript"></script> <script src="$(ProjectName).js" type="text/javascript"></script>
</head> </head>
<body> <body>
</body> </body>
<script type="text/javascript"> <script type="text/javascript">rtl.run();</script>
rtl.run();
</script>
</html> </html>
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
<FrameworkType>VCL</FrameworkType> <FrameworkType>VCL</FrameworkType>
<MainSource>webKGOrders.dpr</MainSource> <MainSource>webKGOrders.dpr</MainSource>
<Base>True</Base> <Base>True</Base>
<Config Condition="'$(Config)'==''">Release</Config> <Config Condition="'$(Config)'==''">Debug</Config>
<Platform Condition="'$(Platform)'==''">Win32</Platform> <Platform Condition="'$(Platform)'==''">Win32</Platform>
<TargetedPlatforms>1</TargetedPlatforms> <TargetedPlatforms>1</TargetedPlatforms>
<AppType>Application</AppType> <AppType>Application</AppType>
......
...@@ -132,6 +132,7 @@ begin ...@@ -132,6 +132,7 @@ begin
JWT.Claims.SetClaimOfType<string>('user_email', userEmail); JWT.Claims.SetClaimOfType<string>('user_email', userEmail);
JWT.Claims.SetClaimOfType<string>('user_qb_id', userQBID); JWT.Claims.SetClaimOfType<string>('user_qb_id', userQBID);
JWT.Claims.SetClaimOfType<string>('user_access_type', userAccessType); JWT.Claims.SetClaimOfType<string>('user_access_type', userAccessType);
JWT.Claims.SetClaimOfType<string>('user_admin', LowerCase(BoolToStr(SameText(userAccessType, 'ALL'), True)));
Result := TJOSE.SHA256CompactToken(serverConfig.jwtTokenSecret, JWT); Result := TJOSE.SHA256CompactToken(serverConfig.jwtTokenSecret, JWT);
finally finally
......
...@@ -132,6 +132,7 @@ begin ...@@ -132,6 +132,7 @@ begin
TXDataOperationContext.Current.Handler.ManagedObjects.Add(Result); TXDataOperationContext.Current.Handler.ManagedObjects.Add(Result);
end; end;
function TLookupService.GetCustomers: TCustomerList; function TLookupService.GetCustomers: TCustomerList;
// Retrieves a list of customers and sends it to the client in object form. // Retrieves a list of customers and sends it to the client in object form.
// The object contains the ID, Name, Short Name, and the shipping address. // The object contains the ID, Name, Short Name, and the shipping address.
...@@ -1426,22 +1427,32 @@ begin ...@@ -1426,22 +1427,32 @@ begin
end; end;
function TLookupService.GetUsers(searchOptions: string): TUserList; function TLookupService.GetUsers(searchOptions: string): TUserList;
// Gets a list of all users for the user edit page. // Returns all users, or one specific user when searchOptions <> ''.
// searchOptions: username of a specific user otherwise empty. // Uses parameterised SQL and the real column name USER_NAME.
// TODO: change SQL to hide passwords instead of storing them in plain text.
var var
SQL: string;
user: TUserItem; user: TUserItem;
begin begin
try try
// Prepare and open the query
ordersDB.UniQuery1.Close;
if searchOptions = '' then if searchOptions = '' then
SQL := 'select * from users order by NAME ASC' begin
ordersDB.UniQuery1.SQL.Text :=
'SELECT * FROM users ORDER BY NAME ASC';
end
else else
SQL := 'select * from users where username=' + quotedStr(searchOptions); begin
doQuery(ordersDB.UniQuery1, SQL); ordersDB.UniQuery1.SQL.Text :=
'SELECT * FROM users WHERE USER_NAME = :uname';
ordersDB.UniQuery1.ParamByName('uname').AsString := searchOptions;
end;
ordersDB.UniQuery1.Open;
Result := TUserList.Create; // Build result list
Result.data := TList<TUserItem>.Create; Result := TUserList.Create;
Result.data := TList<TUserItem>.Create;
TXDataOperationContext.Current.Handler.ManagedObjects.Add(Result.data); TXDataOperationContext.Current.Handler.ManagedObjects.Add(Result.data);
while not ordersDB.UniQuery1.Eof do while not ordersDB.UniQuery1.Eof do
...@@ -1449,32 +1460,42 @@ begin ...@@ -1449,32 +1460,42 @@ begin
user := TUserItem.Create; user := TUserItem.Create;
TXDataOperationContext.Current.Handler.ManagedObjects.Add(user); TXDataOperationContext.Current.Handler.ManagedObjects.Add(user);
Result.data.Add(user); Result.data.Add(user);
user.userID := ordersDB.UniQuery1.FieldByName('USER_ID').AsString;
user.username := ordersDB.UniQuery1.FieldByName('USER_NAME').AsString; user.userID := ordersDB.UniQuery1.FieldByName('USER_ID').AsString;
user.password := ordersDB.UniQuery1.FieldByName('PASSWORD').AsString; user.username := ordersDB.UniQuery1.FieldByName('USER_NAME').AsString;
user.full_name := ordersDB.UniQuery1.FieldByName('NAME').AsString; user.password := ordersDB.UniQuery1.FieldByName('PASSWORD').AsString;
user.status := ordersDB.UniQuery1.FieldByName('STATUS').AsString; user.full_name := ordersDB.UniQuery1.FieldByName('NAME').AsString;
user.status := ordersDB.UniQuery1.FieldByName('STATUS').AsString;
user.email_address := ordersDB.UniQuery1.FieldByName('EMAIL').AsString; user.email_address := ordersDB.UniQuery1.FieldByName('EMAIL').AsString;
user.AType := ordersDB.UniQuery1.FieldByName('ACCESS_TYPE').AsString; user.AType := ordersDB.UniQuery1.FieldByName('ACCESS_TYPE').AsString;
user.rights := ordersDB.UniQuery1.FieldByName('SYSTEM_RIGHTS').AsInteger; user.rights := ordersDB.UniQuery1.FieldByName('SYSTEM_RIGHTS').AsInteger;
user.perspectiveID := ordersDB.UniQuery1.FieldByName('PERSPECTIVE_ID').AsString; user.perspectiveID := ordersDB.UniQuery1.FieldByName('PERSPECTIVE_ID').AsString;
user.QBID := ordersDB.UniQuery1.FieldByName('QB_ID').AsString; user.QBID := ordersDB.UniQuery1.FieldByName('QB_ID').AsString;
ordersDB.UniQuery1.Next; ordersDB.UniQuery1.Next;
end; end;
ordersDB.UniQuery1.Close; ordersDB.UniQuery1.Close;
SQL := 'select count(*) as total_count from users'; // Get total-row count (keeps old behaviour)
doQuery(ordersDB.UniQuery1, SQL); ordersDB.UniQuery1.SQL.Text :=
'SELECT COUNT(*) AS total_count FROM users';
ordersDB.UniQuery1.Open;
Result.count := ordersDB.UniQuery1.FieldByName('total_count').AsInteger; Result.count := ordersDB.UniQuery1.FieldByName('total_count').AsInteger;
ordersDB.UniQuery1.Close; ordersDB.UniQuery1.Close;
except except
on E: Exception do on E: Exception do
begin begin
raise EXDataHttpException.Create(500, 'Unable to retrieve users: ' + E.Message); ordersDB.UniQuery1.Close;
raise EXDataHttpException.Create(
500,
'Unable to retrieve users: ' + E.Message
);
end; end;
end; end;
end; end;
function TLookupService.EditUser(const editOptions: string): string; function TLookupService.EditUser(const editOptions: string): string;
// Edits the user. // Edits the user.
// editOptions: all user information that will be changed. // editOptions: all user information that will be changed.
...@@ -1703,7 +1724,6 @@ begin ...@@ -1703,7 +1724,6 @@ begin
end; end;
function TLookupService.AddStatusSchedule(StatusType: string; order: TJSONObject; ORDER_ID: integer): string; function TLookupService.AddStatusSchedule(StatusType: string; order: TJSONObject; ORDER_ID: integer): string;
// Adds/edits orders_status_schedule table. // Adds/edits orders_status_schedule table.
// StatusType: name of the status getting added to the schedule. // StatusType: name of the status getting added to the schedule.
...@@ -1893,9 +1913,9 @@ begin ...@@ -1893,9 +1913,9 @@ begin
end; end;
function TLookupService.AddUser(userInfo: string): string; function TLookupService.AddUser(userInfo: string): string;
// Adds a user to the database // Adds a user to the database
// userInfo - user information being added
var var
user: string; user: string;
password: string; password: string;
...@@ -1908,53 +1928,54 @@ var ...@@ -1908,53 +1928,54 @@ var
QB: string; QB: string;
SQL: string; SQL: string;
dateCreated: TDateTime; dateCreated: TDateTime;
hashString: string; rightsInt: Integer;
hashPW: string;
params: TStringList; params: TStringList;
begin begin
try try
params := TStringList.Create; params := TStringList.Create;
params.StrictDelimiter := true; params.StrictDelimiter := True;
// parse the searchOptions
params.Delimiter := '&'; params.Delimiter := '&';
params.DelimitedText := userInfo; params.DelimitedText := userInfo;
dateCreated := now;
user := params.Values['username']; dateCreated := Now;
password := params.Values['password'];
full_name := params.Values['fullname']; user := params.Values['username'];
status := params.Values['status']; password := params.Values['password'];
email := params.Values['email']; full_name := params.Values['fullname'];
access := params.Values['access']; status := params.Values['status'];
rights := params.Values['rights']; email := params.Values['email'];
access := params.Values['access'];
rights := params.Values['rights'];
perspective := params.Values['perspective']; perspective := params.Values['perspective'];
QB := params.Values['QB']; QB := params.Values['QB'];
//newUser := params.Values['newuser'];
//hashString := DateTimeToStr(dateCreated) + params.Values['password']; SQL := 'SELECT * FROM users WHERE USER_NAME = ' + QuotedStr(user.ToLower);
//hashPW := THashSHA2.GetHashString(hashString, THashSHA2.TSHA2Version.SHA512).ToUpper;
SQL := 'select * from users where USER_NAME = ' + QuotedStr(params.Values['username'].toLower);
ordersDB.UniQuery1.Close; ordersDB.UniQuery1.Close;
ordersDB.UniQuery1.SQL.Text := SQL; ordersDB.UniQuery1.SQL.Text := SQL;
ordersDB.UniQuery1.Open; ordersDB.UniQuery1.Open;
if ordersDB.UniQuery1.IsEmpty then if ordersDB.UniQuery1.IsEmpty then
begin begin
ordersDB.UniQuery1.Insert; ordersDB.UniQuery1.Insert;
ordersDB.UniQuery1.FieldByName('USER_NAME').AsString := user; ordersDB.UniQuery1.FieldByName('USER_NAME').AsString := user;
ordersDB.UniQuery1.FieldByName('PASSWORD').AsString := password; ordersDB.UniQuery1.FieldByName('PASSWORD').AsString := password;
//THashSHA2.GetHashString(hashString, THashSHA2.TSHA2Version.SHA512).ToUpper; ordersDB.UniQuery1.FieldByName('NAME').AsString := full_name;
//ordersDB.UniQuery1.FieldByName('date_created').AsString := DateTimeToStr(dateCreated);
ordersDB.UniQuery1.FieldByName('NAME').AsString := full_name;
if( StrToBool(status) ) then if StrToBoolDef(status, False) then
ordersDB.UniQuery1.FieldByName('STATUS').AsString := 'ACTIVE' ordersDB.UniQuery1.FieldByName('STATUS').AsString := 'ACTIVE'
else else
ordersDB.UniQuery1.FieldByName('STATUS').AsString := 'INACTIVE'; ordersDB.UniQuery1.FieldByName('STATUS').AsString := 'INACTIVE';
ordersDB.UniQuery1.FieldByName('EMAIL').AsString := email; ordersDB.UniQuery1.FieldByName('EMAIL').AsString := email;
ordersDB.UniQuery1.FieldByName('ACCESS_TYPE').AsString := Access; ordersDB.UniQuery1.FieldByName('ACCESS_TYPE').AsString := access;
ordersDB.UniQuery1.FieldByName('SYSTEM_RIGHTS').AsInteger := StrToInt(rights);
if not TryStrToInt(rights, rightsInt) then
rightsInt := 0;
ordersDB.UniQuery1.FieldByName('SYSTEM_RIGHTS').AsInteger := rightsInt;
ordersDB.UniQuery1.FieldByName('PERSPECTIVE_ID').AsString := perspective; ordersDB.UniQuery1.FieldByName('PERSPECTIVE_ID').AsString := perspective;
ordersDB.UniQuery1.FieldByName('QB_ID').AsString := QB; ordersDB.UniQuery1.FieldByName('QB_ID').AsString := QB;
ordersDB.UniQuery1.Post; ordersDB.UniQuery1.Post;
Result := 'Success: User successfully added'; Result := 'Success: User successfully added';
...@@ -1967,6 +1988,8 @@ begin ...@@ -1967,6 +1988,8 @@ begin
end; end;
end; end;
function TLookupService.AddItem(itemInfo: string): TJSONObject; function TLookupService.AddItem(itemInfo: string): TJSONObject;
// Adds an item to the database // Adds an item to the database
// itemInfo: item info to add to database // itemInfo: item info to add to database
...@@ -2424,6 +2447,7 @@ begin ...@@ -2424,6 +2447,7 @@ begin
ordersDB.UniQuery1.Post; ordersDB.UniQuery1.Post;
end; end;
function TLookupService.getQBCustomers: TJSONArray; function TLookupService.getQBCustomers: TJSONArray;
var var
iniFile: TIniFile; iniFile: TIniFile;
...@@ -2563,6 +2587,7 @@ begin ...@@ -2563,6 +2587,7 @@ begin
end; end;
end; end;
function TLookupService.GetQBItems: TJSONArray; function TLookupService.GetQBItems: TJSONArray;
var var
restClient: TRESTClient; restClient: TRESTClient;
...@@ -2749,6 +2774,7 @@ begin ...@@ -2749,6 +2774,7 @@ begin
end; end;
end; end;
procedure TLookupService.SaveTokens(AccessToken, RefreshToken: string); procedure TLookupService.SaveTokens(AccessToken, RefreshToken: string);
var var
f: TStringList; f: TStringList;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment