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="col-12 col-md-8">
<div class="row"> <div class="row">
<div class=col-sm> <div class="col-lg-10 col-xl-8 mx-auto">
<div id="view.login.message" class="alert alert-danger"> <form id="edituserform" class="row g-3 needs-validation" 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="col-md-6">
</div> <label id="lblfullname" for="edtfullname" class="form-label">Full&nbsp;Name</label>
</div> <input id="edtfullname" class="form-control" required>
</div> <div class="invalid-feedback">Full Name is required.</div>
<form class="form-inline"> </div>
<div class="row">
<div class="col-sm"> <div class="col-md-6">
<label class= 'pe-2' style="font-weight: 700;font-size: 15px;"id="lblfullname">Full Name:</label> <label id="lblusername" for="edtusername" class="form-label">Username</label>
<input id="edtfullname" class= "form-control input-sm" width='50%'/> <input id="edtusername" class="form-control" required>
</div> <div class="invalid-feedback">Username is required.</div>
<div class="col-sm"> </div>
<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 class="col-md-6">
</div> <label id="lblpassword" for="edtpassword" class="form-label">Password</label>
</div> <input id="edtpassword" type="password" class="form-control" required>
</form> <div class="invalid-feedback">Passwords must match.</div>
<form class="form-inline"> </div>
<div class="row">
<div class="col-sm"> <div class="col-md-6">
<label class='pe-2' style="font-weight: 700;font-size: 15px;"id="lblpassword">Password:</label> <label id="lblconfirm" for="edtconfirmpassword" class="form-label">Confirm&nbsp;Password</label>
<input id="edtpassword" class= "form-control input-sm" width='50%'/> <input id="edtconfirmpassword" type="password" class="form-control" required disabled>
</div> <div class="invalid-feedback">Passwords must match.</div>
<div class="col-sm"> </div>
<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 class="col-md-6">
</div> <label id="lblemail" for="edtemail" class="form-label">Email&nbsp;Address</label>
</div> <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> </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> </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 if not FormEl.checkValidity then
begin begin
ShowNotification('Username field is blank!'); FormEl.classList.add('was-validated');
exit; Exit;
end; end;
if string(edtPassword.Text).IsEmpty then Utils.ShowSpinner('spinner');
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
begin
ShowNotification('Phone Number field is blank!');
exit;
end;
if string(edtEmail.Text).IsEmpty then
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
if Confirm = '' then
begin begin
if not (phoneNum[CharIndex] in ['0' .. '9']) then ConfirmInput.setCustomValidity('');
begin ConfirmInput.classList.remove('is-invalid');
console.log('here'); ConfirmInput.classList.remove('is-valid');
ShowNotification('Please enter a valid phone number'); end
exit; else if Confirm = Pwd then
end;
end;
if edtPassword.Text <> edtConfirmPassword.Text then
begin begin
ShowNotification('Passwords must match!'); ConfirmInput.setCustomValidity('');
exit; ConfirmInput.classList.add('is-valid');
end; ConfirmInput.classList.remove('is-invalid');
end
if (length(edtPassword.Text) > 20) or (length(edtPassword.Text) < 6) then else
begin begin
ShowNotification('Passwords must be between 6-20 characters!'); ConfirmInput.setCustomValidity('Passwords must match');
exit; ConfirmInput.classList.add('is-invalid');
ConfirmInput.classList.remove('is-valid');
end; 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. 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>
...@@ -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>
...@@ -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 class="col-auto">
<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>
<div id="additionalFields" class="row mt-3"></div>
</div> </div>
</div> </div>
<h4 class="custom-h4 mt-3">Colors</h4>
<hr class="custom-hr">
<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>
<!-- 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>
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 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
// 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
<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"
</div> for="view.userprofile.form.edtUserID"
<div role="form"> class="form-label">User&nbsp;ID</label>
<div class="form-group"> <input id="view.userprofile.form.edtUserID"
<label id="view.userprofile.form.lblUserID">User ID:</label> class="form-control"
<input id="view.userprofile.form.edtUserID" class="form-control"> readonly>
</div>
<div class="form-group">
<label id="view.userprofile.form.lblUserName">Username:</label>
<input id="view.userprofile.form.edtUsername" class="form-control">
</div>
<div class="form-group">
<label id="view.userprofile.form.lblFullName">Full Name:</label>
<input id="view.userprofile.form.edtFullName" class="form-control">
</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>
<div class="form-group">
<label id="view.userprofile.form.lblEmail">Email Address:</label> <div class="mb-3">
<input id="view.userprofile.form.edtEmail" class="form-control"> <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>
<div class="custom-control custom-checkbox">
<input type="checkbox" class="custom-control-input" id="view.userprofile.form.chkAdminUser"> <div class="mb-3">
<label class="custom-control-label" for="view.userprofile.form.chkAdminUser">Admin User</label> <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>
<div class="form-group">
<button class="btn btn-primary" id="view.userprofile.form.btnconfirm">Confirm Changes</button> <div class="mb-3">
<button class="btn btn-primary" id="view.userprofile.form.btncancel">Xancel Changes</button> <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>
<div class="form-group">
<label id="view.userprofile.form.lblresult"></label> <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 class="d-flex gap-2 mb-4">
<button id="view.userprofile.form.btnconfirm"
class="btn btn-primary flex-grow-1"
type="button">
Confirm&nbsp;Changes
</button>
<button id="view.userprofile.form.btncancel"
class="btn btn-outline-secondary flex-grow-1"
type="button">
Cancel&nbsp;Changes
</button>
</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', xdcResponse := await(XDataWebClient1.RawInvokeAsync('ILookupService.EditUser', [editOptions]));
[editOptions]));
responseString := TJSObject(xdcResponse.Result); responseString := TJSObject(xdcResponse.Result);
asm resultMsg := string(responseString['value']);
var messageDiv = document.getElementById('view.login.message');
messageDiv.classList.remove('alert-danger'); Utils.ShowToast(resultMsg);
messageDiv.classList.add('alert-success');
end; if resultMsg.ToLower.StartsWith('success:') then
ShowNotification(string(responseString['value'])); FViewMain.ViewOrders('');
except
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,6 +143,7 @@ var ...@@ -129,6 +143,7 @@ var
data: TJSArray; data: TJSArray;
user: TJSObject; user: TJSObject;
begin begin
try
xdcResponse := await(XDataWebClient1.RawInvokeAsync('ILookupService.GetUsers', xdcResponse := await(XDataWebClient1.RawInvokeAsync('ILookupService.GetUsers',
[JS.toString(AuthService.TokenPayload.Properties['user_name'])])); [JS.toString(AuthService.TokenPayload.Properties['user_name'])]));
userList := TJSObject(xdcResponse.Result); userList := TJSObject(xdcResponse.Result);
...@@ -136,132 +151,14 @@ begin ...@@ -136,132 +151,14 @@ begin
user := TJSObject(data[0]); user := TJSObject(data[0]);
edtUsername.Text := string(user['username']); edtUsername.Text := string(user['username']);
edtFullName.Text := string(user['full_name']); edtFullName.Text := string(user['full_name']);
edtPhone.Text := string(user['phone_number']);
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>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
<meta content="width=device-width, initial-scale=1" name="viewport"/> <meta content="width=device-width, initial-scale=1" name="viewport"/>
<noscript>Your browser does not support JavaScript!</noscript> <noscript>Your browser does not support JavaScript!</noscript>
<link href="data:;base64,=" rel="icon"/> <link href="data:;base64,=" rel="icon"/>
<title>Web KG Orders</title>
<title>EM Systems webKGOrders App</title>
<link href="https://cdnjs.cloudflare.com/ajax/libs/flag-icon-css/2.3.1/css/flag-icon.min.css" rel="stylesheet"/> <link href="https://cdnjs.cloudflare.com/ajax/libs/flag-icon-css/2.3.1/css/flag-icon.min.css" rel="stylesheet"/>
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet"/> <link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet"/>
<link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.0/css/all.min.css" rel="stylesheet"/> <link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.0/css/all.min.css" rel="stylesheet"/>
<link crossorigin="anonymous" href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.1/dist/css/bootstrap.min.css" rel="stylesheet"/>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.1/dist/js/bootstrap.bundle.min.js" type="text/javascript"></script>
<script crossorigin="anonymous" integrity="sha256-eKhayi8LEQwp4NKxN+CfCh+3qOVUtJn3QNZ0TciWLP4=" src="https://code.jquery.com/jquery-3.7.1.js"></script>
<script src="$(ProjectName).js" type="text/javascript"></script>
<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 crossorigin="anonymous" integrity="sha256-eKhayi8LEQwp4NKxN+CfCh+3qOVUtJn3QNZ0TciWLP4=" src="https://code.jquery.com/jquery-3.7.1.js"></script>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.1/dist/js/bootstrap.bundle.min.js" type="text/javascript"></script>
<link crossorigin="anonymous" href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.1/dist/css/bootstrap.min.css" rel="stylesheet"/>
<script src="$(ProjectName).js" type="text/javascript"></script> <script src="$(ProjectName).js" type="text/javascript"></script>
</head>
<body> <body>
</body> </body>
<script type="text/javascript">rtl.run();</script> <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
......
...@@ -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