Commit 61959006 by emsys

Merge branch 'mac3' into cam3

parents df22fc95 74a2acc1
...@@ -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,17 +260,12 @@ begin ...@@ -259,17 +260,12 @@ 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
// TODO implement deleting customers // TODO implement deleting customers
begin begin
ShowMessage('Deleting Customers Is Not Yet Available'); ShowErrorModal('Deleting Customers Is Not Yet Available');
end; end;
procedure TFViewAddCustomer.btnEditClick(Sender: TObject); procedure TFViewAddCustomer.btnEditClick(Sender: TObject);
...@@ -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;
EditMode(); EditMode();
...@@ -669,43 +665,6 @@ begin ...@@ -669,43 +665,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;
......
...@@ -19,7 +19,7 @@ type ...@@ -19,7 +19,7 @@ type
FUnauthorizedAccessProc: TUnauthorizedAccessProc; FUnauthorizedAccessProc: TUnauthorizedAccessProc;
public public
const clientVersion = '0.9.4'; const clientVersion = '0.9.6';
procedure InitApp(SuccessProc: TSuccessProc; procedure InitApp(SuccessProc: TSuccessProc;
UnauthorizedAccessProc: TUnauthorizedAccessProc); UnauthorizedAccessProc: TUnauthorizedAccessProc);
procedure SetClientConfig(Callback: TVersionCheckCallback); procedure SetClientConfig(Callback: TVersionCheckCallback);
......
...@@ -9,10 +9,11 @@ procedure ShowStatusMessage(const AMessage, AClass: string; const AElementId: st ...@@ -9,10 +9,11 @@ procedure ShowStatusMessage(const AMessage, AClass: string; const AElementId: st
procedure HideStatusMessage(const AElementId: string); procedure HideStatusMessage(const AElementId: string);
procedure ShowSpinner(SpinnerID: string); procedure ShowSpinner(SpinnerID: string);
procedure HideSpinner(SpinnerID: string); procedure HideSpinner(SpinnerID: string);
procedure ShowErrorModal(const msg: string); 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;
...@@ -84,9 +85,8 @@ begin ...@@ -84,9 +85,8 @@ begin
end; end;
// The $IFNDEF WIN32 was recommended by Holger to deal with any modal issues // The $IFNDEF WIN32 was recommended by Holger to deal with any modal issues
procedure ShowErrorModal(const msg: string); procedure ShowErrorModal(msg: string);
begin begin
{$IFNDEF WIN32}
asm asm
var modal = document.getElementById('main_errormodal'); var modal = document.getElementById('main_errormodal');
var label = document.getElementById('main_lblmodal_body'); var label = document.getElementById('main_lblmodal_body');
...@@ -110,13 +110,9 @@ begin ...@@ -110,13 +110,9 @@ begin
var bsModal = new bootstrap.Modal(modal, { keyboard: false }); var bsModal = new bootstrap.Modal(modal, { keyboard: false });
bsModal.show(); bsModal.show();
end; end;
{$ENDIF}
end; end;
function CalculateAge(DateOfBirth: TDateTime): Integer; function CalculateAge(DateOfBirth: TDateTime): Integer;
var var
Today, BirthDate: TJSDate; Today, BirthDate: TJSDate;
...@@ -160,6 +156,71 @@ begin ...@@ -160,6 +156,71 @@ 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');
toastEl.classList.remove('slide-in');
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');
}
// Add slide-in animation
toastEl.classList.add('slide-in');
var toast = new bootstrap.Toast(toastEl, { delay: 2500 });
toast.show();
// Remove animation class after it's done (so it can be reapplied)
setTimeout(function() {
toastEl.classList.remove('slide-in');
}, 500);
end;
end;
procedure ApplyReportTitle(CurrentReportType: string); procedure ApplyReportTitle(CurrentReportType: string);
var var
CrimeTitleElement: TJSHTMLElement; CrimeTitleElement: TJSHTMLElement;
......
object FAddOrder: TFAddOrder object FAddOrder: TFAddOrder
Width = 871 Width = 871
Height = 477 Height = 428
OnShow = WebFormShow OnShow = WebFormShow
object WebLabel1: TWebLabel object WebLabel1: TWebLabel
Left = 4 Left = 4
Top = 81 Top = 49
Width = 95 Width = 95
Height = 15 Height = 15
Caption = 'Search Customers' Caption = 'Search Customers'
...@@ -13,7 +13,7 @@ object FAddOrder: TFAddOrder ...@@ -13,7 +13,7 @@ object FAddOrder: TFAddOrder
end end
object WebLabel2: TWebLabel object WebLabel2: TWebLabel
Left = 135 Left = 135
Top = 81 Top = 49
Width = 113 Width = 113
Height = 15 Height = 15
Caption = 'Selected Customer ID' Caption = 'Selected Customer ID'
...@@ -22,7 +22,7 @@ object FAddOrder: TFAddOrder ...@@ -22,7 +22,7 @@ object FAddOrder: TFAddOrder
end end
object WebLabel3: TWebLabel object WebLabel3: TWebLabel
Left = 283 Left = 283
Top = 81 Top = 49
Width = 134 Width = 134
Height = 15 Height = 15
Caption = 'Selected Customer Name' Caption = 'Selected Customer Name'
...@@ -31,7 +31,7 @@ object FAddOrder: TFAddOrder ...@@ -31,7 +31,7 @@ object FAddOrder: TFAddOrder
end end
object edtSearch: TWebEdit object edtSearch: TWebEdit
Left = 4 Left = 4
Top = 102 Top = 70
Width = 121 Width = 121
Height = 22 Height = 22
HeightPercent = 100.000000000000000000 HeightPercent = 100.000000000000000000
...@@ -40,7 +40,7 @@ object FAddOrder: TFAddOrder ...@@ -40,7 +40,7 @@ object FAddOrder: TFAddOrder
end end
object edtID: TWebEdit object edtID: TWebEdit
Left = 135 Left = 135
Top = 102 Top = 70
Width = 142 Width = 142
Height = 22 Height = 22
ChildOrder = 1 ChildOrder = 1
...@@ -50,7 +50,7 @@ object FAddOrder: TFAddOrder ...@@ -50,7 +50,7 @@ object FAddOrder: TFAddOrder
end end
object TMSFNCGrid1: TTMSFNCGrid object TMSFNCGrid1: TTMSFNCGrid
Left = 0 Left = 0
Top = 160 Top = 111
Width = 871 Width = 871
Height = 317 Height = 317
Align = alBottom Align = alBottom
...@@ -204,10 +204,11 @@ object FAddOrder: TFAddOrder ...@@ -204,10 +204,11 @@ object FAddOrder: TFAddOrder
ScrollMode = scmItemScrolling ScrollMode = scmItemScrolling
DesignTimeSampleData = True DesignTimeSampleData = True
OnCellClick = TMSFNCGrid1CellClick OnCellClick = TMSFNCGrid1CellClick
ExplicitTop = 112
end end
object cbCorrugatedPlate: TWebCheckBox object cbCorrugatedPlate: TWebCheckBox
Left = 4 Left = 4
Top = 49 Top = 17
Width = 113 Width = 113
Height = 22 Height = 22
Caption = 'Corrugated Plate' Caption = 'Corrugated Plate'
...@@ -219,7 +220,7 @@ object FAddOrder: TFAddOrder ...@@ -219,7 +220,7 @@ object FAddOrder: TFAddOrder
end end
object cbWebPlate: TWebCheckBox object cbWebPlate: TWebCheckBox
Left = 134 Left = 134
Top = 49 Top = 17
Width = 83 Width = 83
Height = 22 Height = 22
Caption = 'Web Plate' Caption = 'Web Plate'
...@@ -230,7 +231,7 @@ object FAddOrder: TFAddOrder ...@@ -230,7 +231,7 @@ object FAddOrder: TFAddOrder
end end
object btnCancel: TWebButton object btnCancel: TWebButton
Left = 542 Left = 542
Top = 101 Top = 69
Width = 96 Width = 96
Height = 25 Height = 25
Caption = 'Cancel' Caption = 'Cancel'
...@@ -241,7 +242,7 @@ object FAddOrder: TFAddOrder ...@@ -241,7 +242,7 @@ object FAddOrder: TFAddOrder
end end
object btnConfirm: TWebButton object btnConfirm: TWebButton
Left = 436 Left = 436
Top = 101 Top = 69
Width = 96 Width = 96
Height = 25 Height = 25
Caption = 'Select' Caption = 'Select'
...@@ -252,7 +253,7 @@ object FAddOrder: TFAddOrder ...@@ -252,7 +253,7 @@ object FAddOrder: TFAddOrder
end end
object cbCuttingDie: TWebCheckBox object cbCuttingDie: TWebCheckBox
Left = 239 Left = 239
Top = 49 Top = 17
Width = 83 Width = 83
Height = 22 Height = 22
Caption = 'Cutting Die' Caption = 'Cutting Die'
...@@ -261,30 +262,9 @@ object FAddOrder: TFAddOrder ...@@ -261,30 +262,9 @@ object FAddOrder: TFAddOrder
WidthPercent = 100.000000000000000000 WidthPercent = 100.000000000000000000
OnClick = cbCuttingDieClick OnClick = cbCuttingDieClick
end end
object edtNotification: TWebEdit
Left = 4
Top = 16
Width = 510
Height = 22
HelpType = htKeyword
TabStop = False
ChildOrder = 8
ElementFont = efCSS
Enabled = False
Font.Charset = ANSI_CHARSET
Font.Color = clRed
Font.Height = -13
Font.Name = 'Arial'
Font.Style = []
HeightPercent = 100.000000000000000000
HideSelection = False
ParentFont = False
TabOrder = 1
WidthPercent = 100.000000000000000000
end
object edtName: TWebEdit object edtName: TWebEdit
Left = 283 Left = 283
Top = 102 Top = 70
Width = 142 Width = 142
Height = 22 Height = 22
ChildOrder = 1 ChildOrder = 1
......
...@@ -11,7 +11,7 @@ uses ...@@ -11,7 +11,7 @@ uses
VCL.TMSFNCGridOptions, Vcl.Controls, VCL.TMSFNCCustomControl, VCL.TMSFNCGridOptions, Vcl.Controls, VCL.TMSFNCCustomControl,
VCL.TMSFNCCustomScrollControl, VCL.TMSFNCGridData, VCL.TMSFNCCustomGrid, VCL.TMSFNCCustomScrollControl, VCL.TMSFNCGridData, VCL.TMSFNCCustomGrid,
VCL.TMSFNCGrid, Vcl.StdCtrls, WEBLib.StdCtrls, XData.Web.Client, Data.DB, VCL.TMSFNCGrid, Vcl.StdCtrls, WEBLib.StdCtrls, XData.Web.Client, Data.DB,
XData.Web.JsonDataset, XData.Web.Dataset, WEBLib.DB, ConnectionModule; XData.Web.JsonDataset, XData.Web.Dataset, WEBLib.DB, ConnectionModule, Utils;
type type
TFAddOrder = class(TWebForm) TFAddOrder = class(TWebForm)
...@@ -30,7 +30,6 @@ type ...@@ -30,7 +30,6 @@ type
xdwdsCustomersSHORT_NAME: TStringField; xdwdsCustomersSHORT_NAME: TStringField;
wdsCustomers: TWebDataSource; wdsCustomers: TWebDataSource;
cbCuttingDie: TWebCheckBox; cbCuttingDie: TWebCheckBox;
edtNotification: TWebEdit;
xdwdsCustomersstaff_fields_invoice_to: TStringField; xdwdsCustomersstaff_fields_invoice_to: TStringField;
xdwdsCustomersCUSTOMER_ID: TIntegerField; xdwdsCustomersCUSTOMER_ID: TIntegerField;
WebLabel3: TWebLabel; WebLabel3: TWebLabel;
...@@ -67,25 +66,25 @@ begin ...@@ -67,25 +66,25 @@ begin
Close; Close;
end; end;
procedure TFAddOrder.btnConfirmClick(Sender: TObject); procedure TFAddOrder.btnConfirmClick(Sender: TObject);
begin begin
confirm := true; confirm := true;
edtNotification.ElementHandle.style.setProperty('color', '#8B0000', 'important');
if ( ( not cbCorrugatedPlate.Checked ) and ( not cbWebPlate.Checked ) and ( not cbCuttingDie.Checked ) ) then if ( ( not cbCorrugatedPlate.Checked ) and ( not cbWebPlate.Checked ) and ( not cbCuttingDie.Checked ) ) then
begin begin
edtNotification.Text := 'Please Select an Order Type'; ShowToast('Please Select an Order Type', 'danger');
confirm := false; confirm := false;
end; end;
if edtID.Text = '' then if edtID.Text = '' then
begin begin
edtNotification.Text := 'Please Select a Customer'; ShowToast('Please Select a Customer', 'danger');
confirm := false; confirm := false;
end; end;
if ( ( not cbCorrugatedPlate.Checked ) and ( not cbWebPlate.Checked ) and ( not cbCuttingDie.Checked ) and (edtID.Text = '' )) then if ( ( not cbCorrugatedPlate.Checked ) and ( not cbWebPlate.Checked ) and ( not cbCuttingDie.Checked ) and (edtID.Text = '' )) then
begin begin
edtNotification.Text := 'Please Select an Order Type and a Customer'; ShowToast('Please Select an Order Type and a Customer', 'danger');
confirm := false; confirm := false;
end; end;
...@@ -95,6 +94,7 @@ begin ...@@ -95,6 +94,7 @@ begin
end; end;
end; end;
procedure TFAddOrder.WebFormShow(Sender: TObject); procedure TFAddOrder.WebFormShow(Sender: TObject);
begin begin
confirm := false; confirm := false;
...@@ -108,23 +108,27 @@ begin ...@@ -108,23 +108,27 @@ begin
cbCuttingDie.Checked := False; cbCuttingDie.Checked := False;
end; end;
procedure TFAddOrder.cbCuttingDieClick(Sender: TObject); procedure TFAddOrder.cbCuttingDieClick(Sender: TObject);
begin begin
cbCorrugatedPlate.Checked := False; cbCorrugatedPlate.Checked := False;
cbWebPlate.Checked := False; cbWebPlate.Checked := False;
end; end;
procedure TFAddOrder.cbWebPlateClick(Sender: TObject); procedure TFAddOrder.cbWebPlateClick(Sender: TObject);
begin begin
cbCorrugatedPlate.Checked := False; cbCorrugatedPlate.Checked := False;
cbCuttingDie.Checked := False; cbCuttingDie.Checked := False;
end; end;
procedure TFAddOrder.edtSearchChange(Sender: TObject); procedure TFAddOrder.edtSearchChange(Sender: TObject);
begin begin
ApplyFilter; ApplyFilter;
end; end;
[async] procedure TFAddOrder.getCustomers(); [async] procedure TFAddOrder.getCustomers();
// retrieves customer list from server // retrieves customer list from server
var var
...@@ -144,6 +148,7 @@ begin ...@@ -144,6 +148,7 @@ begin
PopulateGridManually; PopulateGridManually;
end; end;
procedure TFAddOrder.PopulateGridManually; procedure TFAddOrder.PopulateGridManually;
// populates the grid with customers manually. // populates the grid with customers manually.
var var
...@@ -191,6 +196,7 @@ begin ...@@ -191,6 +196,7 @@ begin
DBID := TMSFNCGrid1.Cells[0, ARow]; DBID := TMSFNCGrid1.Cells[0, ARow];
end; end;
procedure TFAddOrder.ApplyFilter; procedure TFAddOrder.ApplyFilter;
// filters the grid based on search textbox contents. // filters the grid based on search textbox contents.
var var
......
...@@ -42,6 +42,7 @@ object FViewCustomers: TFViewCustomers ...@@ -42,6 +42,7 @@ object FViewCustomers: TFViewCustomers
HeightPercent = 100.000000000000000000 HeightPercent = 100.000000000000000000
Text = '500' Text = '500'
WidthPercent = 100.000000000000000000 WidthPercent = 100.000000000000000000
OnChange = wcbPageSizeChange
ItemIndex = -1 ItemIndex = -1
Items.Strings = ( Items.Strings = (
'100' '100'
......
<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)
...@@ -36,13 +36,13 @@ type ...@@ -36,13 +36,13 @@ type
procedure btnAddCustomerClick(Sender: TObject); procedure btnAddCustomerClick(Sender: TObject);
procedure wdbtcCustomersDblClickCell(Sender: TObject; ACol, ARow: Integer); procedure wdbtcCustomersDblClickCell(Sender: TObject; ACol, ARow: Integer);
procedure edtFilterChange(Sender: TObject); procedure edtFilterChange(Sender: TObject);
procedure wcbPageSizeChange(Sender: TObject);
private private
{ Private declarations } { Private declarations }
procedure GeneratePagination(TotalPages: Integer); procedure GeneratePagination(TotalPages: Integer);
[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 +75,7 @@ begin ...@@ -75,6 +75,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 +174,13 @@ begin ...@@ -173,34 +174,13 @@ begin
end; end;
procedure TFViewCustomers.ShowNotification(Notification: string); procedure TFViewCustomers.wcbPageSizeChange(Sender: TObject);
var
splitNotification: TArray<string>;
begin begin
if Notification <> '' then PageSize := StrToInt(wcbPageSize.Text);
begin getCustomers(GenerateSearchOptions());
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;
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,22 @@ ...@@ -47,7 +47,22 @@
</div> </div>
</div> </div>
</nav> </nav>
<!-- Toast wrapper directly under navbar -->
<div id="toast-wrapper"
class="position-fixed top-0 start-0 mt-5 ms-4"
style="z-index: 1080; 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 +101,25 @@ ...@@ -86,6 +101,25 @@
</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>
......
...@@ -6,7 +6,7 @@ uses ...@@ -6,7 +6,7 @@ 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, WEBLib.ExtCtrls, Vcl.Controls, Vcl.StdCtrls, WEBLib.Forms, WEBLib.Dialogs, WEBLib.ExtCtrls, Vcl.Controls, Vcl.StdCtrls,
WEBLib.StdCtrls, Data.DB, XData.Web.JsonDataset, XData.Web.Dataset, WEBLib.StdCtrls, Data.DB, XData.Web.JsonDataset, XData.Web.Dataset,
App.Types, ConnectionModule, XData.Web.Client, WEBLib.Menus; App.Types, ConnectionModule, XData.Web.Client, WEBLib.Menus, Utils;
type type
TFViewMain = class(TWebForm) TFViewMain = class(TWebForm)
...@@ -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);
...@@ -101,7 +103,6 @@ begin ...@@ -101,7 +103,6 @@ begin
ShowForm(TFViewOrders); ShowForm(TFViewOrders);
lblAppTitle.Caption := 'Koehler-Gibson Orders'; lblAppTitle.Caption := 'Koehler-Gibson Orders';
lblVersion.Caption := 'v' + DMConnection.clientVersion; lblVersion.Caption := 'v' + DMConnection.clientVersion;
setActive('Orders'); setActive('Orders');
end; end;
...@@ -117,7 +118,7 @@ begin ...@@ -117,7 +118,7 @@ begin
setActive('Customers'); setActive('Customers');
end end
else else
ShowMessage('Please Save or Cancel your changes'); ShowErrorModal('Please Save or Cancel your changes');
end; end;
procedure TFViewMain.lblHomeClick(Sender: TObject); procedure TFViewMain.lblHomeClick(Sender: TObject);
...@@ -129,7 +130,7 @@ begin ...@@ -129,7 +130,7 @@ begin
//setActive('Home'); //setActive('Home');
end end
else else
ShowMessage('Please Save or Cancel your changes'); ShowErrorModal('Please Save or Cancel your changes');
end; end;
procedure TFViewMain.lblordersClick(Sender: TObject); procedure TFViewMain.lblordersClick(Sender: TObject);
...@@ -142,7 +143,7 @@ begin ...@@ -142,7 +143,7 @@ begin
setActive('Orders'); setActive('Orders');
end end
else else
ShowMessage('Please Save or Cancel your changes'); ShowErrorModal('Please Save or Cancel your changes');
end; end;
procedure TFViewMain.lblQuickbooksClick(Sender: TObject); procedure TFViewMain.lblQuickbooksClick(Sender: TObject);
...@@ -154,7 +155,7 @@ begin ...@@ -154,7 +155,7 @@ begin
setActive('QuickBooks'); setActive('QuickBooks');
end end
else else
ShowMessage('Please Save or Cancel your changes'); ShowErrorModal('Please Save or Cancel your changes');
end; end;
procedure TFViewMain.lblUsersClick(Sender: TObject); procedure TFViewMain.lblUsersClick(Sender: TObject);
...@@ -165,7 +166,7 @@ begin ...@@ -165,7 +166,7 @@ begin
lblAppTitle.Caption := 'Koehler-Gibson Users'; lblAppTitle.Caption := 'Koehler-Gibson Users';
end end
else else
ShowMessage('Please Save or Cancel your changes'); ShowErrorModal('Please Save or Cancel your changes');
end; end;
procedure TFViewMain.lblItemsListClick(Sender: TObject); procedure TFViewMain.lblItemsListClick(Sender: TObject);
...@@ -177,7 +178,7 @@ begin ...@@ -177,7 +178,7 @@ begin
setActive('Items'); setActive('Items');
end end
else else
ShowMessage('Please Save or Cancel your changes'); ShowErrorModal('Please Save or Cancel your changes');
end; end;
procedure TFViewMain.setActive(page: string); procedure TFViewMain.setActive(page: string);
...@@ -200,15 +201,55 @@ end; ...@@ -200,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
...@@ -385,6 +350,7 @@ object FOrderEntryCorrugated: TFOrderEntryCorrugated ...@@ -385,6 +350,7 @@ object FOrderEntryCorrugated: TFOrderEntryCorrugated
HeightPercent = 100.000000000000000000 HeightPercent = 100.000000000000000000
HideSelection = False HideSelection = False
WidthPercent = 100.000000000000000000 WidthPercent = 100.000000000000000000
OnChange = edtJobNameChange
DataField = 'staff_fields_job_name' DataField = 'staff_fields_job_name'
DataSource = WebDataSource1 DataSource = WebDataSource1
end end
...@@ -1190,7 +1156,7 @@ object FOrderEntryCorrugated: TFOrderEntryCorrugated ...@@ -1190,7 +1156,7 @@ object FOrderEntryCorrugated: TFOrderEntryCorrugated
HeightPercent = 100.000000000000000000 HeightPercent = 100.000000000000000000
WidthPercent = 100.000000000000000000 WidthPercent = 100.000000000000000000
end end
object btn_confirm_delete: TWebButton object btn_modal_confirm: TWebButton
Left = 1094 Left = 1094
Top = 414 Top = 414
Width = 96 Width = 96
...@@ -1200,7 +1166,7 @@ object FOrderEntryCorrugated: TFOrderEntryCorrugated ...@@ -1200,7 +1166,7 @@ object FOrderEntryCorrugated: TFOrderEntryCorrugated
ElementID = 'btn_confirm_delete' ElementID = 'btn_confirm_delete'
HeightPercent = 100.000000000000000000 HeightPercent = 100.000000000000000000
WidthPercent = 100.000000000000000000 WidthPercent = 100.000000000000000000
OnClick = btn_confirm_deleteClick OnClick = btn_modal_confirmClick
end end
object btnEdit: TWebButton object btnEdit: TWebButton
Left = 1202 Left = 1202
......
<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>
...@@ -220,7 +215,7 @@ ...@@ -220,7 +215,7 @@
<hr class="custom-hr"> <hr class="custom-hr">
<div class="row"> <div class="row">
<div class="col-auto"> <div class="col-auto">
<label for="wdbe_first_name" class="form-label mt-2">Loose:</label> <label for="wdbe_first_name" style="font-weight: 700; font-size: 15px;" class="form-label mt-2">Loose:</label>
<input type="checkbox" id="cbloose"> <input type="checkbox" id="cbloose">
<input id="edtloose" class="form-control input-sm" style="width: 150px"/> <input id="edtloose" class="form-control input-sm" style="width: 150px"/>
</div> </div>
...@@ -367,23 +362,18 @@ ...@@ -367,23 +362,18 @@
<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 shadow-lg">
<div class="modal-header"> <div class="modal-header">
<h5 class="modal-title" id="confirmation_modal_label">Confirm</h5> <h5 class="modal-title" id="confirmation_modal_label">Confirm</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button> <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div> </div>
<div class="modal-body" id="modal_body"> <div class="modal-body fs-6 fw-bold" id="modal_body">
Are you sure you want to delete this order? Are you sure you want to delete this order?
</div> </div>
<div class="modal-footer"> <div class="modal-footer justify-content-center">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal" id= 'btn_confirm_cancel'>Cancel</button> <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> <button type="button" class="btn btn-primary" data-bs-dismiss="modal" id="btn_confirm_delete">Delete</button>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
<style>
.modal-backdrop {
opacity: 0 !important;
}
</style>
...@@ -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;
...@@ -198,14 +195,12 @@ type ...@@ -198,14 +195,12 @@ type
btnDelete: TWebButton; btnDelete: TWebButton;
btnClose: TWebButton; btnClose: TWebButton;
edtOrderNum: TWebEdit; edtOrderNum: TWebEdit;
btn_confirm_delete: TWebButton; btn_modal_confirm: TWebButton;
tmrReturn: TWebTimer; tmrReturn: TWebTimer;
btnEdit: TWebButton; btnEdit: TWebButton;
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,9 +216,8 @@ type ...@@ -221,9 +216,8 @@ 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_modal_confirmClick(Sender: TObject);
procedure tmrReturnTimer(Sender: TObject); procedure tmrReturnTimer(Sender: TObject);
function VerifyOrder(): boolean; function VerifyOrder(): boolean;
procedure XDataWebDataSet1AfterEdit(DataSet: TDataSet); procedure XDataWebDataSet1AfterEdit(DataSet: TDataSet);
...@@ -242,7 +236,9 @@ type ...@@ -242,7 +236,9 @@ type
procedure WebButton2Click(Sender: TObject); procedure WebButton2Click(Sender: TObject);
procedure ShowAddAddressForm(); procedure ShowAddAddressForm();
[async] procedure SendAddressToServer(AddressJSON: TJSONObject); [async] procedure SendAddressToServer(AddressJSON: TJSONObject);
procedure edtJobNameChange(Sender: TObject);
private private
FModalAction: string;
FAgencyCode: string; FAgencyCode: string;
FCurrentReportType: string; FCurrentReportType: string;
FSelectProc: TSelectProc; FSelectProc: TSelectProc;
...@@ -251,6 +247,7 @@ type ...@@ -251,6 +247,7 @@ type
mode: string; mode: string;
changed: boolean; changed: boolean;
notification: string; notification: string;
procedure RemoveColorRow(Sender: TObject);
//FJSONProc1: TJSONProc1; //FJSONProc1: TJSONProc1;
public public
class function CreateForm(AElementID, orderInfo, customerInfo, mode, info: string): TWebForm; class function CreateForm(AElementID, orderInfo, customerInfo, mode, info: string): TWebForm;
...@@ -266,6 +263,7 @@ implementation ...@@ -266,6 +263,7 @@ implementation
uses uses
View.Home, View.Main, View.AddOrder, View.AddAddress, Utils; View.Home, View.Main, View.AddOrder, View.AddAddress, Utils;
procedure TFOrderEntryCorrugated.sendOrderToServer(); procedure TFOrderEntryCorrugated.sendOrderToServer();
// This can be improved. I was struggling to get the checkboxes to work with // This can be improved. I was struggling to get the checkboxes to work with
// The dataset at first, but if you just change the fields in the database to be // The dataset at first, but if you just change the fields in the database to be
...@@ -383,7 +381,11 @@ begin ...@@ -383,7 +381,11 @@ begin
if Field is TStringField then if Field is TStringField then
begin begin
if Field.AsString = '' then if Field.AsString = '' then
orderJSON.AddPair(Field.FieldName, '') begin
orderJSON.AddPair(Field.FieldName, '');
console.log(Field.FieldName);
console.log(Field.AsString);
end
else else
orderJSON.AddPair(Field.FieldName, Field.AsString); // Add all other fields orderJSON.AddPair(Field.FieldName, Field.AsString); // Add all other fields
end end
...@@ -404,9 +406,9 @@ begin ...@@ -404,9 +406,9 @@ begin
orderJSON.AddPair('ORDER_ID', orderID); orderJSON.AddPair('ORDER_ID', orderID);
AddCorrugatedOrder(orderJSON); AddCorrugatedOrder(orderJSON);
end; end;
procedure TFOrderEntryCorrugated.btnSaveClick(Sender: TObject); procedure TFOrderEntryCorrugated.btnSaveClick(Sender: TObject);
// Converts all the information on the page into a JSON to then send to the server // Converts all the information on the page into a JSON to then send to the server
begin begin
...@@ -432,7 +434,6 @@ begin ...@@ -432,7 +434,6 @@ begin
else else
input.classList.remove('is-invalid'); input.classList.remove('is-invalid');
input := TJSHTMLInputElement(document.getElementById('edtaccountcompanyname')); input := TJSHTMLInputElement(document.getElementById('edtaccountcompanyname'));
if edtCompanyAccountName.Text = '' then if edtCompanyAccountName.Text = '' then
begin begin
...@@ -472,6 +473,7 @@ begin ...@@ -472,6 +473,7 @@ begin
input.classList.remove('is-invalid'); input.classList.remove('is-invalid');
end; end;
procedure TFOrderEntryCorrugated.btnCopyClick(Sender: TObject); procedure TFOrderEntryCorrugated.btnCopyClick(Sender: TObject);
begin begin
mode := 'ADD'; mode := 'ADD';
...@@ -485,67 +487,72 @@ begin ...@@ -485,67 +487,72 @@ 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;
procedure TFOrderEntryCorrugated.btnDeleteClick(Sender: TObject); procedure TFOrderEntryCorrugated.btnDeleteClick(Sender: TObject);
begin begin
FModalAction := 'delete';
document.getElementById('modal_body').innerHTML := 'Are you sure you want to delete this order?'; document.getElementById('modal_body').innerHTML := 'Are you sure you want to delete this order?';
document.getElementById('btn_confirm_cancel').innerText := 'Cancel'; document.getElementById('btn_confirm_cancel').innerText := 'Cancel';
document.getElementById('btn_confirm_delete').innerText := 'Delete'; document.getElementById('btn_confirm_delete').innerText := 'Delete';
asm asm
var confirmationModal = new bootstrap.Modal(document.getElementById('confirmation_modal'), { var modal = document.getElementById('confirmation_modal');
keyboard: false }); 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;
procedure TFOrderEntryCorrugated.btnEditClick(Sender: TObject); procedure TFOrderEntryCorrugated.btnEditClick(Sender: TObject);
begin begin
EditMode(); EditMode();
end; end;
procedure TFOrderEntryCorrugated.btnPDFClick(Sender: TObject); procedure TFOrderEntryCorrugated.btnPDFClick(Sender: TObject);
begin 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_modal_confirmClick(Sender: TObject);
begin begin
if document.getElementById('btn_confirm_delete').innerText = 'Yes' then if FModalAction = 'cancel' then
begin begin
FViewMain.change := false; FViewMain.change := false;
if OrderID <> '' then if OrderID <> '' then
begin FViewMain.ViewOrderEntryCorrugated(OrderID, '', 'EDIT', 'Failure: Changes Discarded')
FViewMain.ViewOrderEntryCorrugated(OrderID, '', 'EDIT', 'Failure:Changes Discarded');
end
else else
FViewMain.ViewOrders(''); FViewMain.ViewOrders('');
end end
else else if FModalAction = 'delete' then
begin begin
Utils.ShowSpinner('spinner'); Utils.ShowSpinner('spinner');
asm asm
var modal = document.getElementById('confirmation_modal'); var modal = document.getElementById('confirmation_modal');
// ensure the modal lives directly under <body>
if (modal && modal.parentNode !== document.body) { if (modal && modal.parentNode !== document.body) {
document.body.appendChild(modal); document.body.appendChild(modal);
} }
var bsModal = new bootstrap.Modal(modal, { keyboard: false });
var bsModal = new bootstrap.Modal(modal, {
keyboard: false
});
bsModal.hide(); bsModal.hide();
end; end;
delOrder(); DelOrder();
tmrReturn.Enabled := true; tmrReturn.Enabled := true;
end; end;
end; end;
[async] procedure TFOrderEntryCorrugated.GenerateReportPDF; [async] procedure TFOrderEntryCorrugated.GenerateReportPDF;
// sends the search to the server which then sends back a pdf of the results // sends the search to the server which then sends back a pdf of the results
var var
...@@ -575,6 +582,7 @@ var ...@@ -575,6 +582,7 @@ var
Response: TXDataClientResponse; Response: TXDataClientResponse;
jsObj: TJSObject; jsObj: TJSObject;
begin begin
console.log(orderJSON);
Response := await(XDataWebClient1.RawInvokeAsync('ILookupService.AddCorrugatedOrder', Response := await(XDataWebClient1.RawInvokeAsync('ILookupService.AddCorrugatedOrder',
[orderJSON.ToString])); [orderJSON.ToString]));
jsObj := JS.TJSObject(Response.Result); jsObj := JS.TJSObject(Response.Result);
...@@ -582,11 +590,10 @@ begin ...@@ -582,11 +590,10 @@ begin
OrderID := String(jsObj.Properties['OrderID']); OrderID := String(jsObj.Properties['OrderID']);
edtOrderNum.Text := OrderID; edtOrderNum.Text := OrderID;
mode := 'EDIT'; mode := 'EDIT';
console.log(jsObj); ShowToast(string(jsObj.Properties['status']));
ShowNotification(string(jsObj.Properties['status']));
end; end;
procedure TFOrderEntryCorrugated.DelOrder(); procedure TFOrderEntryCorrugated.DelOrder();
var var
Response: TXDataClientResponse; Response: TXDataClientResponse;
...@@ -620,70 +627,94 @@ begin ...@@ -620,70 +627,94 @@ begin
); );
end; end;
procedure TFOrderEntryCorrugated.addColorRow(num: string; Color: string; LPI: string; Size: string);
// Java script code to add a row of colors when a button is clicked procedure TFOrderEntryCorrugated.addColorRow(num, color, LPI, size: string);
// all variables are information to be placed in the boxes when loading an order. var
// TODO: convert to Delphi container, newRow, col, labelEl, inputEl, removeCol: TJSHTMLElement;
removeBtn: TWebButton;
values: array[0..3] of string;
labels: array[0..3] of string;
i: Integer;
begin begin
asm container := TJSHTMLElement(document.getElementById('additionalFields'));
const container = document.getElementById('additionalFields');
// Create the new row container
// Create a new row for the new fields newRow := TJSHTMLElement(document.createElement('div'));
const newRow = document.createElement('div'); newRow.className := 'row mb-2';
newRow.className = 'row mb-2';
labels[0] := '#'; values[0] := num;
const labels = ['#', 'Color', 'LPI', 'Size']; labels[1] := 'Color'; values[1] := color;
const values = [num, Color, LPI, Size]; labels[2] := 'LPI'; values[2] := LPI;
labels.forEach((label, index) => { labels[3] := 'Size'; values[3] := size;
const col = document.createElement('div');
col.className = 'col-sm'; for i := 0 to 3 do
begin
const labelElement = document.createElement('label'); col := TJSHTMLElement(document.createElement('div'));
labelElement.className = 'pe-2'; col.className := 'col-sm';
labelElement.style.fontWeight = '700';
labelElement.style.fontSize = '15px'; labelEl := TJSHTMLElement(document.createElement('label'));
labelElement.textContent = label + ':'; labelEl.className := 'pe-2';
labelEl.style.setProperty('font-weight', '700');
const inputElement = document.createElement('input'); labelEl.style.setProperty('font-size', '15px');
inputElement.className = 'form-control input-sm'; labelEl.textContent := labels[i] + ':';
inputElement.style.width = '100%';
inputElement.id = 'input-' + container.childElementCount + '-' + index; // Unique ID based on count inputEl := TJSHTMLElement(document.createElement('input'));
inputElement.value = values[index]; // Set the value based on the parameter inputEl.className := 'form-control input-sm';
inputEl.setAttribute('style', 'width: 100%');
col.appendChild(labelElement); inputEl.setAttribute('value', values[i]);
col.appendChild(inputElement); inputEl.setAttribute('id', 'input-' + IntToStr(container.childElementCount) + '-' + IntToStr(i));
newRow.appendChild(col); col.appendChild(labelEl);
}); col.appendChild(inputEl);
newRow.appendChild(col);
const removeButtonCol = document.createElement('div'); end;
removeButtonCol.className = 'col-auto d-flex align-items-center mt-3';
// Add remove button
const removeButton = document.createElement('button'); removeCol := TJSHTMLElement(document.createElement('div'));
removeButton.className = 'btn btn-danger btn-sm mt-1'; removeCol.className := 'col-auto d-flex align-items-end pb-1';
removeButton.textContent = 'Remove';
removeButton.addEventListener('click', function() { removeBtn := TWebButton.Create(Self);
container.removeChild(newRow); removeBtn.Caption := 'Remove';
}); removeBtn.ElementClassName := 'btn btn-danger btn-sm mt-1';
removeBtn.ParentElement := removeCol;
removeButtonCol.appendChild(removeButton); removeBtn.ElementHandle.style.setProperty('height', '30px');
newRow.appendChild(removeButtonCol); removeBtn.OnClick := RemoveColorRow;
container.appendChild(newRow); newRow.appendChild(removeCol);
end; container.appendChild(newRow);
end;
procedure TFOrderEntryCorrugated.RemoveColorRow(Sender: TObject);
var
btn: TWebButton;
rowElement: TJSHTMLElement;
begin
EditMode();
btn := TWebButton(Sender);
if Assigned(btn.ElementHandle) and Assigned(btn.ElementHandle.parentElement) then
begin
// Assuming button is inside a <div> inside the row
rowElement := TJSHTMLElement(btn.ElementHandle.parentElement.parentElement);
if Assigned(rowElement) then
rowElement.remove;
end;
end; end;
procedure TFOrderEntryCorrugated.btnAddColorClick(Sender: TObject); procedure TFOrderEntryCorrugated.btnAddColorClick(Sender: TObject);
begin begin
EditMode(); EditMode();
addColorRow('','','',''); addColorRow('','','','');
end; end;
procedure TFOrderEntryCorrugated.WebButton2Click(Sender: TObject); procedure TFOrderEntryCorrugated.WebButton2Click(Sender: TObject);
begin begin
ShowAddAddressForm(); ShowAddAddressForm();
end; end;
procedure TFOrderEntryCorrugated.SendAddressToServer(AddressJSON: TJSONObject); procedure TFOrderEntryCorrugated.SendAddressToServer(AddressJSON: TJSONObject);
var var
Response: TXDataClientResponse; Response: TXDataClientResponse;
...@@ -693,12 +724,13 @@ begin ...@@ -693,12 +724,13 @@ 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;
end; end;
procedure TFOrderEntryCorrugated.ShowAddAddressForm; procedure TFOrderEntryCorrugated.ShowAddAddressForm;
// displays the search pop-up that allows the user to filter the order list // displays the search pop-up that allows the user to filter the order list
var var
...@@ -710,6 +742,7 @@ begin ...@@ -710,6 +742,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
...@@ -755,6 +788,7 @@ begin ...@@ -755,6 +788,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
...@@ -783,28 +817,31 @@ begin ...@@ -783,28 +817,31 @@ begin
); );
end; end;
procedure TFOrderEntryCorrugated.btnCancelClick(Sender: TObject); procedure TFOrderEntryCorrugated.btnCancelClick(Sender: TObject);
begin begin
console.log('click'); FModalAction := 'cancel';
document.getElementById('modal_body').innerHTML := 'Are you sure you want to cancel all changes?'; document.getElementById('modal_body').innerHTML := 'Are you sure you want to cancel all changes?';
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 }); 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;
procedure TFOrderEntryCorrugated.btnCloseClick(Sender: TObject); procedure TFOrderEntryCorrugated.btnCloseClick(Sender: TObject);
begin 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
...@@ -815,6 +852,7 @@ begin ...@@ -815,6 +852,7 @@ begin
end; end;
end; end;
procedure TFOrderEntryCorrugated.getOrder(Order_ID: string); procedure TFOrderEntryCorrugated.getOrder(Order_ID: string);
// retrieves an order from the server then loads the info into the page // retrieves an order from the server then loads the info into the page
var var
...@@ -971,6 +1009,7 @@ begin ...@@ -971,6 +1009,7 @@ begin
end; end;
end; end;
procedure TFOrderEntryCorrugated.getCustomer(customerID: string); procedure TFOrderEntryCorrugated.getCustomer(customerID: string);
// gets a customer from the database then loads the appropiate fields // gets a customer from the database then loads the appropiate fields
var var
...@@ -985,8 +1024,7 @@ begin ...@@ -985,8 +1024,7 @@ begin
XDataWebDataSet1.Close; XDataWebDataSet1.Close;
XDataWebDataSet1.SetJsonData(customer); XDataWebDataSet1.SetJsonData(customer);
XDataWebDataSet1.Open; XDataWebDataSet1.Open;
XDataWebDataSet1.Edit;
xdwdsShipTo.Close; xdwdsShipTo.Close;
xdwdsShipTo.SetJSONData(customer['ADDRESS_LIST']); xdwdsShipTo.SetJSONData(customer['ADDRESS_LIST']);
...@@ -1010,6 +1048,7 @@ begin ...@@ -1010,6 +1048,7 @@ begin
end; end;
end; end;
procedure TFOrderEntryCorrugated.WebFormShow(Sender: TObject); procedure TFOrderEntryCorrugated.WebFormShow(Sender: TObject);
begin begin
if mode <> 'ADD' then if mode <> 'ADD' then
...@@ -1023,66 +1062,30 @@ begin ...@@ -1023,66 +1062,30 @@ 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;
procedure TFOrderEntryCorrugated.XDataWebDataSet1AfterEdit(DataSet: TDataSet); procedure TFOrderEntryCorrugated.XDataWebDataSet1AfterEdit(DataSet: TDataSet);
begin begin
EditMode(); EditMode();
end; end;
procedure TFOrderEntryCorrugated.xdwdsQBItemAfterEdit(DataSet: TDataSet); procedure TFOrderEntryCorrugated.xdwdsQBItemAfterEdit(DataSet: TDataSet);
begin begin
EditMode(); EditMode();
end; end;
procedure TFOrderEntryCorrugated.xdwdsShipToAfterEdit(DataSet: TDataSet); procedure TFOrderEntryCorrugated.xdwdsShipToAfterEdit(DataSet: TDataSet);
begin 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
...@@ -1091,12 +1094,14 @@ begin ...@@ -1091,12 +1094,14 @@ begin
FViewMain.ViewOrders('Success: Order Successfully Deleted'); FViewMain.ViewOrders('Success: Order Successfully Deleted');
end; end;
procedure TFOrderEntryCorrugated.tmrScrollTopTimer(Sender: TObject); procedure TFOrderEntryCorrugated.tmrScrollTopTimer(Sender: TObject);
begin begin
tmrScrollTop.Enabled := False; tmrScrollTop.Enabled := False;
window.scrollTo(0, 0); window.scrollTo(0, 0);
end; end;
procedure TFOrderEntryCorrugated.EditMode(); procedure TFOrderEntryCorrugated.EditMode();
begin begin
FViewMain.change := true; FViewMain.change := true;
...@@ -1110,6 +1115,12 @@ begin ...@@ -1110,6 +1115,12 @@ begin
btnAdd.Enabled := false; btnAdd.Enabled := false;
end; end;
procedure TFOrderEntryCorrugated.edtJobNameChange(Sender: TObject);
begin
EditMode();
console.log('onChange');
end;
procedure TFOrderEntryCorrugated.dtpApprovedDateChange(Sender: TObject); procedure TFOrderEntryCorrugated.dtpApprovedDateChange(Sender: TObject);
begin begin
EditMode(); EditMode();
......
...@@ -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
...@@ -400,14 +363,15 @@ object FOrderEntryCuttingDie: TFOrderEntryCuttingDie ...@@ -400,14 +363,15 @@ object FOrderEntryCuttingDie: TFOrderEntryCuttingDie
end end
object WebDataSource1: TWebDataSource object WebDataSource1: TWebDataSource
DataSet = XDataWebDataSet1 DataSet = XDataWebDataSet1
Left = 22 OnDataChange = WebDataSource1DataChange
Top = 10 Left = 318
Top = 262
end end
object XDataWebDataSet1: TXDataWebDataSet object XDataWebDataSet1: TXDataWebDataSet
AfterEdit = XDataWebDataSet1AfterEdit AfterEdit = XDataWebDataSet1AfterEdit
Connection = DMConnection.ApiConnection Connection = DMConnection.ApiConnection
Left = 90 Left = 318
Top = 20 Top = 208
object XDataWebDataSet1COMPANY_ID: TIntegerField object XDataWebDataSet1COMPANY_ID: TIntegerField
FieldName = 'COMPANY_ID' FieldName = 'COMPANY_ID'
end end
...@@ -471,8 +435,8 @@ object FOrderEntryCuttingDie: TFOrderEntryCuttingDie ...@@ -471,8 +435,8 @@ object FOrderEntryCuttingDie: TFOrderEntryCuttingDie
end end
object XDataWebClient1: TXDataWebClient object XDataWebClient1: TXDataWebClient
Connection = DMConnection.ApiConnection Connection = DMConnection.ApiConnection
Left = 192 Left = 218
Top = 92 Top = 76
end end
object tmrScrollTop: TWebTimer object tmrScrollTop: TWebTimer
Interval = 100 Interval = 100
...@@ -487,21 +451,21 @@ object FOrderEntryCuttingDie: TFOrderEntryCuttingDie ...@@ -487,21 +451,21 @@ object FOrderEntryCuttingDie: TFOrderEntryCuttingDie
end end
object xdwdsShipTo: TXDataWebDataSet object xdwdsShipTo: TXDataWebDataSet
AfterEdit = xdwdsShipToAfterEdit AfterEdit = xdwdsShipToAfterEdit
Left = 288 Left = 438
Top = 370 Top = 208
object xdwdsShipToADDRESS: TStringField object xdwdsShipToADDRESS: TStringField
FieldName = 'ADDRESS' FieldName = 'ADDRESS'
end end
end end
object wdsQBItem: TWebDataSource object wdsQBItem: TWebDataSource
DataSet = xdwdsQBItem DataSet = xdwdsQBItem
Left = 230 Left = 272
Top = 554 Top = 548
end end
object xdwdsQBItem: TXDataWebDataSet object xdwdsQBItem: TXDataWebDataSet
AfterEdit = xdwdsQBItemAfterEdit AfterEdit = xdwdsQBItemAfterEdit
Left = 190 Left = 568
Top = 548 Top = 216
object xdwdsQBItemname: TStringField object xdwdsQBItemname: TStringField
FieldName = 'name' FieldName = 'name'
end end
......
<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>
...@@ -131,24 +126,18 @@ ...@@ -131,24 +126,18 @@
</div> </div>
<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 shadow-lg">
<div class="modal-header"> <div class="modal-header">
<h5 class="modal-title" id="confirmation_modal_label">Confirm</h5> <h5 class="modal-title" id="confirmation_modal_label">Confirm</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button> <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div> </div>
<div class="modal-body" id="modal_body"> <div class="modal-body fs-6 fw-bold" id="modal_body">
Are you sure you want to delete this order? Are you sure you want to delete this order?
</div> </div>
<div class="modal-footer"> <div class="modal-footer justify-content-center">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal" id=btn_confirm_cancel>Cancel</button> <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> <button type="button" class="btn btn-primary" data-bs-dismiss="modal" id="btn_confirm_delete">Delete</button>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
</div>
<style>
.modal-backdrop {
opacity: 0 !important;
}
</style>
unit View.OrderEntryCuttingDie; unit View.OrderEntryCuttingDie;
interface interface
...@@ -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);
...@@ -98,14 +93,16 @@ type ...@@ -98,14 +93,16 @@ type
procedure xdwdsShipToAfterEdit(DataSet: TDataSet); procedure xdwdsShipToAfterEdit(DataSet: TDataSet);
procedure EditMode(); procedure EditMode();
procedure xdwdsQBItemAfterEdit(DataSet: TDataSet); procedure xdwdsQBItemAfterEdit(DataSet: TDataSet);
procedure XDataWebDataSet1AfterEdit(DataSet: TDataSet);
procedure dtpOrderDateChange(Sender: TObject); procedure dtpOrderDateChange(Sender: TObject);
procedure btnEditClick(Sender: TObject); procedure btnEditClick(Sender: TObject);
procedure ViewMode(); procedure ViewMode();
procedure WebButton2Click(Sender: TObject); procedure WebButton2Click(Sender: TObject);
procedure ShowAddAddressForm(); procedure ShowAddAddressForm();
[async] procedure SendAddressToServer(AddressJSON: TJSONObject); [async] procedure SendAddressToServer(AddressJSON: TJSONObject);
procedure WebDataSource1DataChange(Sender: TObject; Field: TField);
procedure XDataWebDataSet1AfterEdit(DataSet: TDataSet);
private private
FModalAction: string;
FAgencyCode: string; FAgencyCode: string;
FCurrentReportType: string; FCurrentReportType: string;
FSelectProc: TSelectProc; FSelectProc: TSelectProc;
...@@ -132,6 +129,20 @@ begin ...@@ -132,6 +129,20 @@ begin
ShowAddAddressForm(); ShowAddAddressForm();
end; end;
procedure TFOrderEntryCuttingDie.WebDataSource1DataChange(Sender: TObject; Field: TField);
begin
if Assigned(Field) then
console.log(
'Field.OnChange → ' + Field.FieldName +
' is now: ' + Field.AsString
)
else
console.log('WebDataSource1.OnDataChange fired with no specific Field');
end;
procedure TFOrderEntryCuttingDie.SendAddressToServer(AddressJSON: TJSONObject); procedure TFOrderEntryCuttingDie.SendAddressToServer(AddressJSON: TJSONObject);
var var
Response: TXDataClientResponse; Response: TXDataClientResponse;
...@@ -141,12 +152,13 @@ begin ...@@ -141,12 +152,13 @@ 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;
end; end;
procedure TFOrderEntryCuttingDie.ShowAddAddressForm; procedure TFOrderEntryCuttingDie.ShowAddAddressForm;
// displays the search pop-up that allows the user to filter the order list // displays the search pop-up that allows the user to filter the order list
var var
...@@ -159,6 +171,7 @@ begin ...@@ -159,6 +171,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';
...@@ -193,6 +206,7 @@ begin ...@@ -193,6 +206,7 @@ begin
); );
end; end;
function TFOrderEntryCuttingDie.VerifyOrder: Boolean; function TFOrderEntryCuttingDie.VerifyOrder: Boolean;
var var
input: TJSHTMLInputElement; input: TJSHTMLInputElement;
...@@ -249,6 +263,7 @@ begin ...@@ -249,6 +263,7 @@ begin
input.classList.remove('is-invalid'); input.classList.remove('is-invalid');
end; end;
procedure TFOrderEntryCuttingDie.SendOrderToServer; procedure TFOrderEntryCuttingDie.SendOrderToServer;
var var
orderJSON: TJSONObject; orderJSON: TJSONObject;
...@@ -296,14 +311,15 @@ begin ...@@ -296,14 +311,15 @@ 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);
end; end;
procedure TFOrderEntryCuttingDie.btnSaveClick(Sender: TObject); procedure TFOrderEntryCuttingDie.btnSaveClick(Sender: TObject);
// Converts all the information on the page into a JSON to then send to the server // Converts all the information on the page into a JSON to then send to the server
begin begin
...@@ -315,33 +331,43 @@ begin ...@@ -315,33 +331,43 @@ begin
window.scrollTo(0, 0); window.scrollTo(0, 0);
end; end;
procedure TFOrderEntryCuttingDie.btnCopyClick(Sender: TObject); procedure TFOrderEntryCuttingDie.btnCopyClick(Sender: TObject);
begin begin
mode := 'ADD'; mode := 'ADD';
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;
procedure TFOrderEntryCuttingDie.btnDeleteClick(Sender: TObject); procedure TFOrderEntryCuttingDie.btnDeleteClick(Sender: TObject);
begin begin
FModalAction := 'delete';
document.getElementById('modal_body').innerHTML := 'Are you sure you want to delete this order?'; document.getElementById('modal_body').innerHTML := 'Are you sure you want to delete this order?';
document.getElementById('btn_confirm_cancel').innerText := 'Cancel'; document.getElementById('btn_confirm_cancel').innerText := 'Cancel';
document.getElementById('btn_confirm_delete').innerText := 'Delete'; document.getElementById('btn_confirm_delete').innerText := 'Delete';
asm asm
var confirmationModal = new bootstrap.Modal(document.getElementById('confirmation_modal'), { var modal = document.getElementById('confirmation_modal');
keyboard: false }); 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;
procedure TFOrderEntryCuttingDie.btnEditClick(Sender: TObject); procedure TFOrderEntryCuttingDie.btnEditClick(Sender: TObject);
begin begin
EditMode(); EditMode();
end; end;
procedure TFOrderEntryCuttingDie.DelOrder(); procedure TFOrderEntryCuttingDie.DelOrder();
var var
Response: TXDataClientResponse; Response: TXDataClientResponse;
...@@ -350,43 +376,40 @@ begin ...@@ -350,43 +376,40 @@ begin
[OrderID, 'corrugated', JS.toString(AuthService.TokenPayload.Properties['user_id'])])); [OrderID, 'corrugated', JS.toString(AuthService.TokenPayload.Properties['user_id'])]));
end; end;
procedure TFOrderEntryCuttingDie.btnPDFClick(Sender: TObject); procedure TFOrderEntryCuttingDie.btnPDFClick(Sender: TObject);
begin begin
GenerateReportPDF; GenerateReportPDF;
end; end;
procedure TFOrderEntryCuttingDie.btn_confirm_deleteClick(Sender: TObject); procedure TFOrderEntryCuttingDie.btn_confirm_deleteClick(Sender: TObject);
begin begin
if document.getElementById('btn_confirm_delete').innerText = 'Yes' then if FModalAction = 'cancel' then
begin begin
FViewMain.change := false; FViewMain.change := false;
if OrderID <> '' then if OrderID <> '' then
begin FViewMain.ViewOrderEntryCuttingDie(OrderID, '', 'EDIT', 'Failure: Changes Discarded')
FViewMain.ViewOrderEntryCuttingDie(OrderID, '', 'EDIT', 'Failure:Changes Discarded');
end
else else
FViewMain.ViewOrders(''); FViewMain.ViewOrders('');
end end
else else if FModalAction = 'delete' then
begin begin
Utils.ShowSpinner('spinner'); Utils.ShowSpinner('spinner');
asm asm
var modal = document.getElementById('confirmation_modal'); var modal = document.getElementById('confirmation_modal');
// ensure the modal lives directly under <body>
if (modal && modal.parentNode !== document.body) { if (modal && modal.parentNode !== document.body) {
document.body.appendChild(modal); document.body.appendChild(modal);
} }
var bsModal = new bootstrap.Modal(modal, { keyboard: false });
var bsModal = new bootstrap.Modal(modal, {
keyboard: false
});
bsModal.hide(); bsModal.hide();
end; end;
delOrder(); DelOrder();
tmrReturn.Enabled := true; tmrReturn.Enabled := true;
end; end;
end; end;
[async] procedure TFOrderEntryCuttingDie.GenerateReportPDF; [async] procedure TFOrderEntryCuttingDie.GenerateReportPDF;
// sends the search to the server which then sends back a pdf of the results // sends the search to the server which then sends back a pdf of the results
var var
...@@ -442,7 +465,6 @@ begin ...@@ -442,7 +465,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;
...@@ -452,6 +474,7 @@ begin ...@@ -452,6 +474,7 @@ begin
); );
end; end;
procedure TFOrderEntryCuttingDie.btnAddClick(Sender: TObject); procedure TFOrderEntryCuttingDie.btnAddClick(Sender: TObject);
var var
newform: TFAddOrder; newform: TFAddOrder;
...@@ -462,6 +485,7 @@ begin ...@@ -462,6 +485,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';
...@@ -489,14 +513,20 @@ begin ...@@ -489,14 +513,20 @@ begin
); );
end; end;
procedure TFOrderEntryCuttingDie.btnCancelClick(Sender: TObject); procedure TFOrderEntryCuttingDie.btnCancelClick(Sender: TObject);
begin begin
document.getElementById('modal_body').innerHTML := 'Are you sure you want to cancel all changes to the customer?'; FModalAction := 'cancel';
document.getElementById('modal_body').innerHTML := 'Are you sure you want to cancel all changes?';
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 }); 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;
...@@ -508,13 +538,11 @@ end; ...@@ -508,13 +538,11 @@ end;
procedure TFOrderEntryCuttingDie.WebFormCreate(Sender: TObject); procedure TFOrderEntryCuttingDie.WebFormCreate(Sender: TObject);
begin begin
if not DMConnection.ApiConnection.Connected then if not DMConnection.ApiConnection.Connected then
begin
DMConnection.ApiConnection.OpenAsync; DMConnection.ApiConnection.OpenAsync;
console.log('report requirements connection open')
end;
end; end;
procedure TFOrderEntryCuttingDie.getCuttingDieOrder(Order_ID: string); procedure TFOrderEntryCuttingDie.getCuttingDieOrder(Order_ID: string);
// retrieves an order from the server then loads the info into the page // retrieves an order from the server then loads the info into the page
var var
...@@ -621,46 +649,9 @@ begin ...@@ -621,46 +649,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;
...@@ -678,6 +669,7 @@ begin ...@@ -678,6 +669,7 @@ begin
window.scrollTo(0, 0); window.scrollTo(0, 0);
end; end;
procedure TFOrderEntryCuttingDie.EditMode; procedure TFOrderEntryCuttingDie.EditMode;
begin begin
FViewMain.change := true; FViewMain.change := true;
...@@ -691,26 +683,30 @@ begin ...@@ -691,26 +683,30 @@ begin
btnAdd.Enabled := false; btnAdd.Enabled := false;
end; end;
procedure TFOrderEntryCuttingDie.xdwdsQBItemAfterEdit(DataSet: TDataSet); procedure TFOrderEntryCuttingDie.XDataWebDataSet1AfterEdit(DataSet: TDataSet);
begin begin
EditMode(); EditMode();
end; end;
procedure TFOrderEntryCuttingDie.xdwdsShipToAfterEdit(DataSet: TDataSet);
procedure TFOrderEntryCuttingDie.xdwdsQBItemAfterEdit(DataSet: TDataSet);
begin begin
EditMode(); EditMode();
end; end;
procedure TFOrderEntryCuttingDie.XDataWebDataSet1AfterEdit(DataSet: TDataSet);
procedure TFOrderEntryCuttingDie.xdwdsShipToAfterEdit(DataSet: TDataSet);
begin begin
EditMode(); EditMode();
end; end;
procedure TFOrderEntryCuttingDie.dtpOrderDateChange(Sender: TObject); procedure TFOrderEntryCuttingDie.dtpOrderDateChange(Sender: TObject);
begin begin
EditMode(); EditMode();
end; end;
procedure TFOrderEntryCuttingDie.ViewMode; procedure TFOrderEntryCuttingDie.ViewMode;
begin begin
btnPDF.Enabled := true; btnPDF.Enabled := true;
...@@ -724,6 +720,7 @@ begin ...@@ -724,6 +720,7 @@ begin
FViewMain.change := false; FViewMain.change := false;
end; end;
initialization initialization
RegisterClass(TFOrderEntryCuttingDie); RegisterClass(TFOrderEntryCuttingDie);
......
...@@ -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
...@@ -743,7 +705,7 @@ object FOrderEntryWeb: TFOrderEntryWeb ...@@ -743,7 +705,7 @@ object FOrderEntryWeb: TFOrderEntryWeb
Top = 87 Top = 87
Width = 96 Width = 96
Height = 25 Height = 25
Caption = '+' Caption = 'Add Color'
ChildOrder = 59 ChildOrder = 59
ElementID = 'btnaddcolor' ElementID = 'btnaddcolor'
HeightPercent = 100.000000000000000000 HeightPercent = 100.000000000000000000
...@@ -863,6 +825,7 @@ object FOrderEntryWeb: TFOrderEntryWeb ...@@ -863,6 +825,7 @@ object FOrderEntryWeb: TFOrderEntryWeb
ChildOrder = 79 ChildOrder = 79
ElementID = 'edtaround' ElementID = 'edtaround'
HeightPercent = 100.000000000000000000 HeightPercent = 100.000000000000000000
ShowFocus = False
WidthPercent = 100.000000000000000000 WidthPercent = 100.000000000000000000
DataField = 'layout_around' DataField = 'layout_around'
DataSource = WebDataSource1 DataSource = WebDataSource1
...@@ -876,6 +839,7 @@ object FOrderEntryWeb: TFOrderEntryWeb ...@@ -876,6 +839,7 @@ object FOrderEntryWeb: TFOrderEntryWeb
ChildOrder = 79 ChildOrder = 79
ElementID = 'edtaccross' ElementID = 'edtaccross'
HeightPercent = 100.000000000000000000 HeightPercent = 100.000000000000000000
ShowFocus = False
WidthPercent = 100.000000000000000000 WidthPercent = 100.000000000000000000
DataField = 'layout_accross' DataField = 'layout_accross'
DataSource = WebDataSource1 DataSource = WebDataSource1
...@@ -889,6 +853,7 @@ object FOrderEntryWeb: TFOrderEntryWeb ...@@ -889,6 +853,7 @@ object FOrderEntryWeb: TFOrderEntryWeb
ChildOrder = 79 ChildOrder = 79
ElementID = 'edtreverseprint' ElementID = 'edtreverseprint'
HeightPercent = 100.000000000000000000 HeightPercent = 100.000000000000000000
ShowFocus = False
WidthPercent = 100.000000000000000000 WidthPercent = 100.000000000000000000
DataField = 'layout_reverse_print' DataField = 'layout_reverse_print'
DataSource = WebDataSource1 DataSource = WebDataSource1
...@@ -902,6 +867,7 @@ object FOrderEntryWeb: TFOrderEntryWeb ...@@ -902,6 +867,7 @@ object FOrderEntryWeb: TFOrderEntryWeb
ChildOrder = 79 ChildOrder = 79
ElementID = 'edtsurfaceprint' ElementID = 'edtsurfaceprint'
HeightPercent = 100.000000000000000000 HeightPercent = 100.000000000000000000
ShowFocus = False
WidthPercent = 100.000000000000000000 WidthPercent = 100.000000000000000000
DataField = 'layout_surface_print' DataField = 'layout_surface_print'
DataSource = WebDataSource1 DataSource = WebDataSource1
...@@ -915,6 +881,7 @@ object FOrderEntryWeb: TFOrderEntryWeb ...@@ -915,6 +881,7 @@ object FOrderEntryWeb: TFOrderEntryWeb
ChildOrder = 79 ChildOrder = 79
ElementID = 'edtcutoffdimension' ElementID = 'edtcutoffdimension'
HeightPercent = 100.000000000000000000 HeightPercent = 100.000000000000000000
ShowFocus = False
WidthPercent = 100.000000000000000000 WidthPercent = 100.000000000000000000
DataField = 'layout_cutoff_dimension' DataField = 'layout_cutoff_dimension'
DataSource = WebDataSource1 DataSource = WebDataSource1
...@@ -928,6 +895,7 @@ object FOrderEntryWeb: TFOrderEntryWeb ...@@ -928,6 +895,7 @@ object FOrderEntryWeb: TFOrderEntryWeb
ChildOrder = 79 ChildOrder = 79
ElementID = 'edtcylinderrepeat' ElementID = 'edtcylinderrepeat'
HeightPercent = 100.000000000000000000 HeightPercent = 100.000000000000000000
ShowFocus = False
WidthPercent = 100.000000000000000000 WidthPercent = 100.000000000000000000
DataField = 'layout_cylinder_repeat' DataField = 'layout_cylinder_repeat'
DataSource = WebDataSource1 DataSource = WebDataSource1
...@@ -941,6 +909,7 @@ object FOrderEntryWeb: TFOrderEntryWeb ...@@ -941,6 +909,7 @@ object FOrderEntryWeb: TFOrderEntryWeb
ChildOrder = 79 ChildOrder = 79
ElementID = 'edtpitch' ElementID = 'edtpitch'
HeightPercent = 100.000000000000000000 HeightPercent = 100.000000000000000000
ShowFocus = False
WidthPercent = 100.000000000000000000 WidthPercent = 100.000000000000000000
DataField = 'layout_pitch' DataField = 'layout_pitch'
DataSource = WebDataSource1 DataSource = WebDataSource1
...@@ -954,6 +923,7 @@ object FOrderEntryWeb: TFOrderEntryWeb ...@@ -954,6 +923,7 @@ object FOrderEntryWeb: TFOrderEntryWeb
ChildOrder = 79 ChildOrder = 79
ElementID = 'edtbleed' ElementID = 'edtbleed'
HeightPercent = 100.000000000000000000 HeightPercent = 100.000000000000000000
ShowFocus = False
WidthPercent = 100.000000000000000000 WidthPercent = 100.000000000000000000
DataField = 'layout_bleed' DataField = 'layout_bleed'
DataSource = WebDataSource1 DataSource = WebDataSource1
...@@ -967,6 +937,7 @@ object FOrderEntryWeb: TFOrderEntryWeb ...@@ -967,6 +937,7 @@ object FOrderEntryWeb: TFOrderEntryWeb
ChildOrder = 79 ChildOrder = 79
ElementID = 'edtteeth' ElementID = 'edtteeth'
HeightPercent = 100.000000000000000000 HeightPercent = 100.000000000000000000
ShowFocus = False
WidthPercent = 100.000000000000000000 WidthPercent = 100.000000000000000000
DataField = 'layout_teeth' DataField = 'layout_teeth'
DataSource = WebDataSource1 DataSource = WebDataSource1
...@@ -980,6 +951,7 @@ object FOrderEntryWeb: TFOrderEntryWeb ...@@ -980,6 +951,7 @@ object FOrderEntryWeb: TFOrderEntryWeb
ChildOrder = 79 ChildOrder = 79
ElementID = 'edtcutback' ElementID = 'edtcutback'
HeightPercent = 100.000000000000000000 HeightPercent = 100.000000000000000000
ShowFocus = False
WidthPercent = 100.000000000000000000 WidthPercent = 100.000000000000000000
DataField = 'layout_cutback' DataField = 'layout_cutback'
DataSource = WebDataSource1 DataSource = WebDataSource1
...@@ -993,6 +965,7 @@ object FOrderEntryWeb: TFOrderEntryWeb ...@@ -993,6 +965,7 @@ object FOrderEntryWeb: TFOrderEntryWeb
ChildOrder = 79 ChildOrder = 79
ElementID = 'edtminimumtrapdimension' ElementID = 'edtminimumtrapdimension'
HeightPercent = 100.000000000000000000 HeightPercent = 100.000000000000000000
ShowFocus = False
WidthPercent = 100.000000000000000000 WidthPercent = 100.000000000000000000
DataField = 'layout_minimum_trap_dim' DataField = 'layout_minimum_trap_dim'
DataSource = WebDataSource1 DataSource = WebDataSource1
...@@ -1006,6 +979,7 @@ object FOrderEntryWeb: TFOrderEntryWeb ...@@ -1006,6 +979,7 @@ object FOrderEntryWeb: TFOrderEntryWeb
ChildOrder = 79 ChildOrder = 79
ElementID = 'edtmaximumtrapdimension' ElementID = 'edtmaximumtrapdimension'
HeightPercent = 100.000000000000000000 HeightPercent = 100.000000000000000000
ShowFocus = False
WidthPercent = 100.000000000000000000 WidthPercent = 100.000000000000000000
DataField = 'layout_maximum_trap_dim' DataField = 'layout_maximum_trap_dim'
DataSource = WebDataSource1 DataSource = WebDataSource1
...@@ -1019,6 +993,7 @@ object FOrderEntryWeb: TFOrderEntryWeb ...@@ -1019,6 +993,7 @@ object FOrderEntryWeb: TFOrderEntryWeb
ChildOrder = 79 ChildOrder = 79
ElementID = 'edtsize' ElementID = 'edtsize'
HeightPercent = 100.000000000000000000 HeightPercent = 100.000000000000000000
ShowFocus = False
WidthPercent = 100.000000000000000000 WidthPercent = 100.000000000000000000
DataField = 'upc_size' DataField = 'upc_size'
DataSource = WebDataSource1 DataSource = WebDataSource1
...@@ -1028,10 +1003,12 @@ object FOrderEntryWeb: TFOrderEntryWeb ...@@ -1028,10 +1003,12 @@ object FOrderEntryWeb: TFOrderEntryWeb
Top = 452 Top = 452
Width = 121 Width = 121
Height = 23 Height = 23
TabStop = False
AutoSize = True AutoSize = True
ChildOrder = 79 ChildOrder = 79
ElementID = 'edtbarwidthreduction' ElementID = 'edtbarwidthreduction'
HeightPercent = 100.000000000000000000 HeightPercent = 100.000000000000000000
ShowFocus = False
WidthPercent = 100.000000000000000000 WidthPercent = 100.000000000000000000
DataField = 'upc_bar_width_reduction' DataField = 'upc_bar_width_reduction'
DataSource = WebDataSource1 DataSource = WebDataSource1
...@@ -1041,10 +1018,12 @@ object FOrderEntryWeb: TFOrderEntryWeb ...@@ -1041,10 +1018,12 @@ object FOrderEntryWeb: TFOrderEntryWeb
Top = 523 Top = 523
Width = 121 Width = 121
Height = 23 Height = 23
TabStop = False
AutoSize = True AutoSize = True
ChildOrder = 79 ChildOrder = 79
ElementID = 'edtdistortionamount' ElementID = 'edtdistortionamount'
HeightPercent = 100.000000000000000000 HeightPercent = 100.000000000000000000
ShowFocus = False
WidthPercent = 100.000000000000000000 WidthPercent = 100.000000000000000000
DataField = 'upc_distortion_amount' DataField = 'upc_distortion_amount'
DataSource = WebDataSource1 DataSource = WebDataSource1
...@@ -1054,6 +1033,7 @@ object FOrderEntryWeb: TFOrderEntryWeb ...@@ -1054,6 +1033,7 @@ object FOrderEntryWeb: TFOrderEntryWeb
Top = 490 Top = 490
Width = 121 Width = 121
Height = 23 Height = 23
TabStop = False
AutoSize = True AutoSize = True
ChildOrder = 79 ChildOrder = 79
ElementID = 'edtdistortionpercent' ElementID = 'edtdistortionpercent'
......
<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>
...@@ -248,25 +243,43 @@ ...@@ -248,25 +243,43 @@
<input class="form-control input-sm" id="dtpdigitalcolordate" type="date"> <input class="form-control input-sm" id="dtpdigitalcolordate" type="date">
</div> </div>
</div> </div>
<h4 class="custom-h4 mt-3">Quantity and Colors</h4> <h4 class="custom-h4 mt-3">Quantity</h4>
<hr class="custom-hr"> <hr class="custom-hr">
<div class="row"> <div class="row">
<div class="col-auto"> <div class="col-auto">
<label style="font-weight: 700; font-size: 15px;" class="form-label mt-2">Press Name:</label> <label style="font-weight: 700; font-size: 15px;" class="form-label mt-2">Press Name:</label>
<input id="edtpressname" class="form-control input-sm" width='50%'/> <input id="edtpressname" class="form-control input-sm" width="50%" />
</div> </div>
<div class="col-auto"> <div class="col-auto">
<label style="font-weight: 700; font-size: 15px;" class="form-label mt-2">Anilax Info:</label> <label style="font-weight: 700; font-size: 15px;" class="form-label mt-2">Anilax Info:</label>
<input id="edtanilaxinfo" class="form-control input-sm" width='50%'/> <input id="edtanilaxinfo" class="form-control input-sm" width="50%" />
</div> </div>
<div class="col-auto"> </div>
<label for="wdbe_first_name" style="font-weight: 700; font-size: 15px;" class="form-label mt-2">Colors:</label>
<button id="btnaddcolor" class="btn btn-primary btn-sm float-end">+</button> <h4 class="custom-h4 mt-3">Colors</h4>
<div id="additionalFields" class="row mt-3"></div> <hr class="custom-hr">
</div>
<div class="row align-items-center">
<!-- placeholders for the 4 dynamic input columns to center the Add Color button -->
<div class="col-sm"></div>
<div class="col-sm"></div>
<div class="col-sm"></div>
<div class="col-sm"></div>
<div class="col-auto d-flex justify-content-center">
<!-- Delphi-generated TWebButton stays here -->
<button id="btnaddcolor" class="btn btn-primary btn-sm me-3">
Add Color
</button>
</div>
</div> </div>
<!-- Dynamically injected color rows go here -->
<div id="additionalFields" class="row mt-3"></div>
<h4 class="custom-h4 mt-3">Plate Marks</h4> <h4 class="custom-h4 mt-3">Plate Marks</h4>
<hr class="custom-hr"> <hr class="custom-hr">
<div class="row"> <div class="row">
<div class="col-auto"> <div class="col-auto">
<label label style="font-weight: 700; font-size: 15px;" class="form-label mt-2">Microdots:</label> <label label style="font-weight: 700; font-size: 15px;" class="form-label mt-2">Microdots:</label>
...@@ -407,24 +420,18 @@ ...@@ -407,24 +420,18 @@
</div> </div>
<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 shadow-lg">
<div class="modal-header"> <div class="modal-header">
<h5 class="modal-title" id="confirmation_modal_label">Confirm</h5> <h5 class="modal-title" id="confirmation_modal_label">Confirm</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button> <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div> </div>
<div class="modal-body" id="modal_body"> <div class="modal-body fs-6 fw-bold" id="modal_body">
Are you sure you want to delete this order? Are you sure you want to delete this order?
</div> </div>
<div class="modal-footer"> <div class="modal-footer justify-content-center">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal" id=btn_confirm_cancel>Cancel</button> <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> <button type="button" class="btn btn-primary" data-bs-dismiss="modal" id="btn_confirm_delete">Delete</button>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
</div>
<style>
.modal-backdrop {
opacity: 0 !important;
}
</style>
...@@ -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;
...@@ -240,6 +234,7 @@ type ...@@ -240,6 +234,7 @@ type
procedure ShowAddAddressForm(); procedure ShowAddAddressForm();
[async] procedure SendAddressToServer(AddressJSON: TJSONObject); [async] procedure SendAddressToServer(AddressJSON: TJSONObject);
private private
FModalAction: string;
FAgencyCode: string; FAgencyCode: string;
FCurrentReportType: string; FCurrentReportType: string;
FSelectProc: TSelectProc; FSelectProc: TSelectProc;
...@@ -247,6 +242,7 @@ type ...@@ -247,6 +242,7 @@ type
customerID: string; customerID: string;
mode: string; mode: string;
notification: string; notification: string;
procedure RemoveColorRow(Sender: TObject);
//FJSONProc1: TJSONProc1; //FJSONProc1: TJSONProc1;
public public
class function CreateForm(AElementID, orderInfo, customerInfo, mode, info: string): TWebForm; class function CreateForm(AElementID, orderInfo, customerInfo, mode, info: string): TWebForm;
...@@ -276,7 +272,7 @@ begin ...@@ -276,7 +272,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;
...@@ -294,6 +290,7 @@ begin ...@@ -294,6 +290,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';
...@@ -412,18 +409,23 @@ begin ...@@ -412,18 +409,23 @@ 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;
procedure TFOrderEntryWeb.btnDeleteClick(Sender: TObject); procedure TFOrderEntryWeb.btnDeleteClick(Sender: TObject);
begin begin
FModalAction := 'delete';
document.getElementById('modal_body').innerHTML := 'Are you sure you want to delete this order?'; document.getElementById('modal_body').innerHTML := 'Are you sure you want to delete this order?';
document.getElementById('btn_confirm_cancel').innerText := 'Cancel'; document.getElementById('btn_confirm_cancel').innerText := 'Cancel';
document.getElementById('btn_confirm_delete').innerText := 'Delete'; document.getElementById('btn_confirm_delete').innerText := 'Delete';
asm asm
var confirmationModal = new bootstrap.Modal(document.getElementById('confirmation_modal'), { var modal = document.getElementById('confirmation_modal');
keyboard: false }); 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;
...@@ -547,7 +549,7 @@ begin ...@@ -547,7 +549,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);
...@@ -557,32 +559,26 @@ end; ...@@ -557,32 +559,26 @@ end;
procedure TFOrderEntryWeb.btn_confirm_deleteClick(Sender: TObject); procedure TFOrderEntryWeb.btn_confirm_deleteClick(Sender: TObject);
begin begin
if document.getElementById('btn_confirm_delete').innerText = 'Yes' then if FModalAction = 'cancel' then
begin begin
FViewMain.change := false; FViewMain.change := false;
if OrderID <> '' then if OrderID <> '' then
begin FViewMain.ViewOrderEntryWeb(OrderID, '', 'EDIT', 'Failure: Changes Discarded')
FViewMain.ViewOrderEntryWeb(OrderID, '', 'EDIT', 'Failure:Changes Discarded');
end
else else
FViewMain.ViewOrders(''); FViewMain.ViewOrders('');
end end
else else if FModalAction = 'delete' then
begin begin
Utils.ShowSpinner('spinner'); Utils.ShowSpinner('spinner');
asm asm
var modal = document.getElementById('confirmation_modal'); var modal = document.getElementById('confirmation_modal');
// ensure the modal is directly under <body>
if (modal && modal.parentNode !== document.body) { if (modal && modal.parentNode !== document.body) {
document.body.appendChild(modal); document.body.appendChild(modal);
} }
var bsModal = new bootstrap.Modal(modal, { keyboard: false });
var bsModal = new bootstrap.Modal(modal, {
keyboard: false
});
bsModal.hide(); bsModal.hide();
end; end;
delOrder(); DelOrder();
tmrReturn.Enabled := true; tmrReturn.Enabled := true;
end; end;
end; end;
...@@ -640,7 +636,6 @@ begin ...@@ -640,7 +636,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;
...@@ -652,56 +647,75 @@ begin ...@@ -652,56 +647,75 @@ begin
end; end;
procedure TFOrderEntryWeb.addColorRow(num: string; Color: string; LPI: string; Size: string); procedure TFOrderEntryWeb.addColorRow(num: string; Color: string; LPI: string; Size: string);
// Java script code to add a row of colors when a button is clicked var
// all variables are information to be placed in the boxes when loading an order. container, newRow, col, labelEl, inputEl, removeCol: TJSHTMLElement;
// TODO: convert to Delphi removeBtn: TWebButton;
values: array[0..3] of string;
labels: array[0..3] of string;
i: Integer;
begin begin
asm container := TJSHTMLElement(document.getElementById('additionalFields'));
const container = document.getElementById('additionalFields');
// Create the new row container
// Create a new row for the new fields newRow := TJSHTMLElement(document.createElement('div'));
const newRow = document.createElement('div'); newRow.className := 'row mb-2';
newRow.className = 'row mb-2';
labels[0] := '#'; values[0] := num;
const labels = ['#', 'Color', 'LPI', 'Size']; labels[1] := 'Color'; values[1] := color;
const values = [num, Color, LPI, Size]; labels[2] := 'LPI'; values[2] := LPI;
labels.forEach((label, index) => { labels[3] := 'Size'; values[3] := size;
const col = document.createElement('div');
col.className = 'col-sm'; for i := 0 to 3 do
begin
const labelElement = document.createElement('label'); col := TJSHTMLElement(document.createElement('div'));
labelElement.className = 'pe-2'; col.className := 'col-sm';
labelElement.style.fontWeight = '700';
labelElement.style.fontSize = '15px'; labelEl := TJSHTMLElement(document.createElement('label'));
labelElement.textContent = label + ':'; labelEl.className := 'pe-2';
labelEl.style.setProperty('font-weight', '700');
const inputElement = document.createElement('input'); labelEl.style.setProperty('font-size', '15px');
inputElement.className = 'form-control input-sm'; labelEl.textContent := labels[i] + ':';
inputElement.style.width = '100%';
inputElement.id = 'input-' + container.childElementCount + '-' + index; // Unique ID based on count inputEl := TJSHTMLElement(document.createElement('input'));
inputElement.value = values[index]; // Set the value based on the parameter inputEl.className := 'form-control input-sm';
inputEl.setAttribute('style', 'width: 100%');
col.appendChild(labelElement); inputEl.setAttribute('value', values[i]);
col.appendChild(inputElement); inputEl.setAttribute('id', 'input-' + IntToStr(container.childElementCount) + '-' + IntToStr(i));
newRow.appendChild(col); col.appendChild(labelEl);
}); col.appendChild(inputEl);
newRow.appendChild(col);
const removeButtonCol = document.createElement('div'); end;
removeButtonCol.className = 'col-auto d-flex align-items-center';
// Add remove button
const removeButton = document.createElement('button'); removeCol := TJSHTMLElement(document.createElement('div'));
removeButton.className = 'btn btn-danger btn-sm'; removeCol.className := 'col-auto d-flex align-items-end pb-1';
removeButton.textContent = 'Remove';
removeButton.addEventListener('click', function() { removeBtn := TWebButton.Create(Self);
container.removeChild(newRow); removeBtn.Caption := 'Remove';
}); removeBtn.ElementClassName := 'btn btn-danger btn-sm mt-1';
removeBtn.ParentElement := removeCol;
removeButtonCol.appendChild(removeButton); removeBtn.ElementHandle.style.setProperty('height', '30px');
newRow.appendChild(removeButtonCol); removeBtn.OnClick := RemoveColorRow;
container.appendChild(newRow); newRow.appendChild(removeCol);
end; container.appendChild(newRow);
end;
procedure TFOrderEntryWeb.RemoveColorRow(Sender: TObject);
var
btn: TWebButton;
rowElement: TJSHTMLElement;
begin
EditMode();
btn := TWebButton(Sender);
if Assigned(btn.ElementHandle) and Assigned(btn.ElementHandle.parentElement) then
begin
// Assuming button is inside a <div> inside the row
rowElement := TJSHTMLElement(btn.ElementHandle.parentElement.parentElement);
if Assigned(rowElement) then
rowElement.remove;
end;
end; end;
procedure TFOrderEntryWeb.WebButton1Click(Sender: TObject); procedure TFOrderEntryWeb.WebButton1Click(Sender: TObject);
...@@ -720,6 +734,7 @@ begin ...@@ -720,6 +734,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';
...@@ -749,12 +764,17 @@ end; ...@@ -749,12 +764,17 @@ end;
procedure TFOrderEntryWeb.btnCancelClick(Sender: TObject); procedure TFOrderEntryWeb.btnCancelClick(Sender: TObject);
begin begin
document.getElementById('modal_body').innerHTML := 'Are you sure you want to cancel all changes to the customer?'; FModalAction := 'cancel';
document.getElementById('modal_body').innerHTML := 'Are you sure you want to cancel all changes?';
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 }); 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;
...@@ -764,10 +784,6 @@ begin ...@@ -764,10 +784,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
...@@ -955,13 +971,9 @@ begin ...@@ -955,13 +971,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;
...@@ -970,39 +982,6 @@ begin ...@@ -970,39 +982,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
......
object FViewOrders: TFViewOrders object FViewOrders: TFViewOrders
Width = 676 Width = 676
Height = 480 Height = 480
Caption = 'main.errorpanel'
CSSLibrary = cssBootstrap CSSLibrary = cssBootstrap
ElementFont = efCSS ElementFont = efCSS
Font.Charset = DEFAULT_CHARSET Font.Charset = DEFAULT_CHARSET
...@@ -310,36 +309,6 @@ object FViewOrders: TFViewOrders ...@@ -310,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,20 +69,20 @@ type ...@@ -73,20 +69,20 @@ 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;
FPendingPdfTab: TJSWindow;
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);
procedure HandlePDFConfirmation;
var var
PageNumber: integer; PageNumber: integer;
PageSize: integer; PageSize: integer;
...@@ -146,43 +142,128 @@ begin ...@@ -146,43 +142,128 @@ begin
end; end;
procedure TFViewOrders.btnPDFClick(Sender: TObject); procedure TFViewOrders.btnPDFClick(Sender: TObject);
var
confirmBtn: TJSHTMLElement;
begin
if xdwdsOrders.RecordCount >= 100 then
begin
FPendingPdfTab := nil;
document.getElementById('modal_body').innerHTML :=
'You are about to generate a PDF for over 100 orders. This may take some time. Continue?';
document.getElementById('btn_confirm_cancel').innerText := 'Cancel';
document.getElementById('btn_confirm_delete').innerText := 'Yes';
confirmBtn := TJSHTMLElement(document.getElementById('btn_confirm_delete'));
confirmBtn.addEventListener('click',
TJSEventHandler(
procedure(Event: TJSEvent)
begin
asm bootstrap.Modal.getInstance(document.getElementById('confirmation_modal')).hide(); end;
HandlePDFConfirmation;
end
)
);
asm
var modal = document.getElementById('confirmation_modal');
if (modal && modal.parentNode !== document.body) {
document.body.appendChild(modal);
}
var confirmationModal = new bootstrap.Modal(modal, { keyboard: false });
confirmationModal.show();
end;
end
else
begin
FPendingPdfTab := window.open('', '_blank');
if Assigned(FPendingPdfTab) then
FPendingPdfTab.document.write(
'<!DOCTYPE html>' +
'<html lang="en">' +
'<head>' +
'<meta charset="UTF-8">' +
'<meta name="viewport" content="width=device-width, initial-scale=1.0">' +
'<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">' +
'</head>' +
'<body class="d-flex flex-column justify-content-center align-items-center vh-100 bg-light">' +
'<div class="spinner-border text-primary" role="status" style="width: 3rem; height: 3rem;"></div>' +
'<div class="mt-3 fs-5 text-muted">Generating PDF, please wait�</div>' +
'</body>' +
'</html>'
);
Utils.ShowSpinner('spinner');
GenerateReportPDFAsync(FPendingPdfTab);
end;
end;
procedure TFViewOrders.HandlePDFConfirmation;
begin begin
// Open tab only now
FPendingPdfTab := window.open('', '_blank');
if Assigned(FPendingPdfTab) then
FPendingPdfTab.document.write(
'<!DOCTYPE html>' +
'<html lang="en">' +
'<head>' +
'<meta charset="UTF-8">' +
'<meta name="viewport" content="width=device-width, initial-scale=1.0">' +
'<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">' +
'</head>' +
'<body class="d-flex flex-column justify-content-center align-items-center vh-100 bg-light">' +
'<div class="spinner-border text-primary" role="status" style="width: 3rem; height: 3rem;"></div>' +
'<div class="mt-3 fs-5 text-muted">Generating PDF, please wait�</div>' +
'</body>' +
'</html>'
);
Utils.ShowSpinner('spinner'); Utils.ShowSpinner('spinner');
GenerateReportPDF; GenerateReportPDFAsync(FPendingPdfTab);
FPendingPdfTab := nil;
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 + '&forPDF=true';
// 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 statusOrderID <> '' then if statusOrderID <> '' 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);
...@@ -265,9 +346,7 @@ end; ...@@ -265,9 +346,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;
...@@ -288,6 +367,7 @@ begin ...@@ -288,6 +367,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
...@@ -320,6 +400,7 @@ begin ...@@ -320,6 +400,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
...@@ -370,6 +451,7 @@ begin ...@@ -370,6 +451,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 := statusOrderID; newForm.OrderID := statusOrderID;
newForm.JobName := wdbtcOrders.Cells[3, row]; newForm.JobName := wdbtcOrders.Cells[3, row];
if wdbtcOrders.Cells[14, row] <> '' then if wdbtcOrders.Cells[14, row] <> '' then
...@@ -722,10 +804,6 @@ begin ...@@ -722,10 +804,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
...@@ -798,39 +876,5 @@ begin ...@@ -798,39 +876,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();
...@@ -84,6 +85,11 @@ begin ...@@ -84,6 +85,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,14 +63,15 @@ end; ...@@ -65,14 +63,15 @@ 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;
ShowToast('Success: Status updated!');
Close; Close;
end; end;
end; end;
...@@ -83,7 +82,6 @@ var ...@@ -83,7 +82,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;
...@@ -138,17 +136,5 @@ begin ...@@ -138,17 +136,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
object FViewUserProfile: TFViewUserProfile object FViewUserProfile: TFViewUserProfile
Color = clWhite Width = 604
Height = 434
Font.Charset = DEFAULT_CHARSET Font.Charset = DEFAULT_CHARSET
Font.Color = clWindowText Font.Color = clWindowText
Font.Height = -11 Font.Height = -11
Font.Name = 'Tahoma' Font.Name = 'Tahoma'
Font.Size = 8
Font.Style = [] Font.Style = []
FormStyle = fsNormal
Height = 434
Left = 0
OnShow = WebFormShow
ParentFont = False ParentFont = False
TabOrder = 0 OnShow = WebFormShow
Top = 0
Width = 604
object WebLabel1: TWebLabel object WebLabel1: TWebLabel
Left = 24
Top = 24
Width = 55
Height = 13
Caption = 'User Profile' Caption = 'User Profile'
ElementID = 'view.userprofile.title' ElementID = 'view.userprofile.title'
Font.Charset = ANSI_CHARSET Font.Charset = ANSI_CHARSET
Font.Color = clWindowText Font.Color = clWindowText
Font.Height = -11 Font.Height = -11
Font.Name = 'Tahoma' Font.Name = 'Tahoma'
Font.Size = 8
Font.Style = [] Font.Style = []
Height = 16 HeightPercent = 100.000000000000000000
Left = 24 ParentFont = False
Top = 24
Visible = False Visible = False
Width = 54 WidthPercent = 100.000000000000000000
end end
object WebLabel3: TWebLabel object WebLabel3: TWebLabel
Left = 39
Top = 59
Width = 38
Height = 14
Caption = 'User ID:' Caption = 'User ID:'
ElementID = 'view.userprofile.form.lblUserID' ElementID = 'view.userprofile.form.lblUserID'
ElementPosition = epRelative ElementPosition = epRelative
...@@ -37,14 +37,16 @@ object FViewUserProfile: TFViewUserProfile ...@@ -37,14 +37,16 @@ object FViewUserProfile: TFViewUserProfile
Font.Color = clBlack Font.Color = clBlack
Font.Height = -11 Font.Height = -11
Font.Name = 'Arial' Font.Name = 'Arial'
Font.Size = 8
Font.Style = [] Font.Style = []
Height = 16 HeightPercent = 100.000000000000000000
Left = 39 ParentFont = False
Top = 59 WidthPercent = 100.000000000000000000
Width = 40
end end
object WebLabel2: TWebLabel object WebLabel2: TWebLabel
Left = 13
Top = 131
Width = 71
Height = 14
Caption = 'Email Address:' Caption = 'Email Address:'
ElementID = 'view.userprofile.form.lblEmail' ElementID = 'view.userprofile.form.lblEmail'
ElementPosition = epRelative ElementPosition = epRelative
...@@ -52,14 +54,16 @@ object FViewUserProfile: TFViewUserProfile ...@@ -52,14 +54,16 @@ object FViewUserProfile: TFViewUserProfile
Font.Color = clBlack Font.Color = clBlack
Font.Height = -11 Font.Height = -11
Font.Name = 'Arial' Font.Name = 'Arial'
Font.Size = 8
Font.Style = [] Font.Style = []
Height = 16 HeightPercent = 100.000000000000000000
Left = 13 ParentFont = False
Top = 157 WidthPercent = 100.000000000000000000
Width = 70
end end
object WebLabel4: TWebLabel object WebLabel4: TWebLabel
Left = 29
Top = 83
Width = 52
Height = 14
Caption = 'Username:' Caption = 'Username:'
ElementID = 'view.userprofile.form.lblUserName' ElementID = 'view.userprofile.form.lblUserName'
ElementPosition = epRelative ElementPosition = epRelative
...@@ -67,60 +71,49 @@ object FViewUserProfile: TFViewUserProfile ...@@ -67,60 +71,49 @@ object FViewUserProfile: TFViewUserProfile
Font.Color = clBlack Font.Color = clBlack
Font.Height = -11 Font.Height = -11
Font.Name = 'Arial' Font.Name = 'Arial'
Font.Size = 8
Font.Style = [] Font.Style = []
Height = 16 HeightPercent = 100.000000000000000000
Left = 29 ParentFont = False
Top = 83 WidthPercent = 100.000000000000000000
Width = 51
end end
object WebLabel5: TWebLabel object WebLabel5: TWebLabel
Caption = 'Full Name:'
ElementID = 'view.userprofile.form.lblFullName'
ElementPosition = epRelative
Font.Charset = ANSI_CHARSET
Font.Color = clBlack
Font.Height = -11
Font.Name = 'Arial'
Font.Size = 8
Font.Style = []
Height = 16
Left = 29 Left = 29
Top = 107 Top = 107
Width = 51 Width = 49
end Height = 14
object WebLabel6: TWebLabel Caption = 'Full Name:'
Caption = 'Phone Number:' ElementID = 'view.userprofile.form.lblFullName'
ElementID = 'view.userprofile.form.lblPhone'
ElementPosition = epRelative ElementPosition = epRelative
Font.Charset = ANSI_CHARSET Font.Charset = ANSI_CHARSET
Font.Color = clBlack Font.Color = clBlack
Font.Height = -11 Font.Height = -11
Font.Name = 'Arial' Font.Name = 'Arial'
Font.Size = 8
Font.Style = [] Font.Style = []
Height = 16 HeightPercent = 100.000000000000000000
Left = 5 ParentFont = False
Top = 133 WidthPercent = 100.000000000000000000
Width = 74
end end
object lblResult: TWebLabel object lblResult: TWebLabel
Left = 85
Top = 246
Width = 3
Height = 14
ElementID = 'view.userprofile.form.lblresult' ElementID = 'view.userprofile.form.lblresult'
ElementPosition = epRelative ElementPosition = epRelative
Font.Charset = ANSI_CHARSET Font.Charset = ANSI_CHARSET
Font.Color = clBlack Font.Color = clBlack
Font.Height = -11 Font.Height = -11
Font.Name = 'Arial' Font.Name = 'Arial'
Font.Size = 8
Font.Style = [] Font.Style = []
Height = 13 HeightPercent = 100.000000000000000000
Left = 85 ParentFont = False
Top = 246 WidthPercent = 100.000000000000000000
Width = 3
end end
object edtUsername: TWebEdit object edtUsername: TWebEdit
Alignment = taLeftJustify Left = 85
Color = clWindow Top = 80
Width = 121
Height = 21
ElementID = 'view.userprofile.form.edtUsername' ElementID = 'view.userprofile.form.edtUsername'
ElementPosition = epRelative ElementPosition = epRelative
Enabled = False Enabled = False
...@@ -128,20 +121,18 @@ object FViewUserProfile: TFViewUserProfile ...@@ -128,20 +121,18 @@ object FViewUserProfile: TFViewUserProfile
Font.Color = clBlack Font.Color = clBlack
Font.Height = -11 Font.Height = -11
Font.Name = 'Arial' Font.Name = 'Arial'
Font.Size = 8
Font.Style = [] Font.Style = []
Height = 21 HeightPercent = 100.000000000000000000
HideSelection = False HideSelection = False
Left = 85 ParentFont = False
ReadOnly = True ReadOnly = True
ShowFocus = True WidthPercent = 100.000000000000000000
TabOrder = 0
Top = 80
Width = 121
end end
object edtUserId: TWebEdit object edtUserId: TWebEdit
Alignment = taLeftJustify Left = 85
Color = clWindow Top = 56
Width = 121
Height = 21
ElementID = 'view.userprofile.form.edtUserID' ElementID = 'view.userprofile.form.edtUserID'
ElementPosition = epRelative ElementPosition = epRelative
Enabled = False Enabled = False
...@@ -149,58 +140,37 @@ object FViewUserProfile: TFViewUserProfile ...@@ -149,58 +140,37 @@ object FViewUserProfile: TFViewUserProfile
Font.Color = clBlack Font.Color = clBlack
Font.Height = -11 Font.Height = -11
Font.Name = 'Arial' Font.Name = 'Arial'
Font.Size = 8
Font.Style = [] Font.Style = []
Height = 21 HeightPercent = 100.000000000000000000
HideSelection = False HideSelection = False
Left = 85 ParentFont = False
ReadOnly = True ReadOnly = True
ShowFocus = True
TabOrder = 1 TabOrder = 1
Top = 56 WidthPercent = 100.000000000000000000
Width = 121
end end
object edtFullName: TWebEdit object edtFullName: TWebEdit
Alignment = taLeftJustify
ChildOrder = 5
Color = clWindow
ElementID = 'view.userprofile.form.edtFullName'
ElementPosition = epRelative
Font.Charset = ANSI_CHARSET
Font.Color = clBlack
Font.Height = -11
Font.Name = 'Arial'
Font.Size = 8
Font.Style = []
Height = 21
HideSelection = False
Left = 85 Left = 85
ShowFocus = True
TabOrder = 0
Top = 104 Top = 104
Width = 121 Width = 121
end Height = 21
object edtPhone: TWebEdit ChildOrder = 5
Alignment = taLeftJustify ElementID = 'view.userprofile.form.edtFullName'
ChildOrder = 7
Color = clWindow
ElementID = 'view.userprofile.form.edtPhone'
ElementPosition = epRelative ElementPosition = epRelative
Font.Charset = ANSI_CHARSET Font.Charset = ANSI_CHARSET
Font.Color = clBlack Font.Color = clBlack
Font.Height = -11 Font.Height = -11
Font.Name = 'Arial' Font.Name = 'Arial'
Font.Size = 8
Font.Style = [] Font.Style = []
Height = 21 HeightPercent = 100.000000000000000000
HideSelection = False HideSelection = False
Left = 85 ParentFont = False
ShowFocus = True WidthPercent = 100.000000000000000000
TabOrder = 0
Top = 128
Width = 121
end end
object chkAdminUser: TWebCheckBox object chkAdminUser: TWebCheckBox
Left = 85
Top = 179
Width = 113
Height = 22
Caption = 'chkAdminUser' Caption = 'chkAdminUser'
ChildOrder = 9 ChildOrder = 9
ElementID = 'view.userprofile.form.chkAdminUser' ElementID = 'view.userprofile.form.chkAdminUser'
...@@ -210,128 +180,72 @@ object FViewUserProfile: TFViewUserProfile ...@@ -210,128 +180,72 @@ object FViewUserProfile: TFViewUserProfile
Font.Color = clBlack Font.Color = clBlack
Font.Height = -11 Font.Height = -11
Font.Name = 'Arial' Font.Name = 'Arial'
Font.Size = 8
Font.Style = [] Font.Style = []
Height = 22 HeightPercent = 100.000000000000000000
Left = 85 ParentFont = False
Role = 'null' Role = 'null'
ShowFocus = True WidthPercent = 100.000000000000000000
TabOrder = 0
Top = 179
Width = 113
end end
object edtEmail: TWebEdit object edtEmail: TWebEdit
Alignment = taLeftJustify Left = 85
Top = 126
Width = 121
Height = 21
ChildOrder = 7 ChildOrder = 7
Color = clWindow
ElementID = 'view.userprofile.form.edtEmail' ElementID = 'view.userprofile.form.edtEmail'
ElementPosition = epRelative ElementPosition = epRelative
Font.Charset = ANSI_CHARSET Font.Charset = ANSI_CHARSET
Font.Color = clBlack Font.Color = clBlack
Font.Height = -11 Font.Height = -11
Font.Name = 'Arial' Font.Name = 'Arial'
Font.Size = 8
Font.Style = [] Font.Style = []
Height = 21 HeightPercent = 100.000000000000000000
HideSelection = False HideSelection = False
Left = 85 ParentFont = False
ShowFocus = True WidthPercent = 100.000000000000000000
TabOrder = 0
Top = 152
Width = 121
end end
object btnConfirm: TWebButton object btnConfirm: TWebButton
Left = 85
Top = 210
Width = 96
Height = 25
Caption = 'Confirm Changes' Caption = 'Confirm Changes'
ChildOrder = 12 ChildOrder = 12
Color = clNone
ElementID = 'view.userprofile.form.btnconfirm' ElementID = 'view.userprofile.form.btnconfirm'
ElementPosition = epRelative ElementPosition = epRelative
Font.Charset = ANSI_CHARSET Font.Charset = ANSI_CHARSET
Font.Color = clBlack Font.Color = clBlack
Font.Height = -11 Font.Height = -11
Font.Name = 'Arial' Font.Name = 'Arial'
Font.Size = 8
Font.Style = [] Font.Style = []
Height = 25 HeightPercent = 100.000000000000000000
Left = 85 ParentFont = False
OnClick = btnConfirmClick
Role = 'button' Role = 'button'
TabOrder = 0 WidthPercent = 100.000000000000000000
OnClick = btnConfirmClick
end
object btnCancel: TWebButton
Left = 208
Top = 210 Top = 210
Width = 96 Width = 96
end Height = 25
object WebButton1: TWebButton
Caption = 'Cancel Changes' Caption = 'Cancel Changes'
ChildOrder = 14 ChildOrder = 14
Color = clNone
ElementID = 'view.userprofile.form.btncancel' ElementID = 'view.userprofile.form.btncancel'
ElementPosition = epRelative ElementPosition = epRelative
Font.Charset = ANSI_CHARSET Font.Charset = ANSI_CHARSET
Font.Color = clBlack Font.Color = clBlack
Font.Height = -11 Font.Height = -11
Font.Name = 'Arial' Font.Name = 'Arial'
Font.Size = 8
Font.Style = [] Font.Style = []
Height = 25 HeightPercent = 100.000000000000000000
Left = 208 ParentFont = False
OnClick = WebButton1Click
Role = 'button' Role = 'button'
TabOrder = 0 WidthPercent = 100.000000000000000000
Top = 210 OnClick = btnCancelClick
Width = 96
end
object pnlMessage: TWebPanel
ChildOrder = 17
Color = clBtnFace
ElementID = 'view.login.message'
ElementPosition = epRelative
Font.Charset = ANSI_CHARSET
Font.Color = clBlack
Font.Height = -11
Font.Name = 'Arial'
Font.Size = 8
Font.Style = []
Height = 33
Left = 236
Role = 'null'
TabOrder = 8
TabStop = False
Top = 4
Width = 121
object lblMessage: TWebLabel
Caption = 'Message'
ElementID = 'view.login.message.label'
Font.Charset = ANSI_CHARSET
Font.Color = clBlack
Font.Height = -11
Font.Name = 'Arial'
Font.Size = 8
Font.Style = []
Height = 16
Left = 16
Top = 11
Width = 43
end
object btnCloseNotification: TWebButton
ChildOrder = 1
Color = clNone
ElementID = 'view.login.message.button'
Font.Charset = ANSI_CHARSET
Font.Color = clBlack
Font.Height = -11
Font.Name = 'Arial'
Font.Size = 8
Font.Style = []
Height = 25
Left = 96
OnClick = btnCloseNotificationClick
Role = 'button'
TabOrder = 0
Top = 3
Width = 22
end
end end
object XDataWebClient1: TXDataWebClient object XDataWebClient1: TXDataWebClient
Connection = DMConnection.ApiConnection
Left = 359 Left = 359
Top = 52 Top = 52
end end
......
<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>
...@@ -6,7 +6,8 @@ uses ...@@ -6,7 +6,8 @@ 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.StdCtrls, WEBLib.Forms, WEBLib.Dialogs, Vcl.Controls, Vcl.StdCtrls, WEBLib.StdCtrls,
XData.Web.Client, WEBLib.ExtCtrls, DB, XData.Web.JsonDataset, XData.Web.Client, WEBLib.ExtCtrls, DB, XData.Web.JsonDataset,
XData.Web.Dataset, XData.Web.Connection, Vcl.Forms, ConnectionModule; XData.Web.Dataset, XData.Web.Connection, Vcl.Forms, ConnectionModule,
WEBLib.Toast;
type type
TFViewUserProfile = class(TWebForm) TFViewUserProfile = class(TWebForm)
...@@ -17,27 +18,18 @@ type ...@@ -17,27 +18,18 @@ type
edtUserId: TWebEdit; edtUserId: TWebEdit;
edtFullName: TWebEdit; edtFullName: TWebEdit;
WebLabel4: TWebLabel; WebLabel4: TWebLabel;
edtPhone: TWebEdit;
WebLabel5: TWebLabel; WebLabel5: TWebLabel;
chkAdminUser: TWebCheckBox; chkAdminUser: TWebCheckBox;
edtEmail: TWebEdit; edtEmail: TWebEdit;
WebLabel6: TWebLabel;
btnConfirm: TWebButton; btnConfirm: TWebButton;
lblResult: TWebLabel; lblResult: TWebLabel;
XDataWebClient1: TXDataWebClient; XDataWebClient1: TXDataWebClient;
WebButton1: TWebButton; btnCancel: TWebButton;
pnlMessage: TWebPanel;
lblMessage: TWebLabel;
btnCloseNotification: TWebButton;
procedure WebFormShow(Sender: TObject); procedure WebFormShow(Sender: TObject);
procedure btnConfirmClick(Sender: TObject); procedure btnConfirmClick(Sender: TObject);
[async] procedure EditUser(); [async] procedure EditUser();
[async] procedure GetUser(); [async] procedure GetUser();
procedure WebButton1Click(Sender: TObject); procedure btnCancelClick(Sender: TObject);
procedure HideNotification();
procedure ShowNotification(Notification: string);
procedure btnCloseNotificationClick(Sender: TObject);
function CheckInputs(): boolean;
end; end;
var var
...@@ -47,57 +39,83 @@ implementation ...@@ -47,57 +39,83 @@ implementation
uses uses
Auth.Service, Auth.Service,
XData.Model.Classes; XData.Model.Classes,
Utils,
View.Main;
{$R *.dfm} {$R *.dfm}
procedure TFViewUserProfile.btnCloseNotificationClick(Sender: TObject);
begin
HideNotification;
end;
procedure TFViewUserProfile.btnConfirmClick(Sender: TObject); procedure TFViewUserProfile.btnConfirmClick(Sender: TObject);
var var
resultString: string; FormEl: TJSHTMLFormElement;
begin begin
FormEl := TJSHTMLFormElement(document.querySelector('form'));
if not FormEl.checkValidity then
begin
FormEl.classList.add('was-validated');
Exit;
end;
asm asm
var messageDiv = document.getElementById('view.login.message'); var modal = document.getElementById('confirmation_modal');
messageDiv.classList.remove('alert-success'); var btnCancel = document.getElementById('btn_confirm_cancel');
messageDiv.classList.add('alert-danger'); var btnConfirm = document.getElementById('btn_confirm_delete');
var modalBody = document.getElementById('modal_body');
var self = this;
if (modal && btnCancel && btnConfirm && modalBody) {
modalBody.innerText = 'Are you sure you want to save changes to your profile?';
btnCancel.innerText = 'Cancel';
btnConfirm.innerText = 'Save';
if (modal.parentNode !== document.body) {
document.body.appendChild(modal);
}
var bsModal = new bootstrap.Modal(modal, { keyboard: false });
bsModal.show();
btnConfirm.onclick = function () {
self.EditUser();
bsModal.hide();
};
}
end; end;
if CheckInputs() then
begin
EditUser();
end
end; end;
procedure TFViewUserProfile.EditUser();
[async] procedure TFViewUserProfile.EditUser;
var var
xdcResponse: TXDataClientResponse; xdcResponse: TXDataClientResponse;
responseString: TJSObject; responseString: TJSObject;
editOptions: string; editOptions, resultMsg: string;
begin begin
if(checkInputs()) then try
begin
console.log(edtFullName.Text);
editOptions := '&username=' + edtUsername.Text + editOptions := '&username=' + edtUsername.Text +
'&fullname=' + edtFullName.Text + '&fullname=' + edtFullName.Text +
'&phonenumber=' + edtPhone.Text + '&email=' + edtEmail.Text;
'&email=' + edtEmail.Text;
xdcResponse := await(XDataWebClient1.RawInvokeAsync('ILookupService.EditUser', [editOptions]));
xdcResponse := await(XDataWebClient1.RawInvokeAsync('ILookupService.EditUser', responseString := TJSObject(xdcResponse.Result);
[editOptions])); resultMsg := string(responseString['value']);
responseString := TJSObject(xdcResponse.Result);
asm Utils.ShowToast(resultMsg);
var messageDiv = document.getElementById('view.login.message');
messageDiv.classList.remove('alert-danger'); if resultMsg.ToLower.StartsWith('success:') then
messageDiv.classList.add('alert-success'); FViewMain.ViewOrders('');
end; except
ShowNotification(string(responseString['value'])); on E: EXDataClientRequestException do
Utils.ShowErrorModal('Error editing user: ' + E.ErrorResult.ErrorMessage);
on E: Exception do
Utils.ShowErrorModal('Unexpected error: ' + E.Message);
end; end;
end; end;
procedure TFViewUserProfile.WebButton1Click(Sender: TObject);
procedure TFViewUserProfile.btnCancelClick(Sender: TObject);
var var
xdcResponse: TXDataClientResponse; xdcResponse: TXDataClientResponse;
userList: TJSObject; userList: TJSObject;
...@@ -105,21 +123,17 @@ var ...@@ -105,21 +123,17 @@ var
user: TJSObject; user: TJSObject;
begin begin
GetUser(); GetUser();
showNotification('Failure:Changes discarded'); showToast('Failure: Changes discarded');
end; end;
procedure TFViewUserProfile.WebFormShow(Sender: TObject); procedure TFViewUserProfile.WebFormShow(Sender: TObject);
var
xdcResponse: TXDataClientResponse;
userList: TJSObject;
data: TJSArray;
user: TJSObject;
begin begin
HideNotification;
GetUser(); GetUser();
//edtJwt.Text := TJSJSON.stringify(AuthService.TokenPayload); //edtJwt.Text := TJSJSON.stringify(AuthService.TokenPayload);
chkAdminUser.Checked := JS.toBoolean(AuthService.TokenPayload.Properties['user_admin']); // View.UserProfile.WebFormShow
chkAdminUser.Checked := SameText(string(AuthService.TokenPayload.Properties['user_admin']), 'true');
end; end;
procedure TFViewUserProfile.GetUser; procedure TFViewUserProfile.GetUser;
...@@ -129,139 +143,22 @@ var ...@@ -129,139 +143,22 @@ var
data: TJSArray; data: TJSArray;
user: TJSObject; user: TJSObject;
begin begin
xdcResponse := await(XDataWebClient1.RawInvokeAsync('ILookupService.GetUsers', try
[JS.toString(AuthService.TokenPayload.Properties['user_name'])])); xdcResponse := await(XDataWebClient1.RawInvokeAsync('ILookupService.GetUsers',
userList := TJSObject(xdcResponse.Result); [JS.toString(AuthService.TokenPayload.Properties['user_name'])]));
data := TJSArray(userList['data']); userList := TJSObject(xdcResponse.Result);
user := TJSObject(data[0]); data := TJSArray(userList['data']);
edtUsername.Text := string(user['username']); user := TJSObject(data[0]);
edtFullName.Text := string(user['full_name']); edtUsername.Text := string(user['username']);
edtPhone.Text := string(user['phone_number']); edtFullName.Text := string(user['full_name']);
edtEmail.Text := string(user['email_address']); edtEmail.Text := string(user['email_address']);
edtUserId.Text := string(user['userID']); edtUserId.Text := string(user['userID']);
chkAdminUser.Checked := boolean(user['admin']); chkAdminUser.Checked := boolean(user['admin']);
end; except
on E: EXDataClientRequestException do
procedure TFViewUserProfile.HideNotification; Utils.ShowErrorModal('Could not retrieve users: ' + E.ErrorResult.ErrorMessage);
begin
pnlMessage.ElementHandle.hidden := True;
end;
procedure TFViewUserProfile.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;
function TFViewUserProfile.CheckInputs(): boolean;
var
checkString: string;
charIndex: integer;
phoneNum: string;
begin
Result := false;
checkString := edtFullName.Text + edtUsername.Text + edtPhone.Text + edtEmail.Text;
if string(edtFullName.Text).IsEmpty then
begin
ShowNotification('Failure:Full Name field is blank!');
exit;
end;
if string(edtUsername.Text).IsEmpty then
begin
ShowNotification('Failure:Username field is blank!');
exit;
end;
if string(edtPhone.Text).IsEmpty then
begin
ShowNotification('Failure:Phone Number field is blank!');
exit;
end;
if string(edtEmail.Text).IsEmpty then
begin
ShowNotification('Failure:Email field is blank!');
exit;
end;
if checkString.Contains('&') then
begin
ShowNotification('Failure:No fields may contain "&&"!');
exit;
end;
if string(edtEmail.Text).Contains('@') = false then
begin
ShowNotification('Failure:Please enter a valid email address');
exit;
end;
if (length(string(edtEmail.Text).Split(['@'])) <> 2) or (string(edtEmail.text).CountChar('@') > 1) then
begin
ShowNotification('Failure:Please enter a valid email address');
exit;
end;
phoneNum := edtPhone.Text;
if (not phoneNum.Contains('(')) or (not phoneNum.Contains(')')) or (not phoneNum.Contains('-')) then
begin
ShowNotification('Failure: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
begin
ShowNotification('Failure:Please enter a valid phone number');
exit;
end;
phoneNum := phoneNum.Replace('(', '');
phoneNum := phoneNum.Replace(')', '');
phoneNum := phoneNum.Replace('-', '');
phoneNum := phoneNum.Replace(' ', '');
console.log(phoneNum);
console.log(length(phoneNum));
if(length(phoneNum) <> 10) then
begin
ShowNotification('Failure:Please enter a valid phone number');
exit;
end;
for CharIndex := 1 to Length(phoneNum) do
begin
if not (phoneNum[CharIndex] in ['0' .. '9']) then
begin
console.log('here');
ShowNotification('Failure:Please enter a valid phone number');
exit;
end;
end;
result := true;
end;
end. end.
...@@ -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
......
...@@ -367,6 +367,21 @@ is-invalid .form-check-input { ...@@ -367,6 +367,21 @@ is-invalid .form-check-input {
} }
@keyframes slideInLeft {
from {
transform: translateX(-120%);
opacity: 0;
}
to {
transform: translateX(0);
opacity: 1;
}
}
.toast.slide-in {
animation: slideInLeft 0.4s ease-out forwards;
}
......
<html><head> <!DOCTYPE html>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/> <html>
<meta content="width=device-width, initial-scale=1" name="viewport"/> <head>
<noscript>Your browser does not support JavaScript!</noscript> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
<link href="data:;base64,=" rel="icon"/> <meta content="width=device-width, initial-scale=1" name="viewport"/>
<title>Web KG Orders</title> <noscript>Your browser does not support JavaScript!</noscript>
<link href="https://cdnjs.cloudflare.com/ajax/libs/flag-icon-css/2.3.1/css/flag-icon.min.css" rel="stylesheet"/> <link href="data:;base64,=" rel="icon"/>
<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"/> <title>EM Systems webKGOrders App</title>
<link crossorigin="anonymous" href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.1/dist/css/bootstrap.min.css" rel="stylesheet"/>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.1/dist/js/bootstrap.bundle.min.js" type="text/javascript"></script> <link href="https://cdnjs.cloudflare.com/ajax/libs/flag-icon-css/2.3.1/css/flag-icon.min.css" rel="stylesheet"/>
<script crossorigin="anonymous" integrity="sha256-eKhayi8LEQwp4NKxN+CfCh+3qOVUtJn3QNZ0TciWLP4=" src="https://code.jquery.com/jquery-3.7.1.js"></script> <link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet"/>
<script src="$(ProjectName).js" type="text/javascript"></script> <link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.0/css/all.min.css" rel="stylesheet"/>
<title>EM Systems webKGOrders App</title> <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="$(ProjectName).js" type="text/javascript"></script> <script crossorigin="anonymous" integrity="sha256-eKhayi8LEQwp4NKxN+CfCh+3qOVUtJn3QNZ0TciWLP4=" src="https://code.jquery.com/jquery-3.7.1.js"></script>
<body> <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.1/dist/js/bootstrap.bundle.min.js" type="text/javascript"></script>
</body> <link crossorigin="anonymous" href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.1/dist/css/bootstrap.min.css" rel="stylesheet"/>
<script type="text/javascript">rtl.run();</script> <script src="$(ProjectName).js" type="text/javascript"></script>
</head>
<body>
</body>
<script type="text/javascript">rtl.run();</script>
</html> </html>
program webKGOrders; program webKGOrders;
uses uses
......
...@@ -69,9 +69,13 @@ ...@@ -69,9 +69,13 @@
<DCC_Namespace>Winapi;System.Win;Data.Win;Datasnap.Win;Web.Win;Soap.Win;Xml.Win;Bde;$(DCC_Namespace)</DCC_Namespace> <DCC_Namespace>Winapi;System.Win;Data.Win;Datasnap.Win;Web.Win;Soap.Win;Xml.Win;Bde;$(DCC_Namespace)</DCC_Namespace>
<BT_BuildType>Debug</BT_BuildType> <BT_BuildType>Debug</BT_BuildType>
<VerInfo_IncludeVerInfo>true</VerInfo_IncludeVerInfo> <VerInfo_IncludeVerInfo>true</VerInfo_IncludeVerInfo>
<VerInfo_Keys>CompanyName=;FileDescription=$(MSBuildProjectName);FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProgramID=com.embarcadero.$(MSBuildProjectName);ProductName=$(MSBuildProjectName);ProductVersion=1.0.0.0;Comments=</VerInfo_Keys> <VerInfo_Keys>CompanyName=;FileDescription=$(MSBuildProjectName);FileVersion=0.9.5.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProgramID=com.embarcadero.$(MSBuildProjectName);ProductName=$(MSBuildProjectName);ProductVersion=0.9.5.0;Comments=</VerInfo_Keys>
<VerInfo_Locale>1033</VerInfo_Locale> <VerInfo_Locale>1033</VerInfo_Locale>
<Manifest_File>$(BDS)\bin\default_app.manifest</Manifest_File> <Manifest_File>$(BDS)\bin\default_app.manifest</Manifest_File>
<VerInfo_MajorVer>0</VerInfo_MajorVer>
<VerInfo_MinorVer>9</VerInfo_MinorVer>
<VerInfo_Release>5</VerInfo_Release>
<AppDPIAwarenessMode>none</AppDPIAwarenessMode>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition="'$(Base_Win64)'!=''"> <PropertyGroup Condition="'$(Base_Win64)'!=''">
<DCC_UsePackage>DBXSqliteDriver;DataSnapServerMidas;DBXDb2Driver;DBXInterBaseDriver;vclactnband;vclFireDAC;tethering;FireDACADSDriver;DBXMSSQLDriver;DatasnapConnectorsFreePascal;FireDACMSSQLDriver;vcltouch;vcldb;bindcompfmx;Intraweb;DBXOracleDriver;inetdb;FmxTeeUI;emsedge;fmx;fmxdae;vclib;FireDACDBXDriver;dbexpress;IndyCore;vclx;dsnap;DataSnapCommon;DataSnapConnectors;VCLRESTComponents;vclie;bindengine;DBXMySQLDriver;FireDACOracleDriver;FireDACMySQLDriver;DBXFirebirdDriver;FireDACCommonODBC;DataSnapClient;bindcompdbx;IndyIPCommon;vcl;DBXSybaseASEDriver;IndyIPServer;IndySystem;FireDACDb2Driver;dsnapcon;FireDACMSAccDriver;fmxFireDAC;FireDACInfxDriver;vclimg;TeeDB;emshosting;FireDACPgDriver;ibmonitor;FireDACASADriver;DBXOdbcDriver;FireDACTDataDriver;FMXTee;DbxCommonDriver;ibxpress;Tee;DataSnapServer;xmlrtl;DataSnapNativeClient;fmxobj;vclwinx;ibxbindings;rtl;FireDACDSDriver;DbxClientDriver;DBXSybaseASADriver;CustomIPTransport;vcldsnap;bindcomp;appanalytics;DBXInformixDriver;IndyIPClient;bindcompvcl;TeeUI;dbxcds;VclSmp;adortl;FireDACODBCDriver;DataSnapIndy10ServerTransport;dsnapxml;DataSnapProviderClient;dbrtl;inetdbxpress;FireDACMongoDBDriver;IndyProtocols;fmxase;$(DCC_UsePackage)</DCC_UsePackage> <DCC_UsePackage>DBXSqliteDriver;DataSnapServerMidas;DBXDb2Driver;DBXInterBaseDriver;vclactnband;vclFireDAC;tethering;FireDACADSDriver;DBXMSSQLDriver;DatasnapConnectorsFreePascal;FireDACMSSQLDriver;vcltouch;vcldb;bindcompfmx;Intraweb;DBXOracleDriver;inetdb;FmxTeeUI;emsedge;fmx;fmxdae;vclib;FireDACDBXDriver;dbexpress;IndyCore;vclx;dsnap;DataSnapCommon;DataSnapConnectors;VCLRESTComponents;vclie;bindengine;DBXMySQLDriver;FireDACOracleDriver;FireDACMySQLDriver;DBXFirebirdDriver;FireDACCommonODBC;DataSnapClient;bindcompdbx;IndyIPCommon;vcl;DBXSybaseASEDriver;IndyIPServer;IndySystem;FireDACDb2Driver;dsnapcon;FireDACMSAccDriver;fmxFireDAC;FireDACInfxDriver;vclimg;TeeDB;emshosting;FireDACPgDriver;ibmonitor;FireDACASADriver;DBXOdbcDriver;FireDACTDataDriver;FMXTee;DbxCommonDriver;ibxpress;Tee;DataSnapServer;xmlrtl;DataSnapNativeClient;fmxobj;vclwinx;ibxbindings;rtl;FireDACDSDriver;DbxClientDriver;DBXSybaseASADriver;CustomIPTransport;vcldsnap;bindcomp;appanalytics;DBXInformixDriver;IndyIPClient;bindcompvcl;TeeUI;dbxcds;VclSmp;adortl;FireDACODBCDriver;DataSnapIndy10ServerTransport;dsnapxml;DataSnapProviderClient;dbrtl;inetdbxpress;FireDACMongoDBDriver;IndyProtocols;fmxase;$(DCC_UsePackage)</DCC_UsePackage>
...@@ -90,13 +94,14 @@ ...@@ -90,13 +94,14 @@
<DCC_RemoteDebug>false</DCC_RemoteDebug> <DCC_RemoteDebug>false</DCC_RemoteDebug>
<VerInfo_IncludeVerInfo>true</VerInfo_IncludeVerInfo> <VerInfo_IncludeVerInfo>true</VerInfo_IncludeVerInfo>
<VerInfo_Locale>1033</VerInfo_Locale> <VerInfo_Locale>1033</VerInfo_Locale>
<VerInfo_Keys>CompanyName=;FileDescription=$(MSBuildProjectName);FileVersion=0.9.2.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProgramID=com.embarcadero.$(MSBuildProjectName);ProductName=$(MSBuildProjectName);ProductVersion=0.9.2.0;Comments=;LastCompiledTime=2018/08/27 15:18:29</VerInfo_Keys> <VerInfo_Keys>CompanyName=;FileDescription=$(MSBuildProjectName);FileVersion=0.9.5.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProgramID=com.embarcadero.$(MSBuildProjectName);ProductName=$(MSBuildProjectName);ProductVersion=0.9.5.0;Comments=;LastCompiledTime=2018/08/27 15:18:29</VerInfo_Keys>
<AppDPIAwarenessMode>PerMonitor</AppDPIAwarenessMode> <AppDPIAwarenessMode>PerMonitor</AppDPIAwarenessMode>
<VerInfo_MajorVer>0</VerInfo_MajorVer> <VerInfo_MajorVer>0</VerInfo_MajorVer>
<VerInfo_MinorVer>9</VerInfo_MinorVer> <VerInfo_MinorVer>9</VerInfo_MinorVer>
<TMSWebSingleInstance>1</TMSWebSingleInstance> <TMSWebSingleInstance>1</TMSWebSingleInstance>
<TMSUseJSDebugger>2</TMSUseJSDebugger> <TMSUseJSDebugger>2</TMSUseJSDebugger>
<VerInfo_Release>2</VerInfo_Release> <VerInfo_Release>5</VerInfo_Release>
<TMSWebBrowser>3</TMSWebBrowser>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition="'$(Cfg_2)'!=''"> <PropertyGroup Condition="'$(Cfg_2)'!=''">
<DCC_LocalDebugSymbols>false</DCC_LocalDebugSymbols> <DCC_LocalDebugSymbols>false</DCC_LocalDebugSymbols>
...@@ -107,11 +112,13 @@ ...@@ -107,11 +112,13 @@
<TMSWebDefines>RELEASE</TMSWebDefines> <TMSWebDefines>RELEASE</TMSWebDefines>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition="'$(Cfg_2_Win32)'!=''"> <PropertyGroup Condition="'$(Cfg_2_Win32)'!=''">
<VerInfo_Build>8</VerInfo_Build> <VerInfo_Keys>CompanyName=;FileDescription=$(MSBuildProjectName);FileVersion=0.9.6.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProgramID=com.embarcadero.$(MSBuildProjectName);ProductName=$(MSBuildProjectName);ProductVersion=0.9.6.0;Comments=;LastCompiledTime=2018/08/22 16:25:56</VerInfo_Keys>
<VerInfo_Keys>CompanyName=;FileDescription=$(MSBuildProjectName);FileVersion=1.0.0.8;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProgramID=com.embarcadero.$(MSBuildProjectName);ProductName=$(MSBuildProjectName);ProductVersion=1.0.0.0;Comments=;LastCompiledTime=2018/08/22 16:25:56</VerInfo_Keys>
<VerInfo_IncludeVerInfo>true</VerInfo_IncludeVerInfo> <VerInfo_IncludeVerInfo>true</VerInfo_IncludeVerInfo>
<VerInfo_Locale>1033</VerInfo_Locale> <VerInfo_Locale>1033</VerInfo_Locale>
<AppDPIAwarenessMode>PerMonitor</AppDPIAwarenessMode> <AppDPIAwarenessMode>PerMonitor</AppDPIAwarenessMode>
<VerInfo_MajorVer>0</VerInfo_MajorVer>
<VerInfo_MinorVer>9</VerInfo_MinorVer>
<VerInfo_Release>6</VerInfo_Release>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<DelphiCompile Include="$(MainSource)"> <DelphiCompile Include="$(MainSource)">
......
...@@ -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
......
...@@ -110,7 +110,7 @@ begin ...@@ -110,7 +110,7 @@ begin
OrdersDB.UniQuery1.SQL.Text := SQL; OrdersDB.UniQuery1.SQL.Text := SQL;
OrdersDB.UniQuery1.ExecSQL; OrdersDB.UniQuery1.ExecSQL;
result := TJSONObject.Create; result := TJSONObject.Create;
result.AddPair('status', 'Success:Address Successfully Deleted'); result.AddPair('status', 'Success: Address Successfully Deleted');
SQL := 'select * FROM customers c LEFT JOIN customers_ship s ON c.CUSTOMER_ID = s.customer_id WHERE c.CUSTOMER_ID = ' + CustomerID; SQL := 'select * FROM customers c LEFT JOIN customers_ship s ON c.CUSTOMER_ID = s.customer_id WHERE c.CUSTOMER_ID = ' + CustomerID;
doQuery(ordersDB.UniQuery1, SQL); doQuery(ordersDB.UniQuery1, SQL);
ADDRESS_LIST := TJSONArray.Create; ADDRESS_LIST := TJSONArray.Create;
...@@ -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.
...@@ -254,11 +255,9 @@ end; ...@@ -254,11 +255,9 @@ end;
function TLookupService.GenerateOrderListPDF(searchOptions: string): string; function TLookupService.GenerateOrderListPDF(searchOptions: string): string;
// Generates a report pdf based on the last search (if any) Linked to rOrders
// file which does most of the work.
var var
SQL: string; SQL: string;
rptOrderList: TrptOrderList; // Local instance of rptOrders rptOrderList: TrptOrderList;
CompanyID, CompanyName: string; CompanyID, CompanyName: string;
params: TStringList; params: TStringList;
begin begin
...@@ -267,9 +266,16 @@ begin ...@@ -267,9 +266,16 @@ begin
try try
params := TStringList.Create; params := TStringList.Create;
params.StrictDelimiter := true; params.StrictDelimiter := true;
// parse the searchOptions
params.Delimiter := '&'; params.Delimiter := '&';
params.DelimitedText := searchOptions; params.DelimitedText := searchOptions;
// Strip paging if this is a PDF export
if params.Values['forPDF'] = 'true' then
begin
params.Values['pagesize'] := '';
params.Values['pagenumber'] := '';
end;
companyID := params.Values['companyID']; companyID := params.Values['companyID'];
if companyID <> '' then if companyID <> '' then
begin begin
...@@ -280,11 +286,10 @@ begin ...@@ -280,11 +286,10 @@ begin
else else
CompanyName := ''; CompanyName := '';
SQL := GenerateOrdersSQL(searchOptions).SQL; SQL := GenerateOrdersSQL(params.DelimitedText).SQL;
result := rptOrderList.PrepareReport(SQL, CompanyName); result := rptOrderList.PrepareReport(SQL, CompanyName);
// Optionally, log success Logger.log(5, 'PDF Report successfully generated for searchOptions: ' + params.DelimitedText);
Logger.log(5, 'PDF Report successfully generated for searchOptions: ' + searchOptions);
except except
on E: Exception do on E: Exception do
raise EXDataHttpException.Create(500, 'Failed to generate PDF: ' + E.Message); raise EXDataHttpException.Create(500, 'Failed to generate PDF: ' + E.Message);
...@@ -295,6 +300,7 @@ begin ...@@ -295,6 +300,7 @@ begin
end; end;
function TLookupService.AddShippingAddress(AddressInfo: string): TJSONObject; function TLookupService.AddShippingAddress(AddressInfo: string): TJSONObject;
var var
JSONData: TJSONObject; JSONData: TJSONObject;
...@@ -356,10 +362,10 @@ begin ...@@ -356,10 +362,10 @@ begin
if mode = 'ADD' then if mode = 'ADD' then
begin begin
msg := 'Success:Shipping Address Successfully Added'; msg := 'Success: Shipping Address Successfully Added';
end end
else else
msg := 'Success:Shipping Address Successfully Edited'; msg := 'Success: Shipping Address Successfully Edited';
// Sends the updated Address List Back. // Sends the updated Address List Back.
...@@ -485,9 +491,9 @@ begin ...@@ -485,9 +491,9 @@ begin
ordersDB.UniQuery1.Post; ordersDB.UniQuery1.Post;
if mode = 'ADD' then if mode = 'ADD' then
msg := 'Success:Customer Successfully Added' msg := 'Success: Customer Successfully Added'
else else
msg := 'Success:Customer Successfully Edited'; msg := 'Success: Customer Successfully Edited';
Result := TJSONObject.Create.AddPair('status', msg); Result := TJSONObject.Create.AddPair('status', msg);
...@@ -720,104 +726,81 @@ function TLookupService.generateOrdersSQL(searchOptions: string): TSQLQuery; ...@@ -720,104 +726,81 @@ function TLookupService.generateOrdersSQL(searchOptions: string): TSQLQuery;
// searchOptions: search information sent form client to be parsed. // searchOptions: search information sent form client to be parsed.
var var
params: TStringList; params: TStringList;
PageNum: integer; PageNum, PageSize: integer;
PageSize: integer; OrderBy, offset, limit: string;
OrderBy: string; SQL, whereSQL, orderBySQL: string;
offset: string; OrderID, CompanyID, JobName, orderType: string;
limit: string; status1, status2: TStatusSearchInfo;
SQL: string; ForPDF: Boolean;
whereSQL: string;
orderBySQL: string;
OrderID: string;
CompanyID: string;
JobName: string;
orderType: string;
// These variables apply to the first status sent from the client
status1: TStatusSearchInfo;
// These variables apply to the second status sent from the client
status2: TStatusSearchInfo;
begin begin
result := TSQLQuery.Create; result := TSQLQuery.Create;
params := TStringList.Create; params := TStringList.Create;
params.StrictDelimiter := true; params.StrictDelimiter := true;
// parse the searchOptions
params.Delimiter := '&'; params.Delimiter := '&';
params.DelimitedText := searchOptions; params.DelimitedText := searchOptions;
orderBySQL := ''; ForPDF := SameText(params.Values['forPDF'], 'true');
PageNum := StrToInt(params.Values['pagenumber']);
PageSize := StrToInt(params.Values['pagesize']); if not ForPDF then
begin
PageNum := StrToIntDef(params.Values['pagenumber'], 1);
PageSize := StrToIntDef(params.Values['pagesize'], 500);
offset := IntToStr((PageNum - 1) * PageSize);
limit := IntToStr(PageSize);
end;
OrderBy := params.Values['orderby']; OrderBy := params.Values['orderby'];
orderType := params.Values['orderType'].ToLower(); orderType := params.Values['orderType'].ToLower();
OrderID := params.Values['orderID']; OrderID := params.Values['orderID'];
companyID := params.Values['companyID']; companyID := params.Values['companyID'];
jobName := params.Values['jobName']; jobName := params.Values['jobName'];
// Search infomation for first status type
status1 := createStatusSearchInfo(params, '1'); status1 := createStatusSearchInfo(params, '1');
// Search Information for second status type
status2 := createStatusSearchInfo(params, '2'); status2 := createStatusSearchInfo(params, '2');
offset := IntToStr((PageNum - 1) * PageSize); SQL := 'SELECT o.ORDER_ID, c.SHORT_NAME, o.LOCATION AS Loc, c.NAME AS COMPANY_NAME, o.JOB_NAME, o.ORDER_TYPE, ' +
limit := IntToStr(PageSize); generateSubquery('PROOF') +
generateSubquery('ART') +
SQL := 'SELECT o.ORDER_ID, c.SHORT_NAME, o.LOCATION AS Loc, c.NAME AS COMPANY_NAME, o.JOB_NAME, o.ORDER_TYPE, '; generateSubquery('PLATE') +
generateSubquery('MOUNT') +
generateSubquery('SHIP');
// Generate the subqueries that get the Status Dates(Due and Done) whereSQL := ' FROM orders o JOIN customers c ON c.CUSTOMER_ID = o.COMPANY_ID ' +
SQL := SQL + generateSubquery('PROOF'); 'LEFT JOIN qb_sales_orders qb ON qb.ORDER_ID = o.ORDER_ID ' +
SQL := SQL + generateSubquery('ART'); 'LEFT JOIN corrugated_plate_orders cpo ON o.ORDER_ID = cpo.ORDER_ID ' +
SQL := SQL + generateSubquery('PLATE'); 'LEFT JOIN web_plate_orders wpo ON o.ORDER_ID = wpo.ORDER_ID ' +
SQL := SQL + generateSubquery('MOUNT'); 'LEFT JOIN cutting_die_orders cdo ON o.ORDER_ID = cdo.ORDER_ID WHERE 0 = 0';
SQL := SQL + generateSubquery('SHIP');
// Generate the Where SQL based on if there is a status filter applied or not if (status1.filterType <> '') and (status1.filterType <> 'NONE') then
whereSQL := 'from orders o join customers c on ' +
'c.CUSTOMER_ID = o.COMPANY_ID left join qb_sales_orders qb on qb.ORDER_ID = o.ORDER_ID ' +
' LEFT JOIN corrugated_plate_orders cpo ON o.ORDER_ID = cpo.ORDER_ID ' +
'LEFT JOIN web_plate_orders wpo ON o.ORDER_ID = wpo.ORDER_ID ' +
'LEFT JOIN cutting_die_orders cdo ON o.ORDER_ID = cdo.ORDER_ID where 0 = 0';
if ( ( status1.filterType <> '' ) and ( status1.filterType <> 'NONE' ) ) then
whereSQL := whereSQL + generateStatusWhereSQL(status1); whereSQL := whereSQL + generateStatusWhereSQL(status1);
if (status2.filterType <> '') and (status2.filterType <> 'NONE') then
if ( (status2.filterType <> '' ) and ( status2.filterType <> 'NONE' ) ) then
whereSQL := whereSQL + generateStatusWhereSQL(status2); whereSQL := whereSQL + generateStatusWhereSQL(status2);
if (orderType <> '') and (orderType <> 'any') then
if ( ( orderType <> '' ) and ( orderType <> 'any' ) ) then
begin begin
if ( orderType <> 'cutting die') then if (orderType <> 'cutting die') then
whereSQL := whereSQL + ' AND o.ORDER_TYPE = ' + quotedStr(orderType + '_plate') whereSQL := whereSQL + ' AND o.ORDER_TYPE = ' + QuotedStr(orderType + '_plate')
else else
whereSQL := whereSQL + ' AND o.ORDER_TYPE = ' + quotedStr('cutting_die'); whereSQL := whereSQL + ' AND o.ORDER_TYPE = ' + QuotedStr('cutting_die');
end; end;
if OrderID <> '' then
if orderID <> '' then whereSQL := whereSQL + ' AND o.ORDER_ID = ' + OrderID;
whereSQL := whereSQL + ' AND o.ORDER_ID = ' + orderID;
if companyID <> '' then if companyID <> '' then
whereSQL := whereSQL + ' AND c.CUSTOMER_ID = ' + companyID; whereSQL := whereSQL + ' AND c.CUSTOMER_ID = ' + companyID;
if jobName <> '' then if jobName <> '' then
whereSQL := whereSQL + ' AND o.JOB_NAME LIKE ' + quotedStr('%' + jobName + '%'); whereSQL := whereSQL + ' AND o.JOB_NAME LIKE ' + QuotedStr('%' + jobName + '%');
orderBySQL := 'ORDER BY ' + OrderBy; orderBySQL := ' ORDER BY ' + OrderBy;
SQL := SQL + 'o.PRICE, qb.QB_REF_NUM, ' + SQL := SQL + ' o.PRICE, qb.QB_REF_NUM, ' +
'coalesce( cpo.staff_fields_po_number, wpo.staff_fields_po_number, cdo.staff_fields_po_number ) AS po_number, ' + 'COALESCE(cpo.staff_fields_po_number, wpo.staff_fields_po_number, cdo.staff_fields_po_number) AS po_number, ' +
'coalesce( cpo.staff_fields_quickbooks_item, wpo.staff_fields_quickbooks_item, cdo.staff_fields_quickbooks_item ) AS quickbooks_item, ' + 'COALESCE(cpo.staff_fields_quickbooks_item, wpo.staff_fields_quickbooks_item, cdo.staff_fields_quickbooks_item) AS quickbooks_item, ' +
'coalesce( cpo.staff_fields_order_date, wpo.staff_fields_order_date, cdo.staff_fields_order_date ) AS ORDER_DATE ' + 'COALESCE(cpo.staff_fields_order_date, wpo.staff_fields_order_date, cdo.staff_fields_order_date) AS ORDER_DATE ';
whereSQL + ' ' + orderBySQL + ' LIMIT ' + limit + ' OFFSET ' + offset;
if not ForPDF then
SQL := SQL + whereSQL + orderBySQL + ' LIMIT ' + limit + ' OFFSET ' + offset
else
SQL := SQL + whereSQL + orderBySQL;
// send the SQL and whereSQL back. whereSQL is needed to get the total count.
// probably a way to getthe TotalCount in original SQL but it was giving me issues
result.SQL := SQL; result.SQL := SQL;
result.whereSQL := whereSQL; result.whereSQL := whereSQL;
end; end;
...@@ -1426,22 +1409,32 @@ begin ...@@ -1426,22 +1409,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 +1442,42 @@ begin ...@@ -1449,32 +1442,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.
...@@ -1558,7 +1561,7 @@ begin ...@@ -1558,7 +1561,7 @@ begin
end;} end;}
ordersDB.UniQuery1.Post; ordersDB.UniQuery1.Post;
Result := 'Success: Edit Successful'; Result := 'Success: User Successfully Edited';
end; end;
ordersDB.UniQuery1.Close; ordersDB.UniQuery1.Close;
end; end;
...@@ -1663,7 +1666,7 @@ begin ...@@ -1663,7 +1666,7 @@ begin
else else
TDateTimeField(Field).AsDateTime := StrToDate(Pair.JsonValue.Value); TDateTimeField(Field).AsDateTime := StrToDate(Pair.JsonValue.Value);
end end
else if Pair.JsonValue.Value <> '' then else
Field.AsString := Pair.JsonValue.Value; Field.AsString := Pair.JsonValue.Value;
end; end;
end; end;
...@@ -1686,9 +1689,9 @@ begin ...@@ -1686,9 +1689,9 @@ begin
addToRevisionsTable(intToStr(ORDER_ID), 'corrugated_plate_orders_revisions', JSONData); addToRevisionsTable(intToStr(ORDER_ID), 'corrugated_plate_orders_revisions', JSONData);
if mode = 'ADD' then if mode = 'ADD' then
msg := 'Success:Order Successfully Added' msg := 'Success: Order Successfully Added'
else else
msg := 'Success:Order Successfully Edited'; msg := 'Success: Order Successfully Edited';
Result := TJSONObject.Create.AddPair('status', msg); Result := TJSONObject.Create.AddPair('status', msg);
Result.AddPair('OrderID', ORDER_ID); Result.AddPair('OrderID', ORDER_ID);
...@@ -1703,7 +1706,6 @@ begin ...@@ -1703,7 +1706,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 +1895,9 @@ begin ...@@ -1893,9 +1895,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,65 +1910,68 @@ var ...@@ -1908,65 +1910,68 @@ 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';
end end
else else
Result := 'Failure:Username already taken'; Result := 'Failure: Username already taken';
except except
on E: Exception do on E: Exception do
raise EXDataHttpException.Create(500, 'AddUser failed: ' + E.Message); raise EXDataHttpException.Create(500, 'AddUser failed: ' + E.Message);
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
...@@ -2005,7 +2010,7 @@ begin ...@@ -2005,7 +2010,7 @@ begin
ordersDB.UniQuery1.FieldByName('status').AsString := 'INACTIVE'; ordersDB.UniQuery1.FieldByName('status').AsString := 'INACTIVE';
ordersDB.UniQuery1.Post; ordersDB.UniQuery1.Post;
Result.AddPair('msg', 'Success:Item successfully added'); Result.AddPair('msg', 'Success: Item successfully added');
end end
else else
Result.AddPair('msg', 'Failure: Item already exists'); Result.AddPair('msg', 'Failure: Item already exists');
...@@ -2100,7 +2105,7 @@ begin ...@@ -2100,7 +2105,7 @@ begin
else else
TDateTimeField(Field).AsDateTime := StrToDate(Pair.JsonValue.Value); TDateTimeField(Field).AsDateTime := StrToDate(Pair.JsonValue.Value);
end end
else if Pair.JsonValue.Value <> '' then else
Field.AsString := Pair.JsonValue.Value; Field.AsString := Pair.JsonValue.Value;
end; end;
end; end;
...@@ -2122,9 +2127,9 @@ begin ...@@ -2122,9 +2127,9 @@ begin
AddToRevisionsTable(IntToStr(ORDER_ID), 'web_plate_orders_revisions', JSONData); AddToRevisionsTable(IntToStr(ORDER_ID), 'web_plate_orders_revisions', JSONData);
if mode = 'ADD' then if mode = 'ADD' then
msg := 'Success:Order Successfully Added' msg := 'Success: Order Successfully Added'
else else
msg := 'Success:Order Successfully Edited'; msg := 'Success: Order Successfully Edited';
Result := TJSONObject.Create.AddPair('status', msg); Result := TJSONObject.Create.AddPair('status', msg);
Result.AddPair('OrderID', ORDER_ID); Result.AddPair('OrderID', ORDER_ID);
...@@ -2195,7 +2200,7 @@ begin ...@@ -2195,7 +2200,7 @@ begin
else else
TDateTimeField(Field).AsDateTime := StrToDate(Pair.JsonValue.Value); TDateTimeField(Field).AsDateTime := StrToDate(Pair.JsonValue.Value);
end end
else if Pair.JsonValue.Value <> '' then else
Field.AsString := Pair.JsonValue.Value; Field.AsString := Pair.JsonValue.Value;
end; end;
end; end;
...@@ -2213,9 +2218,9 @@ begin ...@@ -2213,9 +2218,9 @@ begin
AddToRevisionsTable(IntToStr(ORDER_ID), 'cutting_die_orders_revisions', JSONData); AddToRevisionsTable(IntToStr(ORDER_ID), 'cutting_die_orders_revisions', JSONData);
if mode = 'ADD' then if mode = 'ADD' then
msg := 'Success:Order Successfully Added' msg := 'Success: Order Successfully Added'
else else
msg := 'Success:Order Successfully Edited'; msg := 'Success: Order Successfully Edited';
Result := TJSONObject.Create.AddPair('status', msg); Result := TJSONObject.Create.AddPair('status', msg);
Result.AddPair('OrderID', ORDER_ID); Result.AddPair('OrderID', ORDER_ID);
...@@ -2424,6 +2429,7 @@ begin ...@@ -2424,6 +2429,7 @@ begin
ordersDB.UniQuery1.Post; ordersDB.UniQuery1.Post;
end; end;
function TLookupService.getQBCustomers: TJSONArray; function TLookupService.getQBCustomers: TJSONArray;
var var
iniFile: TIniFile; iniFile: TIniFile;
...@@ -2566,6 +2572,7 @@ begin ...@@ -2566,6 +2572,7 @@ begin
end; end;
end; end;
function TLookupService.GetQBItems: TJSONArray; function TLookupService.GetQBItems: TJSONArray;
var var
restClient: TRESTClient; restClient: TRESTClient;
...@@ -2752,6 +2759,7 @@ begin ...@@ -2752,6 +2759,7 @@ begin
end; end;
end; end;
procedure TLookupService.SaveTokens(AccessToken, RefreshToken: string); procedure TLookupService.SaveTokens(AccessToken, RefreshToken: string);
var var
f: TStringList; f: TStringList;
...@@ -2845,9 +2853,9 @@ begin ...@@ -2845,9 +2853,9 @@ begin
OrdersDB.UniQuery1.Post; OrdersDB.UniQuery1.Post;
if mode = 'ADD' then if mode = 'ADD' then
msg := 'Success:Customer Successfully Added' msg := 'Success: Customer Successfully Added'
else else
msg := 'Success:Customer Successfully Edited'; msg := 'Success: Customer Successfully Edited';
Result := TJSONObject.Create; Result := TJSONObject.Create;
Result.AddPair('status', msg); Result.AddPair('status', msg);
......
...@@ -116,8 +116,8 @@ ...@@ -116,8 +116,8 @@
<DCC_UnitSearchPath>C:\RADTOOLS\FastMM4;$(DCC_UnitSearchPath)</DCC_UnitSearchPath> <DCC_UnitSearchPath>C:\RADTOOLS\FastMM4;$(DCC_UnitSearchPath)</DCC_UnitSearchPath>
<VerInfo_MajorVer>0</VerInfo_MajorVer> <VerInfo_MajorVer>0</VerInfo_MajorVer>
<VerInfo_MinorVer>9</VerInfo_MinorVer> <VerInfo_MinorVer>9</VerInfo_MinorVer>
<VerInfo_Release>4</VerInfo_Release> <VerInfo_Release>6</VerInfo_Release>
<VerInfo_Keys>CompanyName=EM Systems;FileDescription=$(MSBuildProjectName);FileVersion=0.9.4.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProgramID=com.embarcadero.$(MSBuildProjectName);ProductName=$(MSBuildProjectName);ProductVersion=0.9.4.0;Comments=</VerInfo_Keys> <VerInfo_Keys>CompanyName=EM Systems;FileDescription=$(MSBuildProjectName);FileVersion=0.9.6.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProgramID=com.embarcadero.$(MSBuildProjectName);ProductName=$(MSBuildProjectName);ProductVersion=0.9.6.0;Comments=</VerInfo_Keys>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition="'$(Cfg_1_Win64)'!=''"> <PropertyGroup Condition="'$(Cfg_1_Win64)'!=''">
<AppDPIAwarenessMode>PerMonitorV2</AppDPIAwarenessMode> <AppDPIAwarenessMode>PerMonitorV2</AppDPIAwarenessMode>
......
[Settings] [Settings]
MemoLogLevel=3 MemoLogLevel=3
FileLogLevel=5 FileLogLevel=5
webClientVersion=0.9.4 webClientVersion=0.9.6
LogFileNum=735 LogFileNum=756
[Database] [Database]
Server=192.168.159.131 Server=192.168.159.151
--Server=192.168.102.130 --Server=192.168.102.130
--Server=192.168.75.133 --Server=192.168.75.133
Database=kg_order_entry Database=kg_order_entry
...@@ -17,6 +17,9 @@ Password=emsys01 ...@@ -17,6 +17,9 @@ Password=emsys01
CompanyID=9341454272655710 CompanyID=9341454272655710
ClientID=ABgO14uvjh8XqLud7spQ8lkb98AUpcdA7HbyMJfCAtl65sQ5yy ClientID=ABgO14uvjh8XqLud7spQ8lkb98AUpcdA7HbyMJfCAtl65sQ5yy
ClientSecret=bQ06TRemHeAGFzVHRaTUvUoBU9jpU9itK6MOMgqN ClientSecret=bQ06TRemHeAGFzVHRaTUvUoBU9jpU9itK6MOMgqN
RefreshToken=RT1-251-H0-1759499151mghzkhn74tjkqi2vg5c0
AccessToken=eyJhbGciOiJkaXIiLCJlbmMiOiJBMTI4Q0JDLUhTMjU2IiwieC5vcmciOiJIMCJ9..BPFIXN1xTjdWuZGjkh1jUQ.IghcYUEoPWx47KnmuIbgZBNm1EhInMZjAXUi68M-l6zZkuKnlQYmbYq6gC3gIyTd66cx85t7pMmdBAH_q-v3qkUKx2ZqVSRZyYVKSrxYWFl0Vafzbj_BY-4kjrGEqZRFtR4dfQfbFmmlDW215Vjn8MO9v3tvgAVbWO9kafJ3Frv4KtNRgJQPmC01nz4ixF5RD91EnCSo-q4DuuRtCERkjjIiEW9D8ODt1GexshbHxam7dWCDGM2yHX_V0trWi37X5jBBrWgTYRogXhTPfpvlfkCQKTrNmKWhVDuVUxJB3aPREI43IMlW6h3hf445quAjINvgK5wokDCnmVPW3XvIDvnckgAaa9qOLzpl5UktpjqDRRiI4zVNs6BXP7kCsZs9ez0Ai5oeWgj0_j0NKbuVW1exkLcrinmYrMny-s8XpADNDslW8XCmJnHPsOWqZZL5bEXFJXPcYfPkGkV7rt-ln84gRD9413Ji05cmOzO1X5ClhrRhFRwjT3dbrgh88Dro-vMNs3weRdYOVpYFvA5aDXs9xkmHx8auphCdZo5a3sB8n9iKiM618HR-mSeYwCIU3aF2xE8kx0ljH8qVgX1bI2w9ByfM-mNBkasu3uKDH3HcpfqJBKWNOkG692JjzBoy.6H4UaInosVyqlMSCqGMAaA
LastRefresh=6/24/2025 10:51:36 AM
RefreshToken=RT1-251-H0-1759499151mghzkhn74tjkqi2vg5c0 RefreshToken=RT1-251-H0-1759499151mghzkhn74tjkqi2vg5c0
AccessToken=eyJhbGciOiJkaXIiLCJlbmMiOiJBMTI4Q0JDLUhTMjU2IiwieC5vcmciOiJIMCJ9..swWerhSONJsQ3kK2n0Z6Mw.hKhH99-B-e1no4mO69AheB1JQi9AVo_2uT_e9Urpto2s_JM_hGuytHiCYkSAt6f8KVoej5YXyB2JRjteqO0FbxLa6UwEx2zYfgKV2bdVDlHWjU1f3nVtJw7RNXc3kOUL8xHDo7a-wAdAl7u3f7HWHxyptZac49L4iZCQ-wTVKHGATp6GIhmS8Al4ICPDV0BGLOLVsc69xIi2vqJwQgfazilPfJAB_9p3hHlpv0xafuAUNpBUATTDSVO8C65cuPQ_pGNZIR4MPjTZIH0vgmOruFsyOynqO1JyZd_bqOCGhO0bS0pfDdoLai1XERlnQsb_2UXE2arFvEqygEq1oqSglj0vW_uy8F6XWoR1mmwr68MXMRE_IbauNV4LuXnYBm_qh2vztX6fk7r-Cja51508Z-YjjBi4uwEpnKf7dBBNpI6J-z7bfKffuVRdVBxuQo1ZUePwz6Df41nkjPqv1cw3NLp4IyyCToqX_wzGhnkx19zzMbjkK5ZaHRxpsms29qpHxpikR8QOtXni0o2DBK9xNGhRuCRTPxuEDZzaf26_c258rz0bd2xFl0IfMsfid9iki8O_u6KLfDcQJPPR50UI150HqvNlzPZQuYBRKzXDnwv7h75igYH0NH2rwellgU_k.Y_Nxh6SpCFATsEzsAUs26g AccessToken=eyJhbGciOiJkaXIiLCJlbmMiOiJBMTI4Q0JDLUhTMjU2IiwieC5vcmciOiJIMCJ9..swWerhSONJsQ3kK2n0Z6Mw.hKhH99-B-e1no4mO69AheB1JQi9AVo_2uT_e9Urpto2s_JM_hGuytHiCYkSAt6f8KVoej5YXyB2JRjteqO0FbxLa6UwEx2zYfgKV2bdVDlHWjU1f3nVtJw7RNXc3kOUL8xHDo7a-wAdAl7u3f7HWHxyptZac49L4iZCQ-wTVKHGATp6GIhmS8Al4ICPDV0BGLOLVsc69xIi2vqJwQgfazilPfJAB_9p3hHlpv0xafuAUNpBUATTDSVO8C65cuPQ_pGNZIR4MPjTZIH0vgmOruFsyOynqO1JyZd_bqOCGhO0bS0pfDdoLai1XERlnQsb_2UXE2arFvEqygEq1oqSglj0vW_uy8F6XWoR1mmwr68MXMRE_IbauNV4LuXnYBm_qh2vztX6fk7r-Cja51508Z-YjjBi4uwEpnKf7dBBNpI6J-z7bfKffuVRdVBxuQo1ZUePwz6Df41nkjPqv1cw3NLp4IyyCToqX_wzGhnkx19zzMbjkK5ZaHRxpsms29qpHxpikR8QOtXni0o2DBK9xNGhRuCRTPxuEDZzaf26_c258rz0bd2xFl0IfMsfid9iki8O_u6KLfDcQJPPR50UI150HqvNlzPZQuYBRKzXDnwv7h75igYH0NH2rwellgU_k.Y_Nxh6SpCFATsEzsAUs26g
......
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