Commit 61959006 by emsys

Merge branch 'mac3' into cam3

parents df22fc95 74a2acc1
......@@ -200,44 +200,6 @@ object FViewAddCustomer: TFViewAddCustomer
WidthPercent = 100.000000000000000000
OnClick = btnEditClick
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
Left = 151
Top = 12
......@@ -393,7 +355,6 @@ object FViewAddCustomer: TFViewAddCustomer
SelLength = 0
SelStart = 0
WidthPercent = 100.000000000000000000
OnChange = memoAddressBlockChange
end
object btnAdd: TWebButton
Left = 19
......
<nav class="navbar navbar-expand navbar-light bg-light sticky-top" style="z-index: 100;">
<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">
<li class="nav-item pe-2">
<button id="btnadd" class="btn btn-primary btn-sm">Add</button>
......
......@@ -9,7 +9,7 @@ uses
WEBLib.Forms, WEBLib.Dialogs, WEBLib.Menus, WEBLib.ExtCtrls, WEBLib.StdCtrls,
WEBLib.JSON, Auth.Service, XData.Web.Client, WebLib.Storage,
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
TFViewAddCustomer = class(TWebForm)
......@@ -29,9 +29,6 @@ type
btnDelete: TWebButton;
btnClose: TWebButton;
btnEdit: TWebButton;
pnlMessage: TWebPanel;
lblMessage: TWebLabel;
btnCloseNotification: TWebButton;
XDataWebClient1: TXDataWebClient;
WebDataSource1: TWebDataSource;
XDataWebDataSet1: TXDataWebDataSet;
......@@ -83,7 +80,6 @@ type
XDataWebDataSet1REP_USER_ID: TStringField;
xdwdsUsersfull_name: TStringField;
procedure WebFormShow(Sender: TObject);
procedure btnCloseNotificationClick(Sender: TObject);
procedure btnSaveClick(Sender: TObject);
procedure btnCancelClick(Sender: TObject);
procedure xdwdsShipToAfterEdit(DataSet: TDataSet);
......@@ -92,7 +88,6 @@ type
procedure btnEditClick(Sender: TObject);
procedure wdbtcAddressesDblClickCell(Sender: TObject; ACol, ARow: Integer);
procedure btnClearClick(Sender: TObject);
procedure memoAddressBlockChange(Sender: TObject);
procedure AddressEditMode();
procedure edtShippingAddressChange(Sender: TObject);
procedure btnAddClick(Sender: TObject);
......@@ -105,9 +100,6 @@ type
procedure btnShipDeleteClick(Sender: TObject);
private
{ Private declarations }
procedure HideNotification();
procedure ShowNotification(Notification: string);
procedure ViewMode();
procedure EditMode();
[async] procedure GetCustomer();
......@@ -159,6 +151,7 @@ begin
newform.Caption := 'Select Customer and Order Type';
newForm.Popup := True;
newForm.Border := fbDialog;
newForm.Position := poScreenCenter;
// used to manage Back button handling to close subform
window.location.hash := 'subform';
......@@ -180,7 +173,7 @@ begin
Response := await(XDataWebClient1.RawInvokeAsync('ILookupService.DelShippingAddress',
[xdwdsShipTo.FieldByName('ship_id').AsString, customerID]));
notification := TJSObject(Response.Result);
ShowNotification(string(notification['status']));
ShowToast(string(notification['status']));
xdwdsShipTo.Close;
xdwdsShipTo.SetJSONData(notification['ADDRESS']);
xdwdsShipTo.Open;
......@@ -222,7 +215,7 @@ begin
[AddressJSON.ToString]));
notification := TJSObject(Response.Result);
ShowNotification(string(notification['status']));
ShowToast(string(notification['status']));
xdwdsShipTo.Close;
xdwdsShipTo.SetJSONData(notification['ADDRESS']);
xdwdsShipTo.Open;
......@@ -241,8 +234,16 @@ begin
document.getElementById('btn_confirm_cancel').innerText := 'No';
document.getElementById('btn_confirm_delete').innerText := 'Yes';
asm
var confirmationModal = new bootstrap.Modal(document.getElementById('confirmation_modal'), {
keyboard: false });
var modal = document.getElementById('confirmation_modal');
// 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();
end;
end;
......@@ -259,17 +260,12 @@ begin
FViewMain.ShowForm(TFViewCustomers)
end;
procedure TFViewAddCustomer.btnCloseNotificationClick(Sender: TObject);
// Closes a Notification.
begin
HideNotification();
end;
procedure TFViewAddCustomer.btnDeleteClick(Sender: TObject);
// Eventually will delete customers after a confirmation
// TODO implement deleting customers
begin
ShowMessage('Deleting Customers Is Not Yet Available');
ShowErrorModal('Deleting Customers Is Not Yet Available');
end;
procedure TFViewAddCustomer.btnEditClick(Sender: TObject);
......@@ -460,7 +456,7 @@ begin
edtCustomerID.Text := CustomerID;
ShowNotification(msg);
ShowToast(msg);
//TODO update the BILL_ADDRESS_BLOCK memo after saving.
......@@ -646,10 +642,10 @@ begin
else
mode := 'EDIT';
if notification = '' then
hideNotification()
else
showNotification(notification);
if notification <> '' then
begin
showToast(notification);
end;
EditMode();
......@@ -669,43 +665,6 @@ begin
EditMode();
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);
// Timer to returnto the customer page because it takes slightly too long to
......
......@@ -175,10 +175,10 @@ begin
Exit('');
Result := '';
asm
var Token = AToken.split('.');
if (Token.length = 3) {
Result = Token[1];
Result = atob(Result);
const parts = AToken.split('.');
if (parts.length === 3) { // <- strict compare
// JWTs use url-safe base64; convert before atob
Result = atob(parts[1].replace(/-/g,'+').replace(/_/g,'/'));
}
end;
end;
......
......@@ -19,7 +19,7 @@ type
FUnauthorizedAccessProc: TUnauthorizedAccessProc;
public
const clientVersion = '0.9.4';
const clientVersion = '0.9.6';
procedure InitApp(SuccessProc: TSuccessProc;
UnauthorizedAccessProc: TUnauthorizedAccessProc);
procedure SetClientConfig(Callback: TVersionCheckCallback);
......
......@@ -9,10 +9,11 @@ procedure ShowStatusMessage(const AMessage, AClass: string; const AElementId: st
procedure HideStatusMessage(const AElementId: string);
procedure ShowSpinner(SpinnerID: string);
procedure HideSpinner(SpinnerID: string);
procedure ShowErrorModal(const msg: string);
procedure ShowErrorModal(msg: string);
function CalculateAge(DateOfBirth: TDateTime): Integer;
function FormatPhoneNumber(PhoneNumber: string): string;
procedure ApplyReportTitle(CurrentReportType: string);
procedure ShowToast(const MessageText: string; const ToastType: string = 'success');
// function FormatDollarValue(ValueStr: string): string;
......@@ -84,9 +85,8 @@ begin
end;
// The $IFNDEF WIN32 was recommended by Holger to deal with any modal issues
procedure ShowErrorModal(const msg: string);
procedure ShowErrorModal(msg: string);
begin
{$IFNDEF WIN32}
asm
var modal = document.getElementById('main_errormodal');
var label = document.getElementById('main_lblmodal_body');
......@@ -110,13 +110,9 @@ begin
var bsModal = new bootstrap.Modal(modal, { keyboard: false });
bsModal.show();
end;
{$ENDIF}
end;
function CalculateAge(DateOfBirth: TDateTime): Integer;
var
Today, BirthDate: TJSDate;
......@@ -160,6 +156,71 @@ begin
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);
var
CrimeTitleElement: TJSHTMLElement;
......
object FAddOrder: TFAddOrder
Width = 871
Height = 477
Height = 428
OnShow = WebFormShow
object WebLabel1: TWebLabel
Left = 4
Top = 81
Top = 49
Width = 95
Height = 15
Caption = 'Search Customers'
......@@ -13,7 +13,7 @@ object FAddOrder: TFAddOrder
end
object WebLabel2: TWebLabel
Left = 135
Top = 81
Top = 49
Width = 113
Height = 15
Caption = 'Selected Customer ID'
......@@ -22,7 +22,7 @@ object FAddOrder: TFAddOrder
end
object WebLabel3: TWebLabel
Left = 283
Top = 81
Top = 49
Width = 134
Height = 15
Caption = 'Selected Customer Name'
......@@ -31,7 +31,7 @@ object FAddOrder: TFAddOrder
end
object edtSearch: TWebEdit
Left = 4
Top = 102
Top = 70
Width = 121
Height = 22
HeightPercent = 100.000000000000000000
......@@ -40,7 +40,7 @@ object FAddOrder: TFAddOrder
end
object edtID: TWebEdit
Left = 135
Top = 102
Top = 70
Width = 142
Height = 22
ChildOrder = 1
......@@ -50,7 +50,7 @@ object FAddOrder: TFAddOrder
end
object TMSFNCGrid1: TTMSFNCGrid
Left = 0
Top = 160
Top = 111
Width = 871
Height = 317
Align = alBottom
......@@ -204,10 +204,11 @@ object FAddOrder: TFAddOrder
ScrollMode = scmItemScrolling
DesignTimeSampleData = True
OnCellClick = TMSFNCGrid1CellClick
ExplicitTop = 112
end
object cbCorrugatedPlate: TWebCheckBox
Left = 4
Top = 49
Top = 17
Width = 113
Height = 22
Caption = 'Corrugated Plate'
......@@ -219,7 +220,7 @@ object FAddOrder: TFAddOrder
end
object cbWebPlate: TWebCheckBox
Left = 134
Top = 49
Top = 17
Width = 83
Height = 22
Caption = 'Web Plate'
......@@ -230,7 +231,7 @@ object FAddOrder: TFAddOrder
end
object btnCancel: TWebButton
Left = 542
Top = 101
Top = 69
Width = 96
Height = 25
Caption = 'Cancel'
......@@ -241,7 +242,7 @@ object FAddOrder: TFAddOrder
end
object btnConfirm: TWebButton
Left = 436
Top = 101
Top = 69
Width = 96
Height = 25
Caption = 'Select'
......@@ -252,7 +253,7 @@ object FAddOrder: TFAddOrder
end
object cbCuttingDie: TWebCheckBox
Left = 239
Top = 49
Top = 17
Width = 83
Height = 22
Caption = 'Cutting Die'
......@@ -261,30 +262,9 @@ object FAddOrder: TFAddOrder
WidthPercent = 100.000000000000000000
OnClick = cbCuttingDieClick
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
Left = 283
Top = 102
Top = 70
Width = 142
Height = 22
ChildOrder = 1
......
......@@ -11,7 +11,7 @@ uses
VCL.TMSFNCGridOptions, Vcl.Controls, VCL.TMSFNCCustomControl,
VCL.TMSFNCCustomScrollControl, VCL.TMSFNCGridData, VCL.TMSFNCCustomGrid,
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
TFAddOrder = class(TWebForm)
......@@ -30,7 +30,6 @@ type
xdwdsCustomersSHORT_NAME: TStringField;
wdsCustomers: TWebDataSource;
cbCuttingDie: TWebCheckBox;
edtNotification: TWebEdit;
xdwdsCustomersstaff_fields_invoice_to: TStringField;
xdwdsCustomersCUSTOMER_ID: TIntegerField;
WebLabel3: TWebLabel;
......@@ -67,25 +66,25 @@ begin
Close;
end;
procedure TFAddOrder.btnConfirmClick(Sender: TObject);
begin
confirm := true;
edtNotification.ElementHandle.style.setProperty('color', '#8B0000', 'important');
if ( ( not cbCorrugatedPlate.Checked ) and ( not cbWebPlate.Checked ) and ( not cbCuttingDie.Checked ) ) then
begin
edtNotification.Text := 'Please Select an Order Type';
ShowToast('Please Select an Order Type', 'danger');
confirm := false;
end;
if edtID.Text = '' then
begin
edtNotification.Text := 'Please Select a Customer';
ShowToast('Please Select a Customer', 'danger');
confirm := false;
end;
if ( ( not cbCorrugatedPlate.Checked ) and ( not cbWebPlate.Checked ) and ( not cbCuttingDie.Checked ) and (edtID.Text = '' )) then
begin
edtNotification.Text := 'Please Select an Order Type and a Customer';
ShowToast('Please Select an Order Type and a Customer', 'danger');
confirm := false;
end;
......@@ -95,6 +94,7 @@ begin
end;
end;
procedure TFAddOrder.WebFormShow(Sender: TObject);
begin
confirm := false;
......@@ -108,23 +108,27 @@ begin
cbCuttingDie.Checked := False;
end;
procedure TFAddOrder.cbCuttingDieClick(Sender: TObject);
begin
cbCorrugatedPlate.Checked := False;
cbWebPlate.Checked := False;
end;
procedure TFAddOrder.cbWebPlateClick(Sender: TObject);
begin
cbCorrugatedPlate.Checked := False;
cbCuttingDie.Checked := False;
end;
procedure TFAddOrder.edtSearchChange(Sender: TObject);
begin
ApplyFilter;
end;
[async] procedure TFAddOrder.getCustomers();
// retrieves customer list from server
var
......@@ -144,6 +148,7 @@ begin
PopulateGridManually;
end;
procedure TFAddOrder.PopulateGridManually;
// populates the grid with customers manually.
var
......@@ -191,6 +196,7 @@ begin
DBID := TMSFNCGrid1.Cells[0, ARow];
end;
procedure TFAddOrder.ApplyFilter;
// filters the grid based on search textbox contents.
var
......
......@@ -42,6 +42,7 @@ object FViewCustomers: TFViewCustomers
HeightPercent = 100.000000000000000000
Text = '500'
WidthPercent = 100.000000000000000000
OnChange = wcbPageSizeChange
ItemIndex = -1
Items.Strings = (
'100'
......
<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 -->
<div class="row mt-3 justify-content-center align-items-end">
<div class="col-auto">
......
......@@ -13,7 +13,7 @@ uses
WEBLib.Grids, VCL.TMSFNCTypes, VCL.TMSFNCUtils, VCL.TMSFNCGraphics,
VCL.TMSFNCGraphicsTypes, VCL.TMSFNCGridCell, VCL.TMSFNCGridOptions,
VCL.TMSFNCCustomControl, VCL.TMSFNCCustomScrollControl, VCL.TMSFNCGridData,
VCL.TMSFNCCustomGrid, VCL.TMSFNCGrid;
VCL.TMSFNCCustomGrid, VCL.TMSFNCGrid, VCL.Forms;
type
TFViewCustomers = class(TWebForm)
......@@ -36,13 +36,13 @@ type
procedure btnAddCustomerClick(Sender: TObject);
procedure wdbtcCustomersDblClickCell(Sender: TObject; ACol, ARow: Integer);
procedure edtFilterChange(Sender: TObject);
procedure wcbPageSizeChange(Sender: TObject);
private
{ Private declarations }
procedure GeneratePagination(TotalPages: Integer);
[async] procedure GetCustomers(searchOptions: string);
function GenerateSearchOptions(): string;
procedure HideNotification();
procedure ShowNotification(Notification: string);
procedure ShowSelectCustomerForm();
var
......@@ -75,6 +75,7 @@ begin
newform.Caption := 'Select Customer and Order Type';
newForm.Popup := True;
newForm.Border := fbDialog;
newForm.Position := poScreenCenter;
// used to manage Back button handling to close subform
window.location.hash := 'subform';
......@@ -173,34 +174,13 @@ begin
end;
procedure TFViewCustomers.ShowNotification(Notification: string);
var
splitNotification: TArray<string>;
procedure TFViewCustomers.wcbPageSizeChange(Sender: TObject);
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;
PageSize := StrToInt(wcbPageSize.Text);
getCustomers(GenerateSearchOptions());
end;
procedure TFViewCustomers.wdbtcCustomersDblClickCell(Sender: TObject; ACol,
ARow: Integer);
begin
......
......@@ -108,6 +108,7 @@ object FViewEditUser: TFViewEditUser
ElementID = 'edtconfirmpassword'
HeightPercent = 100.000000000000000000
WidthPercent = 100.000000000000000000
OnChange = edtConfirmPasswordChange
end
object edtEmail: TWebEdit
Left = 96
......@@ -128,6 +129,7 @@ object FViewEditUser: TFViewEditUser
ElementID = 'edtpassword'
HeightPercent = 100.000000000000000000
WidthPercent = 100.000000000000000000
OnChange = edtPasswordChange
end
object btnConfirm: TWebButton
Left = 96
......@@ -187,48 +189,6 @@ object FViewEditUser: TFViewEditUser
WidthPercent = 100.000000000000000000
OnClick = btnCancelClick
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
Left = 96
Top = 162
......
<div class="row">
<div class="col-12">
<div class="container mt-4">
<div class="row justify-content-center">
<div class="col-12 col-md-8">
<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>
<form class="form-inline">
<div class="row">
<div class="col-sm">
<label class= 'pe-2' style="font-weight: 700;font-size: 15px;"id="lblfullname">Full Name:</label>
<input id="edtfullname" class= "form-control input-sm" width='50%'/>
</div>
<div class="col-sm">
<label class= 'pe-2' style="font-weight: 700;font-size: 15px"id="lblusername">Username:</label>
<input id="edtusername" class="form-control input-sm" width='50%'>
</div>
</div>
</form>
<form class="form-inline">
<div class="row">
<div class="col-sm">
<label class='pe-2' style="font-weight: 700;font-size: 15px;"id="lblpassword">Password:</label>
<input id="edtpassword" class= "form-control input-sm" width='50%'/>
</div>
<div class="col-sm">
<label class= 'pe-2' style="font-weight: 700;font-size: 15px"id="lblconfirm">Confirm Password:</label>
<input class="form-control input-sm" id="edtconfirmpassword">
</div>
</div>
</form>
<form class="form-inline">
<div class="row">
<div class="col-sm">
<label class='pe-2' style="font-weight: 700;font-size: 15px;" id="lblemail">Email Address:</label>
<input id="edtemail" class= "form-control input-sm" width='50%'/>
</div>
<div class="col-sm">
<label class= 'pe-2' style="font-weight: 700;font-size: 15px"id="lblQB">Quickbook ID:</label>
<input class="form-control input-sm" id="edtQB">
</div>
</div>
</form>
<div class="row">
<div class="col-6">
<label class='pe-2' style="font-weight: 700;font-size: 15px;" id="lblrights">System Rights:</label>
<input id="edtrights" class= "form-control input-sm" width='50%'/>
</div>
</div>
<div class="row">
<div class="col-sm py-3">
<label class= 'pe-2' style="font-weight: 700;font-size: 15px"id="lblaccess">Access Type:</label>
<select class="custom-select-large" id="cbaccess" style="font-size: 1.00rem;"></select>
</div>
</div>
<div class="row">
<div class="col-sm">
<form class='form-inline'>
<div class="col-sm">
<div class="form-cells"><input type="checkbox" id="cbstatus"></div>
<div class="form-cells ps-1 py-2"><label style="font-weight: 700;font-size: 15px" id="lblactive">Active></label></div>
</div>
</form>
</div>
<div class="col-sm-12 py-2">
<button class="py-2" id="btnconfirm" style="font-weight: 700;font-size: 15px";>Confirm</button>
<button class="py-2" id="btncancel" style="font-weight: 700;font-size: 15px";>Cancel</button>
</div>
</div>
</div>
</div>
<div class="container">
<!-- Edit-User form -->
<div class="row">
<div class="col-lg-10 col-xl-8 mx-auto">
<form id="edituserform" class="row g-3 needs-validation" novalidate>
<div class="col-md-6">
<label id="lblfullname" for="edtfullname" class="form-label">Full&nbsp;Name</label>
<input id="edtfullname" class="form-control" required>
<div class="invalid-feedback">Full Name is required.</div>
</div>
<div class="col-md-6">
<label id="lblusername" for="edtusername" class="form-label">Username</label>
<input id="edtusername" class="form-control" required>
<div class="invalid-feedback">Username is required.</div>
</div>
<div class="col-md-6">
<label id="lblpassword" for="edtpassword" class="form-label">Password</label>
<input id="edtpassword" type="password" class="form-control" required>
<div class="invalid-feedback">Passwords must match.</div>
</div>
<div class="col-md-6">
<label id="lblconfirm" for="edtconfirmpassword" class="form-label">Confirm&nbsp;Password</label>
<input id="edtconfirmpassword" type="password" class="form-control" required disabled>
<div class="invalid-feedback">Passwords must match.</div>
</div>
<div class="col-md-6">
<label id="lblemail" for="edtemail" class="form-label">Email&nbsp;Address</label>
<input id="edtemail" type="email" class="form-control" required>
<div class="invalid-feedback">Valid email is required.</div>
</div>
<div class="col-md-6">
<label id="lblQB" for="edtQB" class="form-label">QuickBooks&nbsp;ID</label>
<input id="edtQB" class="form-control">
</div>
<div class="col-md-6">
<label id="lblrights" for="edtrights" class="form-label">System&nbsp;Rights</label>
<input id="edtrights" class="form-control">
</div>
<div class="col-md-6">
<label id="lblaccess" for="cbaccess" class="form-label">Access&nbsp;Type</label>
<select id="cbaccess" class="form-select" required>
<option selected disabled value="">Choose...</option>
<option value="ALL">All</option>
<option value="LIMITED">Limited</option>
</select>
<div class="invalid-feedback">Please select an access type.</div>
</div>
<div class="col-md-6">
<div class="form-check pt-2">
<input id="cbstatus" class="form-check-input" type="checkbox">
<label id="lblactive" for="cbstatus" class="form-check-label">Active</label>
</div>
</div>
<div class="d-flex gap-2 mt-4">
<button id="btnconfirm" type="button" class="btn btn-primary flex-grow-1">
Confirm
</button>
<button id="btncancel" type="button" class="btn btn-outline-secondary flex-grow-1">
Cancel
</button>
</div>
</form>
</div>
</div>
</div>
<!-- Confirmation modal -->
<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">
......@@ -95,3 +94,4 @@
</div>
</div>
</div>
......@@ -26,10 +26,6 @@ type
XDataWebClient1: TXDataWebClient;
btnCancel: TWebButton;
WebTimer1: TWebTimer;
btnConfirmChanges: TWebButton;
pnlMessage: TWebPanel;
lblMessage: TWebLabel;
btnCloseNotification: TWebButton;
lblactive: TWebLabel;
cbStatus: TWebCheckBox;
lblRights: TWebLabel;
......@@ -42,8 +38,8 @@ type
procedure btnConfirmClick(Sender: TObject);
procedure btnCancelClick(Sender: TObject);
procedure WebTimer1Timer(Sender: TObject);
procedure btnConfirmChangesClick(Sender: TObject);
procedure btnCloseNotificationClick(Sender: TObject);
procedure edtPasswordChange(Sender: TObject);
procedure edtConfirmPasswordChange(Sender: TObject);
private
{ Private declarations }
FMessage: string;
......@@ -59,8 +55,7 @@ type
QB: string;
[async] procedure EditUser();
[async] function AddUser(): string;
procedure HideNotification();
procedure ShowNotification(notification: string);
procedure ValidatePasswords;
public
{ Public declarations }
Info: string;
......@@ -84,24 +79,10 @@ Utils;
procedure TFViewEditUser.btnCancelClick(Sender: TObject);
// Cancels the edit or addition
begin
Info := 'Failure:Changes discarded!';
Info := 'Failure: Changes discarded!';
FViewMain.ShowUserForm(Info);
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;
// Sends UserInfo over to the server so it can be added to the database
......@@ -131,20 +112,6 @@ begin
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();
// Sends EditOptions over to the server so the given user can be editted
var
......@@ -172,6 +139,16 @@ begin
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,
Access, Rights, Perspective, QB: string): TWebForm;
// Autofills known information about a user on create
......@@ -199,9 +176,7 @@ procedure TFViewEditUser.WebFormCreate(Sender: TObject);
// Autofills known information about a user on create
begin
if FMessage <> '' then
ShowNotification(FMessage)
else
HideNotification;
ShowToast(FMessage);
edtUsername.Text := Username;
edtFullName.Text := FullName;
if Mode = 'Edit' then
......@@ -226,132 +201,79 @@ begin
FViewMain.ShowUserForm(Info);
end
else
showNotification(Info);
showToast(Info);
console.log('Info at Timer:' + Info);
end;
procedure TFViewEditUser.btnConfirmClick(Sender: TObject);
// Confirms the edit or addition
var
checkString: string;
charIndex: integer;
phoneNum: string;
FormEl: TJSHTMLFormElement;
begin
{ checkString := edtFullName.Text + edtUsername.Text + edtPassword.Text
+ edtConfirmPassword.Text + edtPhoneNumber.Text + edtEmail.Text;
if string(edtFullName.Text).IsEmpty then
begin
ShowNotification('Full Name field is blank!');
exit;
end;
if string(edtUsername.Text).IsEmpty then
begin
ShowNotification('Username field is blank!');
exit;
end;
if string(edtPassword.Text).IsEmpty then
begin
ShowNotification('Password field is blank!');
exit;
end;
if string(edtConfirmPassword.Text).IsEmpty then
begin
ShowNotification('Please confirm your password!');
exit;
end;
FormEl := TJSHTMLFormElement(document.getElementById('edituserform'));
if string(edtPhoneNumber.Text).IsEmpty then
if not FormEl.checkValidity then
begin
ShowNotification('Phone Number field is blank!');
exit;
FormEl.classList.add('was-validated');
Exit;
end;
if string(edtEmail.Text).IsEmpty then
begin
ShowNotification('Email field is blank!');
exit;
end;
Utils.ShowSpinner('spinner');
if checkString.Contains('&') then
begin
ShowNotification('No fields may contain "&&"!');
exit;
end;
if Mode = 'Edit' then
EditUser
else
AddUser;
if string(edtEmail.Text).Contains('@') = false then
begin
ShowNotification('Please enter a valid email address');
exit;
end;
WebTimer1.Enabled := True;
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
begin
ShowNotification('Please enter a valid phone number');
exit;
end;
Pwd := PwdInput.value.Trim;
Confirm := ConfirmInput.value.Trim;
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
ShowNotification('Please enter a valid phone number');
exit;
end;
phoneNum := phoneNum.Replace('(', '');
phoneNum := phoneNum.Replace(')', '');
phoneNum := phoneNum.Replace('-', '');
phoneNum := phoneNum.Replace(' ', '');
if(length(phoneNum) <> 10) then
ConfirmInput.disabled := True;
ConfirmInput.value := '';
ConfirmInput.setCustomValidity('');
ConfirmInput.classList.remove('is-invalid');
ConfirmInput.classList.remove('is-valid');
end
else
begin
ShowNotification('Please enter a valid phone number');
exit;
end;
ConfirmInput.disabled := False;
for CharIndex := 1 to Length(phoneNum) do
begin
if not (phoneNum[CharIndex] in ['0' .. '9']) then
// Live match check
if Confirm = '' then
begin
ConfirmInput.setCustomValidity('');
ConfirmInput.classList.remove('is-invalid');
ConfirmInput.classList.remove('is-valid');
end
else if Confirm = Pwd then
begin
ConfirmInput.setCustomValidity('');
ConfirmInput.classList.add('is-valid');
ConfirmInput.classList.remove('is-invalid');
end
else
begin
console.log('here');
ShowNotification('Please enter a valid phone number');
exit;
ConfirmInput.setCustomValidity('Passwords must match');
ConfirmInput.classList.add('is-invalid');
ConfirmInput.classList.remove('is-valid');
end;
end;
if edtPassword.Text <> edtConfirmPassword.Text then
begin
ShowNotification('Passwords must match!');
exit;
end;
if (length(edtPassword.Text) > 20) or (length(edtPassword.Text) < 6) then
begin
ShowNotification('Passwords must be between 6-20 characters!');
exit;
end;
}
asm
var modal = document.getElementById('confirmation_modal');
// ensure the modal is directly under <body>
if (modal && modal.parentNode !== document.body) {
document.body.appendChild(modal);
}
var bsModal = new bootstrap.Modal(modal, {
keyboard: false
});
bsModal.show();
end;
end;
end.
......@@ -50,7 +50,6 @@ object FViewItems: TFViewItems
ChildOrder = 7
ElementID = 'btnadd'
ElementFont = efCSS
Enabled = False
HeightStyle = ssAuto
HeightPercent = 100.000000000000000000
WidthPercent = 100.000000000000000000
......@@ -97,51 +96,6 @@ object FViewItems: TFViewItems
HeightPercent = 100.000000000000000000
WidthPercent = 100.000000000000000000
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
Left = 565
Top = 228
......
<nav class="navbar navbar-expand navbar-light bg-light sticky-top" style="z-index: 100;">
<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">
<li class="nav-item pe-2">
<button id="btnadd" class="btn btn-primary btn-sm">Add</button>
......
......@@ -24,9 +24,6 @@ type
edtName: TWebEdit;
edtDescription: TWebEdit;
cbStatus: TWebCheckBox;
pnlMessage: TWebPanel;
lblMessage: TWebLabel;
btnCloseNotification: TWebButton;
btnSave: TWebButton;
btnCancel: TWebButton;
btnDelete: TWebButton;
......@@ -34,7 +31,6 @@ type
procedure WebFormCreate(Sender: TObject);
procedure btnAddClick(Sender: TObject);
procedure wcbPageSizeChange(Sender: TObject);
procedure btnCloseNotificationClick(Sender: TObject);
procedure btnEditClick(Sender: TObject);
procedure btnSaveClick(Sender: TObject);
procedure btnDeleteClick(Sender: TObject);
......@@ -45,8 +41,6 @@ type
procedure ClearTable();
procedure GeneratePagination(TotalPages: Integer);
function GenerateSearchOptions(): string;
procedure HideNotification();
procedure ShowNotification(Notification: string);
procedure ViewMode();
procedure EditMode();
[async] procedure GetItems(searchOptions: string);
......@@ -412,6 +406,7 @@ begin
newform.Caption := 'Select Customer and Order Type';
newForm.Popup := True;
newForm.position:= poScreenCenter;
newForm.Border := fbDialog;
// used to manage Back button handling to close subform
......@@ -427,64 +422,28 @@ end;
procedure TFViewItems.btnCancelClick(Sender: TObject);
begin
ShowMessage('Editting Items is not yet implemented');
ShowToast('Editing items is not yet implemented.', 'info');
end;
procedure TFViewItems.btnCloseNotificationClick(Sender: TObject);
begin
HideNotification();
end;
procedure TFViewItems.btnDeleteClick(Sender: TObject);
begin
ShowMessage('Deleting Items is no yet implemented');
ShowToast('Deleting items is no yet implemented.', 'info');
end;
procedure TFViewItems.btnEditClick(Sender: TObject);
begin
ShowMessage('Editting Items is not yet implemented');
ShowToast('Editing items is not yet implemented.', 'info');
//EditMode();
end;
procedure TFViewItems.btnSaveClick(Sender: TObject);
//TODO implement editting items
begin
ShowMessage('Editting Items is not yet implemented');
ShowToast('Editing items is not yet implemented.', 'info');
//ViewMode();
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);
// adds an item to the database.
......
......@@ -57,7 +57,7 @@ object FViewMain: TFViewMain
end
object lblAppTitle: TWebLabel
Left = 57
Top = 31
Top = 33
Width = 75
Height = 14
Caption = 'Koehler-Gibson'
......
......@@ -47,7 +47,22 @@
</div>
</div>
</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="row">
<div id="main.webpanel" class="col-12"></div>
......@@ -86,6 +101,25 @@
</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
System.SysUtils, System.Classes, JS, Web, WEBLib.Graphics, WEBLib.Controls,
WEBLib.Forms, WEBLib.Dialogs, WEBLib.ExtCtrls, Vcl.Controls, Vcl.StdCtrls,
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
TFViewMain = class(TWebForm)
......@@ -46,6 +46,8 @@ type
//procedure EditUser( AParam, BParam, CParam, DParam, EParam: string);
function GetUserInfo: string;
procedure setActive(page: string);
procedure ConfirmLogout;
procedure OnConfirmLogout(Event: TJSEvent);
public
{ Public declarations }
class procedure Display(LogoutProc: TLogoutProc);
......@@ -101,7 +103,6 @@ begin
ShowForm(TFViewOrders);
lblAppTitle.Caption := 'Koehler-Gibson Orders';
lblVersion.Caption := 'v' + DMConnection.clientVersion;
setActive('Orders');
end;
......@@ -117,7 +118,7 @@ begin
setActive('Customers');
end
else
ShowMessage('Please Save or Cancel your changes');
ShowErrorModal('Please Save or Cancel your changes');
end;
procedure TFViewMain.lblHomeClick(Sender: TObject);
......@@ -129,7 +130,7 @@ begin
//setActive('Home');
end
else
ShowMessage('Please Save or Cancel your changes');
ShowErrorModal('Please Save or Cancel your changes');
end;
procedure TFViewMain.lblordersClick(Sender: TObject);
......@@ -142,7 +143,7 @@ begin
setActive('Orders');
end
else
ShowMessage('Please Save or Cancel your changes');
ShowErrorModal('Please Save or Cancel your changes');
end;
procedure TFViewMain.lblQuickbooksClick(Sender: TObject);
......@@ -154,7 +155,7 @@ begin
setActive('QuickBooks');
end
else
ShowMessage('Please Save or Cancel your changes');
ShowErrorModal('Please Save or Cancel your changes');
end;
procedure TFViewMain.lblUsersClick(Sender: TObject);
......@@ -165,7 +166,7 @@ begin
lblAppTitle.Caption := 'Koehler-Gibson Users';
end
else
ShowMessage('Please Save or Cancel your changes');
ShowErrorModal('Please Save or Cancel your changes');
end;
procedure TFViewMain.lblItemsListClick(Sender: TObject);
......@@ -177,7 +178,7 @@ begin
setActive('Items');
end
else
ShowMessage('Please Save or Cancel your changes');
ShowErrorModal('Please Save or Cancel your changes');
end;
procedure TFViewMain.setActive(page: string);
......@@ -200,15 +201,55 @@ end;
procedure TFViewMain.mnuLogoutClick(Sender: TObject);
begin
FLogoutProc;
ConfirmLogout;
end;
procedure TFViewMain.wllblLogoutClick(Sender: TObject);
begin
FLogoutProc;
ConfirmLogout;
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);
begin
......
......@@ -99,41 +99,6 @@ object FOrderEntryCorrugated: TFOrderEntryCorrugated
Visible = False
WidthPercent = 100.000000000000000000
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
Left = 22
Top = 218
......@@ -385,6 +350,7 @@ object FOrderEntryCorrugated: TFOrderEntryCorrugated
HeightPercent = 100.000000000000000000
HideSelection = False
WidthPercent = 100.000000000000000000
OnChange = edtJobNameChange
DataField = 'staff_fields_job_name'
DataSource = WebDataSource1
end
......@@ -1190,7 +1156,7 @@ object FOrderEntryCorrugated: TFOrderEntryCorrugated
HeightPercent = 100.000000000000000000
WidthPercent = 100.000000000000000000
end
object btn_confirm_delete: TWebButton
object btn_modal_confirm: TWebButton
Left = 1094
Top = 414
Width = 96
......@@ -1200,7 +1166,7 @@ object FOrderEntryCorrugated: TFOrderEntryCorrugated
ElementID = 'btn_confirm_delete'
HeightPercent = 100.000000000000000000
WidthPercent = 100.000000000000000000
OnClick = btn_confirm_deleteClick
OnClick = btn_modal_confirmClick
end
object btnEdit: TWebButton
Left = 1202
......
<nav class="navbar navbar-expand navbar-light bg-light border-light sticky-top" style="z-index: 100;">
<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">
<li class="nav-item pe-2">
<button id="btnadd" class="btn btn-primary btn-sm">Add</button>
......@@ -220,7 +215,7 @@
<hr class="custom-hr">
<div class="row">
<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 id="edtloose" class="form-control input-sm" style="width: 150px"/>
</div>
......@@ -367,23 +362,18 @@
<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">
<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" id="modal_body">
<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">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal" id= 'btn_confirm_cancel'>Cancel</button>
<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>
<style>
.modal-backdrop {
opacity: 0 !important;
}
</style>
......@@ -9,13 +9,10 @@ uses
WEBLib.Forms, WEBLib.Dialogs, WEBLib.Menus, WEBLib.ExtCtrls, WEBLib.StdCtrls,
WEBLib.JSON, Auth.Service, XData.Web.Client, WebLib.Storage,
ConnectionModule, App.Types, Vcl.StdCtrls, Vcl.Controls, WEBLib.DBCtrls,
Data.DB, XData.Web.JsonDataset, XData.Web.Dataset, WEBLib.DB;
Data.DB, XData.Web.JsonDataset, XData.Web.Dataset, WEBLib.DB, VCL.Forms;
type
TFOrderEntryCorrugated = class(TWebForm)
pnlMessage: TWebPanel;
lblMessage: TWebLabel;
btnCloseNotification: TWebButton;
dtpOrderDate: TWebDateTimePicker;
dtpProofDate: TWebDateTimePicker;
dtpShipDate: TWebDateTimePicker;
......@@ -198,14 +195,12 @@ type
btnDelete: TWebButton;
btnClose: TWebButton;
edtOrderNum: TWebEdit;
btn_confirm_delete: TWebButton;
btn_modal_confirm: TWebButton;
tmrReturn: TWebTimer;
btnEdit: TWebButton;
btnAdd: TWebButton;
WebButton2: TWebButton;
procedure WebFormCreate(Sender: TObject);
procedure HideNotification();
procedure ShowNotification(Notification: string);
procedure WebFormShow(Sender: TObject);
[async] procedure getOrder(Order_ID: string);
[async] procedure getCustomer(customerID: string);
......@@ -221,9 +216,8 @@ type
procedure btnCopyClick(Sender: TObject);
procedure sendOrderToServer();
procedure btnCloseClick(Sender: TObject);
procedure btnCloseNotificationClick(Sender: TObject);
procedure btnDeleteClick(Sender: TObject);
procedure btn_confirm_deleteClick(Sender: TObject);
procedure btn_modal_confirmClick(Sender: TObject);
procedure tmrReturnTimer(Sender: TObject);
function VerifyOrder(): boolean;
procedure XDataWebDataSet1AfterEdit(DataSet: TDataSet);
......@@ -242,7 +236,9 @@ type
procedure WebButton2Click(Sender: TObject);
procedure ShowAddAddressForm();
[async] procedure SendAddressToServer(AddressJSON: TJSONObject);
procedure edtJobNameChange(Sender: TObject);
private
FModalAction: string;
FAgencyCode: string;
FCurrentReportType: string;
FSelectProc: TSelectProc;
......@@ -251,6 +247,7 @@ type
mode: string;
changed: boolean;
notification: string;
procedure RemoveColorRow(Sender: TObject);
//FJSONProc1: TJSONProc1;
public
class function CreateForm(AElementID, orderInfo, customerInfo, mode, info: string): TWebForm;
......@@ -266,6 +263,7 @@ implementation
uses
View.Home, View.Main, View.AddOrder, View.AddAddress, Utils;
procedure TFOrderEntryCorrugated.sendOrderToServer();
// This can be improved. I was struggling to get the checkboxes to work with
// The dataset at first, but if you just change the fields in the database to be
......@@ -383,7 +381,11 @@ begin
if Field is TStringField then
begin
if Field.AsString = '' then
orderJSON.AddPair(Field.FieldName, '')
begin
orderJSON.AddPair(Field.FieldName, '');
console.log(Field.FieldName);
console.log(Field.AsString);
end
else
orderJSON.AddPair(Field.FieldName, Field.AsString); // Add all other fields
end
......@@ -404,9 +406,9 @@ begin
orderJSON.AddPair('ORDER_ID', orderID);
AddCorrugatedOrder(orderJSON);
end;
procedure TFOrderEntryCorrugated.btnSaveClick(Sender: TObject);
// Converts all the information on the page into a JSON to then send to the server
begin
......@@ -432,7 +434,6 @@ begin
else
input.classList.remove('is-invalid');
input := TJSHTMLInputElement(document.getElementById('edtaccountcompanyname'));
if edtCompanyAccountName.Text = '' then
begin
......@@ -472,6 +473,7 @@ begin
input.classList.remove('is-invalid');
end;
procedure TFOrderEntryCorrugated.btnCopyClick(Sender: TObject);
begin
mode := 'ADD';
......@@ -485,67 +487,72 @@ begin
dtpApprovedDate.Date := 0;
edtOrderNum.Text := '';
EditMode();
ShowNotification('Success:Order Successfully Copied');
ShowToast('Success: Order Successfully Copied');
window.scrollTo(0, 0);
end;
procedure TFOrderEntryCorrugated.btnDeleteClick(Sender: TObject);
begin
FModalAction := 'delete';
document.getElementById('modal_body').innerHTML := 'Are you sure you want to delete this order?';
document.getElementById('btn_confirm_cancel').innerText := 'Cancel';
document.getElementById('btn_confirm_delete').innerText := 'Delete';
asm
var confirmationModal = new bootstrap.Modal(document.getElementById('confirmation_modal'), {
keyboard: false });
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;
procedure TFOrderEntryCorrugated.btnEditClick(Sender: TObject);
begin
EditMode();
end;
procedure TFOrderEntryCorrugated.btnPDFClick(Sender: TObject);
begin
if mode = 'EDIT' then
GenerateReportPDF
else
showNotification('Failure:Cannot Generate PDF when Adding an Order');
ShowToast('Failure: Cannot Generate PDF when Adding an Order');
end;
procedure TFOrderEntryCorrugated.btn_confirm_deleteClick(Sender: TObject);
procedure TFOrderEntryCorrugated.btn_modal_confirmClick(Sender: TObject);
begin
if document.getElementById('btn_confirm_delete').innerText = 'Yes' then
if FModalAction = 'cancel' then
begin
FViewMain.change := false;
if OrderID <> '' then
begin
FViewMain.ViewOrderEntryCorrugated(OrderID, '', 'EDIT', 'Failure:Changes Discarded');
end
FViewMain.ViewOrderEntryCorrugated(OrderID, '', 'EDIT', 'Failure: Changes Discarded')
else
FViewMain.ViewOrders('');
end
else
else if FModalAction = 'delete' then
begin
Utils.ShowSpinner('spinner');
asm
var modal = document.getElementById('confirmation_modal');
// ensure the modal lives directly under <body>
if (modal && modal.parentNode !== document.body) {
document.body.appendChild(modal);
}
var bsModal = new bootstrap.Modal(modal, {
keyboard: false
});
var bsModal = new bootstrap.Modal(modal, { keyboard: false });
bsModal.hide();
end;
delOrder();
DelOrder();
tmrReturn.Enabled := true;
end;
end;
[async] procedure TFOrderEntryCorrugated.GenerateReportPDF;
// sends the search to the server which then sends back a pdf of the results
var
......@@ -575,6 +582,7 @@ var
Response: TXDataClientResponse;
jsObj: TJSObject;
begin
console.log(orderJSON);
Response := await(XDataWebClient1.RawInvokeAsync('ILookupService.AddCorrugatedOrder',
[orderJSON.ToString]));
jsObj := JS.TJSObject(Response.Result);
......@@ -582,11 +590,10 @@ begin
OrderID := String(jsObj.Properties['OrderID']);
edtOrderNum.Text := OrderID;
mode := 'EDIT';
console.log(jsObj);
ShowNotification(string(jsObj.Properties['status']));
ShowToast(string(jsObj.Properties['status']));
end;
procedure TFOrderEntryCorrugated.DelOrder();
var
Response: TXDataClientResponse;
......@@ -620,70 +627,94 @@ begin
);
end;
procedure TFOrderEntryCorrugated.addColorRow(num: string; Color: string; LPI: string; Size: string);
// Java script code to add a row of colors when a button is clicked
// all variables are information to be placed in the boxes when loading an order.
// TODO: convert to Delphi
procedure TFOrderEntryCorrugated.addColorRow(num, color, LPI, size: string);
var
container, newRow, col, labelEl, inputEl, removeCol: TJSHTMLElement;
removeBtn: TWebButton;
values: array[0..3] of string;
labels: array[0..3] of string;
i: Integer;
begin
asm
const container = document.getElementById('additionalFields');
// Create a new row for the new fields
const newRow = document.createElement('div');
newRow.className = 'row mb-2';
const labels = ['#', 'Color', 'LPI', 'Size'];
const values = [num, Color, LPI, Size];
labels.forEach((label, index) => {
const col = document.createElement('div');
col.className = 'col-sm';
const labelElement = document.createElement('label');
labelElement.className = 'pe-2';
labelElement.style.fontWeight = '700';
labelElement.style.fontSize = '15px';
labelElement.textContent = label + ':';
const inputElement = document.createElement('input');
inputElement.className = 'form-control input-sm';
inputElement.style.width = '100%';
inputElement.id = 'input-' + container.childElementCount + '-' + index; // Unique ID based on count
inputElement.value = values[index]; // Set the value based on the parameter
col.appendChild(labelElement);
col.appendChild(inputElement);
newRow.appendChild(col);
});
const removeButtonCol = document.createElement('div');
removeButtonCol.className = 'col-auto d-flex align-items-center mt-3';
const removeButton = document.createElement('button');
removeButton.className = 'btn btn-danger btn-sm mt-1';
removeButton.textContent = 'Remove';
removeButton.addEventListener('click', function() {
container.removeChild(newRow);
});
removeButtonCol.appendChild(removeButton);
newRow.appendChild(removeButtonCol);
container.appendChild(newRow);
end;
container := TJSHTMLElement(document.getElementById('additionalFields'));
// Create the new row container
newRow := TJSHTMLElement(document.createElement('div'));
newRow.className := 'row mb-2';
labels[0] := '#'; values[0] := num;
labels[1] := 'Color'; values[1] := color;
labels[2] := 'LPI'; values[2] := LPI;
labels[3] := 'Size'; values[3] := size;
for i := 0 to 3 do
begin
col := TJSHTMLElement(document.createElement('div'));
col.className := 'col-sm';
labelEl := TJSHTMLElement(document.createElement('label'));
labelEl.className := 'pe-2';
labelEl.style.setProperty('font-weight', '700');
labelEl.style.setProperty('font-size', '15px');
labelEl.textContent := labels[i] + ':';
inputEl := TJSHTMLElement(document.createElement('input'));
inputEl.className := 'form-control input-sm';
inputEl.setAttribute('style', 'width: 100%');
inputEl.setAttribute('value', values[i]);
inputEl.setAttribute('id', 'input-' + IntToStr(container.childElementCount) + '-' + IntToStr(i));
col.appendChild(labelEl);
col.appendChild(inputEl);
newRow.appendChild(col);
end;
// Add remove button
removeCol := TJSHTMLElement(document.createElement('div'));
removeCol.className := 'col-auto d-flex align-items-end pb-1';
removeBtn := TWebButton.Create(Self);
removeBtn.Caption := 'Remove';
removeBtn.ElementClassName := 'btn btn-danger btn-sm mt-1';
removeBtn.ParentElement := removeCol;
removeBtn.ElementHandle.style.setProperty('height', '30px');
removeBtn.OnClick := RemoveColorRow;
newRow.appendChild(removeCol);
container.appendChild(newRow);
end;
procedure TFOrderEntryCorrugated.RemoveColorRow(Sender: TObject);
var
btn: TWebButton;
rowElement: TJSHTMLElement;
begin
EditMode();
btn := TWebButton(Sender);
if Assigned(btn.ElementHandle) and Assigned(btn.ElementHandle.parentElement) then
begin
// Assuming button is inside a <div> inside the row
rowElement := TJSHTMLElement(btn.ElementHandle.parentElement.parentElement);
if Assigned(rowElement) then
rowElement.remove;
end;
end;
procedure TFOrderEntryCorrugated.btnAddColorClick(Sender: TObject);
begin
EditMode();
addColorRow('','','','');
end;
procedure TFOrderEntryCorrugated.WebButton2Click(Sender: TObject);
begin
ShowAddAddressForm();
end;
procedure TFOrderEntryCorrugated.SendAddressToServer(AddressJSON: TJSONObject);
var
Response: TXDataClientResponse;
......@@ -693,12 +724,13 @@ begin
[AddressJSON.ToString]));
notification := TJSObject(Response.Result);
ShowNotification(string(notification['status']));
ShowToast(string(notification['status']));
xdwdsShipTo.Close;
xdwdsShipTo.SetJSONData(notification['ADDRESS']);
xdwdsShipTo.Open;
end;
procedure TFOrderEntryCorrugated.ShowAddAddressForm;
// displays the search pop-up that allows the user to filter the order list
var
......@@ -710,6 +742,7 @@ begin
newform.Caption := 'Input Shipping Information';
newForm.Popup := True;
newForm.Position := poScreenCenter;
newForm.Border := fbDialog;
// used to manage Back button handling to close subform
......@@ -755,6 +788,7 @@ begin
newform.Caption := 'Select Customer and Order Type';
newForm.Popup := True;
newForm.Position := poScreenCenter;
newForm.Border := fbDialog;
// used to manage Back button handling to close subform
......@@ -783,28 +817,31 @@ begin
);
end;
procedure TFOrderEntryCorrugated.btnCancelClick(Sender: TObject);
begin
console.log('click');
FModalAction := 'cancel';
document.getElementById('modal_body').innerHTML := 'Are you sure you want to cancel all changes?';
document.getElementById('btn_confirm_cancel').innerText := 'No';
document.getElementById('btn_confirm_delete').innerText := 'Yes';
asm
var confirmationModal = new bootstrap.Modal(document.getElementById('confirmation_modal'), {
keyboard: false });
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;
procedure TFOrderEntryCorrugated.btnCloseClick(Sender: TObject);
begin
FViewMain.ViewOrders('');
end;
procedure TFOrderEntryCorrugated.btnCloseNotificationClick(Sender: TObject);
begin
hideNotification();
end;
procedure TFOrderEntryCorrugated.WebFormCreate(Sender: TObject);
begin
......@@ -815,6 +852,7 @@ begin
end;
end;
procedure TFOrderEntryCorrugated.getOrder(Order_ID: string);
// retrieves an order from the server then loads the info into the page
var
......@@ -971,6 +1009,7 @@ begin
end;
end;
procedure TFOrderEntryCorrugated.getCustomer(customerID: string);
// gets a customer from the database then loads the appropiate fields
var
......@@ -985,8 +1024,7 @@ begin
XDataWebDataSet1.Close;
XDataWebDataSet1.SetJsonData(customer);
XDataWebDataSet1.Open;
XDataWebDataSet1.Edit;
xdwdsShipTo.Close;
xdwdsShipTo.SetJSONData(customer['ADDRESS_LIST']);
......@@ -1010,6 +1048,7 @@ begin
end;
end;
procedure TFOrderEntryCorrugated.WebFormShow(Sender: TObject);
begin
if mode <> 'ADD' then
......@@ -1023,66 +1062,30 @@ begin
EditMode();
end;
edtOrderNum.Text := OrderID;
if notification = '' then
begin
HideNotification;
end
else
if notification <> '' then
begin
ShowNotification(notification);
ShowToast(notification);
end;
end;
procedure TFOrderEntryCorrugated.XDataWebDataSet1AfterEdit(DataSet: TDataSet);
begin
EditMode();
end;
procedure TFOrderEntryCorrugated.xdwdsQBItemAfterEdit(DataSet: TDataSet);
begin
EditMode();
end;
procedure TFOrderEntryCorrugated.xdwdsShipToAfterEdit(DataSet: TDataSet);
begin
EditMode();
end;
procedure TFOrderEntryCorrugated.HideNotification;
begin
pnlMessage.ElementHandle.hidden := True;
end;
procedure TFOrderEntryCorrugated.ShowNotification(Notification: string);
var
splitNotification: TArray<string>;
begin
console.log(notification);
if Notification <> '' then
begin
splitNotification := Notification.Split([':']);
if(splitNotification[0] = 'Success') then
begin
asm
var messageDiv = document.getElementById('view.login.message');
messageDiv.classList.remove('alert-danger');
messageDiv.classList.add('alert-success');
end;
end
else
begin
asm
var messageDiv = document.getElementById('view.login.message');
messageDiv.classList.remove('alert-success');
messageDiv.classList.add('alert-danger');
end;
end;
console.log(splitNotification[1]) ;
lblMessage.Caption := splitNotification[1];
pnlMessage.ElementHandle.hidden := False;
end;
end;
procedure TFOrderEntryCorrugated.tmrReturnTimer(Sender: TObject);
begin
......@@ -1091,12 +1094,14 @@ begin
FViewMain.ViewOrders('Success: Order Successfully Deleted');
end;
procedure TFOrderEntryCorrugated.tmrScrollTopTimer(Sender: TObject);
begin
tmrScrollTop.Enabled := False;
window.scrollTo(0, 0);
end;
procedure TFOrderEntryCorrugated.EditMode();
begin
FViewMain.change := true;
......@@ -1110,6 +1115,12 @@ begin
btnAdd.Enabled := false;
end;
procedure TFOrderEntryCorrugated.edtJobNameChange(Sender: TObject);
begin
EditMode();
console.log('onChange');
end;
procedure TFOrderEntryCorrugated.dtpApprovedDateChange(Sender: TObject);
begin
EditMode();
......
......@@ -228,43 +228,6 @@ object FOrderEntryCuttingDie: TFOrderEntryCuttingDie
WidthPercent = 100.000000000000000000
OnClick = btnCancelClick
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
Left = 26
Top = 92
......@@ -400,14 +363,15 @@ object FOrderEntryCuttingDie: TFOrderEntryCuttingDie
end
object WebDataSource1: TWebDataSource
DataSet = XDataWebDataSet1
Left = 22
Top = 10
OnDataChange = WebDataSource1DataChange
Left = 318
Top = 262
end
object XDataWebDataSet1: TXDataWebDataSet
AfterEdit = XDataWebDataSet1AfterEdit
Connection = DMConnection.ApiConnection
Left = 90
Top = 20
Left = 318
Top = 208
object XDataWebDataSet1COMPANY_ID: TIntegerField
FieldName = 'COMPANY_ID'
end
......@@ -471,8 +435,8 @@ object FOrderEntryCuttingDie: TFOrderEntryCuttingDie
end
object XDataWebClient1: TXDataWebClient
Connection = DMConnection.ApiConnection
Left = 192
Top = 92
Left = 218
Top = 76
end
object tmrScrollTop: TWebTimer
Interval = 100
......@@ -487,21 +451,21 @@ object FOrderEntryCuttingDie: TFOrderEntryCuttingDie
end
object xdwdsShipTo: TXDataWebDataSet
AfterEdit = xdwdsShipToAfterEdit
Left = 288
Top = 370
Left = 438
Top = 208
object xdwdsShipToADDRESS: TStringField
FieldName = 'ADDRESS'
end
end
object wdsQBItem: TWebDataSource
DataSet = xdwdsQBItem
Left = 230
Top = 554
Left = 272
Top = 548
end
object xdwdsQBItem: TXDataWebDataSet
AfterEdit = xdwdsQBItemAfterEdit
Left = 190
Top = 548
Left = 568
Top = 216
object xdwdsQBItemname: TStringField
FieldName = 'name'
end
......
<nav class="navbar navbar-expand navbar-light bg-light sticky-top" style="z-index: 100;">
<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">
<li class="nav-item pe-2">
<button id="btnadd" class="btn btn-primary btn-sm">Add</button>
......@@ -131,24 +126,18 @@
</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">
<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" id="modal_body">
<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">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal" id=btn_confirm_cancel>Cancel</button>
<div class="modal-footer justify-content-center">
<button type="button" class="btn btn-secondary me-3" data-bs-dismiss="modal" id="btn_confirm_cancel">Cancel</button>
<button type="button" class="btn btn-primary" data-bs-dismiss="modal" id="btn_confirm_delete">Delete</button>
</div>
</div>
</div>
</div>
</div>
<style>
.modal-backdrop {
opacity: 0 !important;
}
</style>
unit View.OrderEntryCuttingDie;
unit View.OrderEntryCuttingDie;
interface
......@@ -7,7 +7,7 @@ uses
WEBLib.Forms, WEBLib.Dialogs, WEBLib.Menus, WEBLib.ExtCtrls, WEBLib.StdCtrls,
WEBLib.JSON, Auth.Service, XData.Web.Client, WebLib.Storage,
ConnectionModule, App.Types, Vcl.StdCtrls, Vcl.Controls, WEBLib.DBCtrls,
Data.DB, XData.Web.JsonDataset, XData.Web.Dataset, WEBLib.DB;
Data.DB, XData.Web.JsonDataset, XData.Web.Dataset, WEBLib.DB, VCL.Forms;
type
TFOrderEntryCuttingDie = class(TWebForm)
......@@ -52,9 +52,6 @@ type
edtSpecialInstructions: TWebDBEdit;
btnSave: TWebButton;
btnCancel: TWebButton;
pnlMessage: TWebPanel;
lblMessage: TWebLabel;
btnCloseNotification: TWebButton;
edtCompanyName: TWebDBEdit;
XDataWebDataSet1NAME: TStringField;
XDataWebDataSet1staff_fields_quickbooks_item: TStringField;
......@@ -76,9 +73,7 @@ type
WebButton2: TWebButton;
procedure btnSaveClick(Sender: TObject);
procedure btnCancelClick(Sender: TObject);
procedure WebFormCreate(Sender: TObject);
procedure HideNotification();
procedure ShowNotification(Notification: string);
procedure WebFormCreate(Sender: TObject);
procedure WebFormShow(Sender: TObject);
[async] procedure GetCuttingDieOrder(Order_ID: string);
[async] procedure GetCustomer(customerID: string);
......@@ -98,14 +93,16 @@ type
procedure xdwdsShipToAfterEdit(DataSet: TDataSet);
procedure EditMode();
procedure xdwdsQBItemAfterEdit(DataSet: TDataSet);
procedure XDataWebDataSet1AfterEdit(DataSet: TDataSet);
procedure dtpOrderDateChange(Sender: TObject);
procedure btnEditClick(Sender: TObject);
procedure ViewMode();
procedure WebButton2Click(Sender: TObject);
procedure ShowAddAddressForm();
[async] procedure SendAddressToServer(AddressJSON: TJSONObject);
procedure WebDataSource1DataChange(Sender: TObject; Field: TField);
procedure XDataWebDataSet1AfterEdit(DataSet: TDataSet);
private
FModalAction: string;
FAgencyCode: string;
FCurrentReportType: string;
FSelectProc: TSelectProc;
......@@ -132,6 +129,20 @@ begin
ShowAddAddressForm();
end;
procedure TFOrderEntryCuttingDie.WebDataSource1DataChange(Sender: TObject; Field: TField);
begin
if Assigned(Field) then
console.log(
'Field.OnChange → ' + Field.FieldName +
' is now: ' + Field.AsString
)
else
console.log('WebDataSource1.OnDataChange fired with no specific Field');
end;
procedure TFOrderEntryCuttingDie.SendAddressToServer(AddressJSON: TJSONObject);
var
Response: TXDataClientResponse;
......@@ -141,12 +152,13 @@ begin
[AddressJSON.ToString]));
notification := TJSObject(Response.Result);
ShowNotification(string(notification['status']));
ShowToast(string(notification['status']));
xdwdsShipTo.Close;
xdwdsShipTo.SetJSONData(notification['ADDRESS']);
xdwdsShipTo.Open;
end;
procedure TFOrderEntryCuttingDie.ShowAddAddressForm;
// displays the search pop-up that allows the user to filter the order list
var
......@@ -159,6 +171,7 @@ begin
newform.Caption := 'Shipping Information';
newForm.Popup := True;
newForm.Border := fbDialog;
newForm.Position := poScreenCenter;
// used to manage Back button handling to close subform
window.location.hash := 'subform';
......@@ -193,6 +206,7 @@ begin
);
end;
function TFOrderEntryCuttingDie.VerifyOrder: Boolean;
var
input: TJSHTMLInputElement;
......@@ -249,6 +263,7 @@ begin
input.classList.remove('is-invalid');
end;
procedure TFOrderEntryCuttingDie.SendOrderToServer;
var
orderJSON: TJSONObject;
......@@ -296,14 +311,15 @@ begin
orderJSON.AddPair('ORDER_ID', orderID);
if mode = 'ADD' then
ShowNotification('Success:Order Added Successfully!')
ShowToast('Success: Order Added Successfully!')
else
ShowNotification('Success:Order Edited Successfully');
ShowToast('Success: Order Edited Successfully');
AddCuttingDieOrder(orderJSON);
end;
procedure TFOrderEntryCuttingDie.btnSaveClick(Sender: TObject);
// Converts all the information on the page into a JSON to then send to the server
begin
......@@ -315,33 +331,43 @@ begin
window.scrollTo(0, 0);
end;
procedure TFOrderEntryCuttingDie.btnCopyClick(Sender: TObject);
begin
mode := 'ADD';
dtpOrderDate.Date := 0;
dtpProofDate.Date := 0;
edtOrderNum.Text := '';
ShowNotification('Success:Order Successfully Copied');
ShowToast('Success: Order Successfully Copied');
EditMode();
window.scrollTo(0, 0);
end;
procedure TFOrderEntryCuttingDie.btnDeleteClick(Sender: TObject);
begin
FModalAction := 'delete';
document.getElementById('modal_body').innerHTML := 'Are you sure you want to delete this order?';
document.getElementById('btn_confirm_cancel').innerText := 'Cancel';
document.getElementById('btn_confirm_delete').innerText := 'Delete';
asm
var confirmationModal = new bootstrap.Modal(document.getElementById('confirmation_modal'), {
keyboard: false });
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;
procedure TFOrderEntryCuttingDie.btnEditClick(Sender: TObject);
begin
EditMode();
end;
procedure TFOrderEntryCuttingDie.DelOrder();
var
Response: TXDataClientResponse;
......@@ -350,43 +376,40 @@ begin
[OrderID, 'corrugated', JS.toString(AuthService.TokenPayload.Properties['user_id'])]));
end;
procedure TFOrderEntryCuttingDie.btnPDFClick(Sender: TObject);
begin
GenerateReportPDF;
end;
procedure TFOrderEntryCuttingDie.btn_confirm_deleteClick(Sender: TObject);
begin
if document.getElementById('btn_confirm_delete').innerText = 'Yes' then
if FModalAction = 'cancel' then
begin
FViewMain.change := false;
if OrderID <> '' then
begin
FViewMain.ViewOrderEntryCuttingDie(OrderID, '', 'EDIT', 'Failure:Changes Discarded');
end
FViewMain.ViewOrderEntryCuttingDie(OrderID, '', 'EDIT', 'Failure: Changes Discarded')
else
FViewMain.ViewOrders('');
end
else
else if FModalAction = 'delete' then
begin
Utils.ShowSpinner('spinner');
asm
var modal = document.getElementById('confirmation_modal');
// ensure the modal lives directly under <body>
if (modal && modal.parentNode !== document.body) {
document.body.appendChild(modal);
}
var bsModal = new bootstrap.Modal(modal, {
keyboard: false
});
var bsModal = new bootstrap.Modal(modal, { keyboard: false });
bsModal.hide();
end;
delOrder();
DelOrder();
tmrReturn.Enabled := true;
end;
end;
[async] procedure TFOrderEntryCuttingDie.GenerateReportPDF;
// sends the search to the server which then sends back a pdf of the results
var
......@@ -442,7 +465,6 @@ begin
begin
with TFOrderEntryCuttingDie(AForm) do
begin
HideNotification;
TFOrderEntryCuttingDie(AForm).customerID := customerInfo;
TFOrderEntryCuttingDie(AForm).orderID := orderInfo;
TFOrderEntryCuttingDie(AForm).mode := localMode;
......@@ -452,6 +474,7 @@ begin
);
end;
procedure TFOrderEntryCuttingDie.btnAddClick(Sender: TObject);
var
newform: TFAddOrder;
......@@ -462,6 +485,7 @@ begin
newform.Caption := 'Select Customer and Order Type';
newForm.Popup := True;
newForm.Border := fbDialog;
newForm.Position := poScreenCenter;
// used to manage Back button handling to close subform
window.location.hash := 'subform';
......@@ -489,14 +513,20 @@ begin
);
end;
procedure TFOrderEntryCuttingDie.btnCancelClick(Sender: TObject);
begin
document.getElementById('modal_body').innerHTML := 'Are you sure you want to cancel all changes to the customer?';
FModalAction := 'cancel';
document.getElementById('modal_body').innerHTML := 'Are you sure you want to cancel all changes?';
document.getElementById('btn_confirm_cancel').innerText := 'No';
document.getElementById('btn_confirm_delete').innerText := 'Yes';
asm
var confirmationModal = new bootstrap.Modal(document.getElementById('confirmation_modal'), {
keyboard: false });
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;
......@@ -508,13 +538,11 @@ end;
procedure TFOrderEntryCuttingDie.WebFormCreate(Sender: TObject);
begin
if not DMConnection.ApiConnection.Connected then
begin
if not DMConnection.ApiConnection.Connected then
DMConnection.ApiConnection.OpenAsync;
console.log('report requirements connection open')
end;
end;
procedure TFOrderEntryCuttingDie.getCuttingDieOrder(Order_ID: string);
// retrieves an order from the server then loads the info into the page
var
......@@ -621,46 +649,9 @@ begin
EditMode();
end;
edtOrderNum.Text := OrderID;
if notification = '' then
if notification <> '' then
begin
HideNotification;
end
else
begin
ShowNotification(notification);
end;
end;
procedure TFOrderEntryCuttingDie.HideNotification;
begin
pnlMessage.ElementHandle.hidden := True;
end;
procedure TFOrderEntryCuttingDie.ShowNotification(Notification: string);
var
splitNotification: TArray<string>;
begin
if Notification <> '' then
begin
splitNotification := Notification.Split([':']);
if(splitNotification[0] = 'Success') then
begin
asm
var messageDiv = document.getElementById('view.login.message');
messageDiv.classList.remove('alert-danger');
messageDiv.classList.add('alert-success');
end;
end
else
begin
asm
var messageDiv = document.getElementById('view.login.message');
messageDiv.classList.remove('alert-success');
messageDiv.classList.add('alert-danger');
end;
end;
lblMessage.Caption := splitNotification[1];
pnlMessage.ElementHandle.hidden := False;
ShowToast(notification);
end;
end;
......@@ -678,6 +669,7 @@ begin
window.scrollTo(0, 0);
end;
procedure TFOrderEntryCuttingDie.EditMode;
begin
FViewMain.change := true;
......@@ -691,26 +683,30 @@ begin
btnAdd.Enabled := false;
end;
procedure TFOrderEntryCuttingDie.xdwdsQBItemAfterEdit(DataSet: TDataSet);
procedure TFOrderEntryCuttingDie.XDataWebDataSet1AfterEdit(DataSet: TDataSet);
begin
EditMode();
end;
procedure TFOrderEntryCuttingDie.xdwdsShipToAfterEdit(DataSet: TDataSet);
procedure TFOrderEntryCuttingDie.xdwdsQBItemAfterEdit(DataSet: TDataSet);
begin
EditMode();
end;
procedure TFOrderEntryCuttingDie.XDataWebDataSet1AfterEdit(DataSet: TDataSet);
procedure TFOrderEntryCuttingDie.xdwdsShipToAfterEdit(DataSet: TDataSet);
begin
EditMode();
end;
procedure TFOrderEntryCuttingDie.dtpOrderDateChange(Sender: TObject);
begin
EditMode();
end;
procedure TFOrderEntryCuttingDie.ViewMode;
begin
btnPDF.Enabled := true;
......@@ -724,6 +720,7 @@ begin
FViewMain.change := false;
end;
initialization
RegisterClass(TFOrderEntryCuttingDie);
......
......@@ -112,44 +112,6 @@ object FOrderEntryWeb: TFOrderEntryWeb
Visible = False
WidthPercent = 100.000000000000000000
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
Left = 24
Top = 92
......@@ -743,7 +705,7 @@ object FOrderEntryWeb: TFOrderEntryWeb
Top = 87
Width = 96
Height = 25
Caption = '+'
Caption = 'Add Color'
ChildOrder = 59
ElementID = 'btnaddcolor'
HeightPercent = 100.000000000000000000
......@@ -863,6 +825,7 @@ object FOrderEntryWeb: TFOrderEntryWeb
ChildOrder = 79
ElementID = 'edtaround'
HeightPercent = 100.000000000000000000
ShowFocus = False
WidthPercent = 100.000000000000000000
DataField = 'layout_around'
DataSource = WebDataSource1
......@@ -876,6 +839,7 @@ object FOrderEntryWeb: TFOrderEntryWeb
ChildOrder = 79
ElementID = 'edtaccross'
HeightPercent = 100.000000000000000000
ShowFocus = False
WidthPercent = 100.000000000000000000
DataField = 'layout_accross'
DataSource = WebDataSource1
......@@ -889,6 +853,7 @@ object FOrderEntryWeb: TFOrderEntryWeb
ChildOrder = 79
ElementID = 'edtreverseprint'
HeightPercent = 100.000000000000000000
ShowFocus = False
WidthPercent = 100.000000000000000000
DataField = 'layout_reverse_print'
DataSource = WebDataSource1
......@@ -902,6 +867,7 @@ object FOrderEntryWeb: TFOrderEntryWeb
ChildOrder = 79
ElementID = 'edtsurfaceprint'
HeightPercent = 100.000000000000000000
ShowFocus = False
WidthPercent = 100.000000000000000000
DataField = 'layout_surface_print'
DataSource = WebDataSource1
......@@ -915,6 +881,7 @@ object FOrderEntryWeb: TFOrderEntryWeb
ChildOrder = 79
ElementID = 'edtcutoffdimension'
HeightPercent = 100.000000000000000000
ShowFocus = False
WidthPercent = 100.000000000000000000
DataField = 'layout_cutoff_dimension'
DataSource = WebDataSource1
......@@ -928,6 +895,7 @@ object FOrderEntryWeb: TFOrderEntryWeb
ChildOrder = 79
ElementID = 'edtcylinderrepeat'
HeightPercent = 100.000000000000000000
ShowFocus = False
WidthPercent = 100.000000000000000000
DataField = 'layout_cylinder_repeat'
DataSource = WebDataSource1
......@@ -941,6 +909,7 @@ object FOrderEntryWeb: TFOrderEntryWeb
ChildOrder = 79
ElementID = 'edtpitch'
HeightPercent = 100.000000000000000000
ShowFocus = False
WidthPercent = 100.000000000000000000
DataField = 'layout_pitch'
DataSource = WebDataSource1
......@@ -954,6 +923,7 @@ object FOrderEntryWeb: TFOrderEntryWeb
ChildOrder = 79
ElementID = 'edtbleed'
HeightPercent = 100.000000000000000000
ShowFocus = False
WidthPercent = 100.000000000000000000
DataField = 'layout_bleed'
DataSource = WebDataSource1
......@@ -967,6 +937,7 @@ object FOrderEntryWeb: TFOrderEntryWeb
ChildOrder = 79
ElementID = 'edtteeth'
HeightPercent = 100.000000000000000000
ShowFocus = False
WidthPercent = 100.000000000000000000
DataField = 'layout_teeth'
DataSource = WebDataSource1
......@@ -980,6 +951,7 @@ object FOrderEntryWeb: TFOrderEntryWeb
ChildOrder = 79
ElementID = 'edtcutback'
HeightPercent = 100.000000000000000000
ShowFocus = False
WidthPercent = 100.000000000000000000
DataField = 'layout_cutback'
DataSource = WebDataSource1
......@@ -993,6 +965,7 @@ object FOrderEntryWeb: TFOrderEntryWeb
ChildOrder = 79
ElementID = 'edtminimumtrapdimension'
HeightPercent = 100.000000000000000000
ShowFocus = False
WidthPercent = 100.000000000000000000
DataField = 'layout_minimum_trap_dim'
DataSource = WebDataSource1
......@@ -1006,6 +979,7 @@ object FOrderEntryWeb: TFOrderEntryWeb
ChildOrder = 79
ElementID = 'edtmaximumtrapdimension'
HeightPercent = 100.000000000000000000
ShowFocus = False
WidthPercent = 100.000000000000000000
DataField = 'layout_maximum_trap_dim'
DataSource = WebDataSource1
......@@ -1019,6 +993,7 @@ object FOrderEntryWeb: TFOrderEntryWeb
ChildOrder = 79
ElementID = 'edtsize'
HeightPercent = 100.000000000000000000
ShowFocus = False
WidthPercent = 100.000000000000000000
DataField = 'upc_size'
DataSource = WebDataSource1
......@@ -1028,10 +1003,12 @@ object FOrderEntryWeb: TFOrderEntryWeb
Top = 452
Width = 121
Height = 23
TabStop = False
AutoSize = True
ChildOrder = 79
ElementID = 'edtbarwidthreduction'
HeightPercent = 100.000000000000000000
ShowFocus = False
WidthPercent = 100.000000000000000000
DataField = 'upc_bar_width_reduction'
DataSource = WebDataSource1
......@@ -1041,10 +1018,12 @@ object FOrderEntryWeb: TFOrderEntryWeb
Top = 523
Width = 121
Height = 23
TabStop = False
AutoSize = True
ChildOrder = 79
ElementID = 'edtdistortionamount'
HeightPercent = 100.000000000000000000
ShowFocus = False
WidthPercent = 100.000000000000000000
DataField = 'upc_distortion_amount'
DataSource = WebDataSource1
......@@ -1054,6 +1033,7 @@ object FOrderEntryWeb: TFOrderEntryWeb
Top = 490
Width = 121
Height = 23
TabStop = False
AutoSize = True
ChildOrder = 79
ElementID = 'edtdistortionpercent'
......
<nav class="navbar navbar-expand navbar-light bg-light sticky-top" style="z-index: 100;">
<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">
<li class="nav-item pe-2">
<button id="btnadd" class="btn btn-primary btn-sm">Add</button>
......@@ -248,25 +243,43 @@
<input class="form-control input-sm" id="dtpdigitalcolordate" type="date">
</div>
</div>
<h4 class="custom-h4 mt-3">Quantity and Colors</h4>
<h4 class="custom-h4 mt-3">Quantity</h4>
<hr class="custom-hr">
<div class="row">
<div class="col-auto">
<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%'/>
</div>
<div class="col-auto">
<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%'/>
</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 class="col-auto">
<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%" />
</div>
<div class="col-auto">
<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%" />
</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>
<hr class="custom-hr">
<div class="row">
<div class="col-auto">
<label label style="font-weight: 700; font-size: 15px;" class="form-label mt-2">Microdots:</label>
......@@ -407,24 +420,18 @@
</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">
<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" id="modal_body">
<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">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal" id=btn_confirm_cancel>Cancel</button>
<div class="modal-footer justify-content-center">
<button type="button" class="btn btn-secondary me-3" data-bs-dismiss="modal" id="btn_confirm_cancel">Cancel</button>
<button type="button" class="btn btn-primary" data-bs-dismiss="modal" id="btn_confirm_delete">Delete</button>
</div>
</div>
</div>
</div>
</div>
<style>
.modal-backdrop {
opacity: 0 !important;
}
</style>
......@@ -7,14 +7,11 @@ uses
WEBLib.Forms, WEBLib.Dialogs, WEBLib.Menus, WEBLib.ExtCtrls, WEBLib.StdCtrls,
WEBLib.JSON, Auth.Service, XData.Web.Client, WebLib.Storage,
ConnectionModule, App.Types, Vcl.StdCtrls, Vcl.Controls, WEBLib.DBCtrls,
Data.DB, XData.Web.JsonDataset, XData.Web.Dataset, WEBLib.DB;
Data.DB, XData.Web.JsonDataset, XData.Web.Dataset, WEBLib.DB, VCL.Forms;
type
TFOrderEntryWeb = class(TWebForm)
WebLabel2: TWebLabel;
pnlMessage: TWebPanel;
lblMessage: TWebLabel;
btnCloseNotification: TWebButton;
edtCompanyName: TWebDBEdit;
edtCompanyAccountName: TWebDBEdit;
edtInQuickBooks: TWebDBEdit;
......@@ -208,8 +205,6 @@ type
btnAdd: TWebButton;
WebButton2: TWebButton;
procedure WebFormCreate(Sender: TObject);
procedure HideNotification();
procedure ShowNotification(Notification: string);
procedure WebFormShow(Sender: TObject);
[async] procedure getOrder(Order_ID: string);
[async] procedure getCustomer(customerID: string);
......@@ -226,7 +221,6 @@ type
procedure btnCloseClick(Sender: TObject);
procedure btnDeleteClick(Sender: TObject);
[async] procedure DelOrder;
procedure btnCloseNotificationClick(Sender: TObject);
procedure tmrReturnTimer(Sender: TObject);
procedure btn_confirm_deleteClick(Sender: TObject);
function VerifyOrder(): boolean;
......@@ -240,6 +234,7 @@ type
procedure ShowAddAddressForm();
[async] procedure SendAddressToServer(AddressJSON: TJSONObject);
private
FModalAction: string;
FAgencyCode: string;
FCurrentReportType: string;
FSelectProc: TSelectProc;
......@@ -247,6 +242,7 @@ type
customerID: string;
mode: string;
notification: string;
procedure RemoveColorRow(Sender: TObject);
//FJSONProc1: TJSONProc1;
public
class function CreateForm(AElementID, orderInfo, customerInfo, mode, info: string): TWebForm;
......@@ -276,7 +272,7 @@ begin
[AddressJSON.ToString]));
notification := TJSObject(Response.Result);
ShowNotification(string(notification['status']));
ShowToast(string(notification['status']));
xdwdsShipTo.Close;
xdwdsShipTo.SetJSONData(notification['ADDRESS']);
xdwdsShipTo.Open;
......@@ -294,6 +290,7 @@ begin
newform.Caption := 'Input Shipping Information';
newForm.Popup := True;
newForm.Border := fbDialog;
newForm.Position := poScreenCenter;
// used to manage Back button handling to close subform
window.location.hash := 'subform';
......@@ -412,18 +409,23 @@ begin
dtpDigitalColorDate.Date := 0;
edtOrderNum.Text := '';
EditMode();
ShowNotification('Success:Order Successfully Copied');
ShowToast('Success: Order Successfully Copied');
window.scrollTo(0, 0);
end;
procedure TFOrderEntryWeb.btnDeleteClick(Sender: TObject);
begin
FModalAction := 'delete';
document.getElementById('modal_body').innerHTML := 'Are you sure you want to delete this order?';
document.getElementById('btn_confirm_cancel').innerText := 'Cancel';
document.getElementById('btn_confirm_delete').innerText := 'Delete';
asm
var confirmationModal = new bootstrap.Modal(document.getElementById('confirmation_modal'), {
keyboard: false });
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;
......@@ -547,7 +549,7 @@ begin
else
info := 'Success:Order Successfully Added';
AddWebOrder(orderJSON);
ShowNotification(info);
ShowToast(info);
end;
procedure TFOrderEntryWeb.btnPDFClick(Sender: TObject);
......@@ -557,32 +559,26 @@ end;
procedure TFOrderEntryWeb.btn_confirm_deleteClick(Sender: TObject);
begin
if document.getElementById('btn_confirm_delete').innerText = 'Yes' then
if FModalAction = 'cancel' then
begin
FViewMain.change := false;
if OrderID <> '' then
begin
FViewMain.ViewOrderEntryWeb(OrderID, '', 'EDIT', 'Failure:Changes Discarded');
end
FViewMain.ViewOrderEntryWeb(OrderID, '', 'EDIT', 'Failure: Changes Discarded')
else
FViewMain.ViewOrders('');
end
else
else if FModalAction = 'delete' then
begin
Utils.ShowSpinner('spinner');
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
});
var bsModal = new bootstrap.Modal(modal, { keyboard: false });
bsModal.hide();
end;
delOrder();
DelOrder();
tmrReturn.Enabled := true;
end;
end;
......@@ -640,7 +636,6 @@ begin
begin
with TFOrderEntryWeb(AForm) do
begin
HideNotification;
TFOrderEntryWeb(AForm).customerID := customerInfo;
TFOrderEntryWeb(AForm).orderID := orderInfo;
TFOrderEntryWeb(AForm).mode := localMode;
......@@ -652,56 +647,75 @@ begin
end;
procedure TFOrderEntryWeb.addColorRow(num: string; Color: string; LPI: string; Size: string);
// Java script code to add a row of colors when a button is clicked
// all variables are information to be placed in the boxes when loading an order.
// TODO: convert to Delphi
var
container, newRow, col, labelEl, inputEl, removeCol: TJSHTMLElement;
removeBtn: TWebButton;
values: array[0..3] of string;
labels: array[0..3] of string;
i: Integer;
begin
asm
const container = document.getElementById('additionalFields');
// Create a new row for the new fields
const newRow = document.createElement('div');
newRow.className = 'row mb-2';
const labels = ['#', 'Color', 'LPI', 'Size'];
const values = [num, Color, LPI, Size];
labels.forEach((label, index) => {
const col = document.createElement('div');
col.className = 'col-sm';
const labelElement = document.createElement('label');
labelElement.className = 'pe-2';
labelElement.style.fontWeight = '700';
labelElement.style.fontSize = '15px';
labelElement.textContent = label + ':';
const inputElement = document.createElement('input');
inputElement.className = 'form-control input-sm';
inputElement.style.width = '100%';
inputElement.id = 'input-' + container.childElementCount + '-' + index; // Unique ID based on count
inputElement.value = values[index]; // Set the value based on the parameter
col.appendChild(labelElement);
col.appendChild(inputElement);
newRow.appendChild(col);
});
const removeButtonCol = document.createElement('div');
removeButtonCol.className = 'col-auto d-flex align-items-center';
const removeButton = document.createElement('button');
removeButton.className = 'btn btn-danger btn-sm';
removeButton.textContent = 'Remove';
removeButton.addEventListener('click', function() {
container.removeChild(newRow);
});
removeButtonCol.appendChild(removeButton);
newRow.appendChild(removeButtonCol);
container.appendChild(newRow);
end;
container := TJSHTMLElement(document.getElementById('additionalFields'));
// Create the new row container
newRow := TJSHTMLElement(document.createElement('div'));
newRow.className := 'row mb-2';
labels[0] := '#'; values[0] := num;
labels[1] := 'Color'; values[1] := color;
labels[2] := 'LPI'; values[2] := LPI;
labels[3] := 'Size'; values[3] := size;
for i := 0 to 3 do
begin
col := TJSHTMLElement(document.createElement('div'));
col.className := 'col-sm';
labelEl := TJSHTMLElement(document.createElement('label'));
labelEl.className := 'pe-2';
labelEl.style.setProperty('font-weight', '700');
labelEl.style.setProperty('font-size', '15px');
labelEl.textContent := labels[i] + ':';
inputEl := TJSHTMLElement(document.createElement('input'));
inputEl.className := 'form-control input-sm';
inputEl.setAttribute('style', 'width: 100%');
inputEl.setAttribute('value', values[i]);
inputEl.setAttribute('id', 'input-' + IntToStr(container.childElementCount) + '-' + IntToStr(i));
col.appendChild(labelEl);
col.appendChild(inputEl);
newRow.appendChild(col);
end;
// Add remove button
removeCol := TJSHTMLElement(document.createElement('div'));
removeCol.className := 'col-auto d-flex align-items-end pb-1';
removeBtn := TWebButton.Create(Self);
removeBtn.Caption := 'Remove';
removeBtn.ElementClassName := 'btn btn-danger btn-sm mt-1';
removeBtn.ParentElement := removeCol;
removeBtn.ElementHandle.style.setProperty('height', '30px');
removeBtn.OnClick := RemoveColorRow;
newRow.appendChild(removeCol);
container.appendChild(newRow);
end;
procedure TFOrderEntryWeb.RemoveColorRow(Sender: TObject);
var
btn: TWebButton;
rowElement: TJSHTMLElement;
begin
EditMode();
btn := TWebButton(Sender);
if Assigned(btn.ElementHandle) and Assigned(btn.ElementHandle.parentElement) then
begin
// Assuming button is inside a <div> inside the row
rowElement := TJSHTMLElement(btn.ElementHandle.parentElement.parentElement);
if Assigned(rowElement) then
rowElement.remove;
end;
end;
procedure TFOrderEntryWeb.WebButton1Click(Sender: TObject);
......@@ -720,6 +734,7 @@ begin
newform.Caption := 'Select Customer and Order Type';
newForm.Popup := True;
newForm.Border := fbDialog;
newForm.Position := poScreenCenter;
// used to manage Back button handling to close subform
window.location.hash := 'subform';
......@@ -749,12 +764,17 @@ end;
procedure TFOrderEntryWeb.btnCancelClick(Sender: TObject);
begin
document.getElementById('modal_body').innerHTML := 'Are you sure you want to cancel all changes to the customer?';
FModalAction := 'cancel';
document.getElementById('modal_body').innerHTML := 'Are you sure you want to cancel all changes?';
document.getElementById('btn_confirm_cancel').innerText := 'No';
document.getElementById('btn_confirm_delete').innerText := 'Yes';
asm
var confirmationModal = new bootstrap.Modal(document.getElementById('confirmation_modal'), {
keyboard: false });
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;
......@@ -764,10 +784,6 @@ begin
FViewMain.ViewOrders('');
end;
procedure TFOrderEntryWeb.btnCloseNotificationClick(Sender: TObject);
begin
hideNotification();
end;
procedure TFOrderEntryWeb.WebFormCreate(Sender: TObject);
begin
......@@ -955,13 +971,9 @@ begin
EditMode();
end;
edtOrderNum.Text := OrderID;
if notification = '' then
begin
HideNotification;
end
else
if notification <> '' then
begin
ShowNotification(notification);
ShowToast(notification);
end;
end;
......@@ -970,39 +982,6 @@ begin
EditMode();
end;
procedure TFOrderEntryWeb.HideNotification;
begin
pnlMessage.ElementHandle.hidden := True;
end;
procedure TFOrderEntryWeb.ShowNotification(Notification: string);
var
splitNotification: TArray<string>;
begin
if Notification <> '' then
begin
splitNotification := Notification.Split([':']);
if(splitNotification[0] = 'Success') then
begin
asm
var messageDiv = document.getElementById('view.login.message');
messageDiv.classList.remove('alert-danger');
messageDiv.classList.add('alert-success');
end;
end
else
begin
asm
var messageDiv = document.getElementById('view.login.message');
messageDiv.classList.remove('alert-success');
messageDiv.classList.add('alert-danger');
end;
end;
lblMessage.Caption := splitNotification[1];
pnlMessage.ElementHandle.hidden := False;
end;
end;
procedure TFOrderEntryWeb.tmrReturnTimer(Sender: TObject);
begin
......
object FViewOrders: TFViewOrders
Width = 676
Height = 480
Caption = 'main.errorpanel'
CSSLibrary = cssBootstrap
ElementFont = efCSS
Font.Charset = DEFAULT_CHARSET
......@@ -310,36 +309,6 @@ object FViewOrders: TFViewOrders
HeightPercent = 100.000000000000000000
WidthPercent = 100.000000000000000000
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
Connection = DMConnection.ApiConnection
Left = 28
......
<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 -->
<div class="row mt-2 justify-content-center">
<div class="col-auto d-flex align-items-center">
......
......@@ -14,7 +14,7 @@ uses
WEBLib.JSON, Auth.Service, XData.Web.Client, WebLib.Storage,
ConnectionModule, App.Types, Vcl.StdCtrls, Vcl.Controls, WEBLib.DBCtrls,
XData.Web.JsonDataset, WEBLib.DB, Data.DB, XData.Web.Dataset, XData.Web.DatasetCommon,
WEBLib.Grids;
WEBLib.Grids, VCL.Forms;
type
TFViewOrders = class(TWebForm)
......@@ -56,15 +56,11 @@ type
wcbPageSize: TWebComboBox;
wlcbOrderBy: TWebLookupComboBox;
edtSearch: TWebEdit;
pnlMessage: TWebPanel;
lblMessage: TWebLabel;
btnCloseNotification: TWebButton;
xdwdsOrdersDBID: TStringField;
tmrReturn: TWebTimer;
procedure WebFormCreate(Sender: TObject);
procedure btnAddOrderClick(Sender: TObject);
procedure btnSearchClick(Sender: TObject);
procedure btnCloseNotificationClick(Sender: TObject);
procedure WebFormShow(Sender: TObject);
procedure btnPDFClick(Sender: TObject);
procedure wcbPageSizeChange(Sender: TObject);
......@@ -73,20 +69,20 @@ type
procedure wdbtcOrdersClickCell(Sender: TObject; ACol, ARow: Integer);
procedure WebButton1Click(Sender: TObject);
procedure tmrReturnTimer(Sender: TObject);
[async] procedure GenerateReportPDFAsync(APdfTab: TJSWindow);
private
FChildForm: TWebForm;
FPendingPdfTab: TJSWindow;
procedure ClearTable();
procedure GeneratePagination(TotalPages: Integer);
function GenerateSearchOptions(): string;
procedure orderEntry(orderInfo, customerInfo, mode, orderType: string);
procedure HideNotification();
procedure ShowNotification(Notification: string);
procedure ShowAddOrderForm();
procedure ShowSearchForm();
procedure ShowSetStatusForm();
[async] procedure GetOrders(searchOptions: string);
[async] procedure GenerateReportPDF;
[async] procedure SetStatus(statusInfo: string);
procedure HandlePDFConfirmation;
var
PageNumber: integer;
PageSize: integer;
......@@ -146,43 +142,128 @@ begin
end;
procedure TFViewOrders.btnPDFClick(Sender: TObject);
var
confirmBtn: TJSHTMLElement;
begin
if xdwdsOrders.RecordCount >= 100 then
begin
FPendingPdfTab := nil;
document.getElementById('modal_body').innerHTML :=
'You are about to generate a PDF for over 100 orders. This may take some time. Continue?';
document.getElementById('btn_confirm_cancel').innerText := 'Cancel';
document.getElementById('btn_confirm_delete').innerText := 'Yes';
confirmBtn := TJSHTMLElement(document.getElementById('btn_confirm_delete'));
confirmBtn.addEventListener('click',
TJSEventHandler(
procedure(Event: TJSEvent)
begin
asm bootstrap.Modal.getInstance(document.getElementById('confirmation_modal')).hide(); end;
HandlePDFConfirmation;
end
)
);
asm
var modal = document.getElementById('confirmation_modal');
if (modal && modal.parentNode !== document.body) {
document.body.appendChild(modal);
}
var confirmationModal = new bootstrap.Modal(modal, { keyboard: false });
confirmationModal.show();
end;
end
else
begin
FPendingPdfTab := window.open('', '_blank');
if Assigned(FPendingPdfTab) then
FPendingPdfTab.document.write(
'<!DOCTYPE html>' +
'<html lang="en">' +
'<head>' +
'<meta charset="UTF-8">' +
'<meta name="viewport" content="width=device-width, initial-scale=1.0">' +
'<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">' +
'</head>' +
'<body class="d-flex flex-column justify-content-center align-items-center vh-100 bg-light">' +
'<div class="spinner-border text-primary" role="status" style="width: 3rem; height: 3rem;"></div>' +
'<div class="mt-3 fs-5 text-muted">Generating PDF, please wait�</div>' +
'</body>' +
'</html>'
);
Utils.ShowSpinner('spinner');
GenerateReportPDFAsync(FPendingPdfTab);
end;
end;
procedure TFViewOrders.HandlePDFConfirmation;
begin
// 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');
GenerateReportPDF;
GenerateReportPDFAsync(FPendingPdfTab);
FPendingPdfTab := nil;
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
xdcResponse: TXDataClientResponse;
searchOptions, pdfURL: string;
jsObject: TJSObject;
begin
Utils.ShowSpinner('spinner');
try
searchOptions := edtSearch.Text;
searchOptions := edtSearch.Text + '&forPDF=true';
// Call the server method to generate the PDF
xdcResponse := await(XDataWebClient1.RawInvokeAsync('ILookupService.GenerateOrderListPDF', [searchOptions]));
jsObject := JS.TJSObject(xdcResponse.Result);
pdfURL := JS.toString(jsObject.Properties['value']);
xdcResponse := await(
XDataWebClient1.RawInvokeAsync('ILookupService.GenerateOrderListPDF',
[searchOptions]));
jsObject := TJSObject(xdcResponse.Result);
pdfURL := String(jsObject.Properties['value']);
// Open the PDF in a new browser tab
window.open(pdfURL, '_blank');
if Assigned(APdfTab) then
APdfTab.location.href := pdfURL;
except
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;
Utils.HideSpinner('spinner');
end;
procedure TFViewOrders.WebButton1Click(Sender: TObject);
begin
if statusOrderID <> '' then
ShowSetStatusForm()
else
ShowNotification('Failure:Please select an order');
ShowToast('Failure: Please select an order');
end;
procedure TFViewOrders.WebFormCreate(Sender: TObject);
......@@ -265,9 +346,7 @@ end;
procedure TFViewOrders.WebFormShow(Sender: TObject);
begin
if info <> '' then
ShowNotification(info)
else
HideNotification();
ShowToast(info)
end;
......@@ -288,6 +367,7 @@ begin
newform.Caption := 'Select Customer and Order Type';
newForm.Popup := True;
newForm.position:= poScreenCenter;
newForm.Border := fbDialog;
// used to manage Back button handling to close subform
......@@ -320,6 +400,7 @@ begin
newform.Caption := 'Input Search Options';
newForm.Popup := True;
newForm.Border := fbDialog;
newForm.position:= poScreenCenter;
newForm.searchOptions := FViewMain.search;
// used to manage Back button handling to close subform
......@@ -370,6 +451,7 @@ begin
newform.Caption := 'Input Search Options';
newForm.Popup := True;
newForm.Border := fbDialog;
newForm.Position := poScreenCenter;
newForm.OrderID := statusOrderID;
newForm.JobName := wdbtcOrders.Cells[3, row];
if wdbtcOrders.Cells[14, row] <> '' then
......@@ -722,10 +804,6 @@ begin
FViewMain.ViewOrderEntryCuttingDie(orderInfo, customerInfo, mode, '');
end;
procedure TFViewOrders.btnCloseNotificationClick(Sender: TObject);
begin
HideNotification();
end;
procedure TFViewOrders.btnSearchClick(Sender: TObject);
var
......@@ -798,39 +876,5 @@ begin
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.
......@@ -216,6 +216,7 @@ object FSelectCustomer: TFSelectCustomer
ChildOrder = 5
HeightPercent = 100.000000000000000000
WidthPercent = 100.000000000000000000
OnClick = btnCancelClick
end
object btnConfirm: TWebButton
Left = 440
......
......@@ -47,6 +47,7 @@ type
procedure btnConfirmClick(Sender: TObject);
procedure TMSFNCGrid1CellClick(Sender: TObject; ACol, ARow: Integer);
procedure edtSearchChange(Sender: TObject);
procedure btnCancelClick(Sender: TObject);
private
{ Private declarations }
[Async] procedure GetCustomers();
......@@ -84,6 +85,11 @@ begin
getCustomers();
end;
procedure TFSelectCustomer.btnCancelClick(Sender: TObject);
begin
Close();
end;
procedure TFSelectCustomer.btnConfirmClick(Sender: TObject);
begin
if edtID.Text = '' then
......
......@@ -5,7 +5,7 @@ interface
uses
System.SysUtils, System.Classes, JS, Web, WEBLib.Graphics, WEBLib.Controls,
WEBLib.Forms, WEBLib.Dialogs, Vcl.Controls, Vcl.StdCtrls, WEBLib.ExtCtrls,
WEBLib.StdCtrls;
WEBLib.StdCtrls, Utils;
type
TFSetStatus = class(TWebForm)
......@@ -41,8 +41,6 @@ type
procedure btnCancelClick(Sender: TObject);
private
{ Private declarations }
procedure HideNotification;
procedure ShowNotification(Notification: string);
public
{ Public declarations }
confirm: boolean;
......@@ -65,14 +63,15 @@ end;
procedure TFSetStatus.btnConfirmClick(Sender: TObject);
begin
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
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
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
begin
confirm := true;
ShowToast('Success: Status updated!');
Close;
end;
end;
......@@ -83,7 +82,6 @@ var
i: integer;
filteredItems: TJSArray;
begin
HideNotification();
edtOrderID.Text := OrderID;
dtpDate.Date := 0;
edtJobName.Text := JobName;
......@@ -138,17 +136,5 @@ begin
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.
\ No newline at end of file
object FViewUserProfile: TFViewUserProfile
Color = clWhite
Width = 604
Height = 434
Font.Charset = DEFAULT_CHARSET
Font.Color = clWindowText
Font.Height = -11
Font.Name = 'Tahoma'
Font.Size = 8
Font.Style = []
FormStyle = fsNormal
Height = 434
Left = 0
OnShow = WebFormShow
ParentFont = False
TabOrder = 0
Top = 0
Width = 604
OnShow = WebFormShow
object WebLabel1: TWebLabel
Left = 24
Top = 24
Width = 55
Height = 13
Caption = 'User Profile'
ElementID = 'view.userprofile.title'
Font.Charset = ANSI_CHARSET
Font.Color = clWindowText
Font.Height = -11
Font.Name = 'Tahoma'
Font.Size = 8
Font.Style = []
Height = 16
Left = 24
Top = 24
HeightPercent = 100.000000000000000000
ParentFont = False
Visible = False
Width = 54
WidthPercent = 100.000000000000000000
end
object WebLabel3: TWebLabel
Left = 39
Top = 59
Width = 38
Height = 14
Caption = 'User ID:'
ElementID = 'view.userprofile.form.lblUserID'
ElementPosition = epRelative
......@@ -37,14 +37,16 @@ object FViewUserProfile: TFViewUserProfile
Font.Color = clBlack
Font.Height = -11
Font.Name = 'Arial'
Font.Size = 8
Font.Style = []
Height = 16
Left = 39
Top = 59
Width = 40
HeightPercent = 100.000000000000000000
ParentFont = False
WidthPercent = 100.000000000000000000
end
object WebLabel2: TWebLabel
Left = 13
Top = 131
Width = 71
Height = 14
Caption = 'Email Address:'
ElementID = 'view.userprofile.form.lblEmail'
ElementPosition = epRelative
......@@ -52,14 +54,16 @@ object FViewUserProfile: TFViewUserProfile
Font.Color = clBlack
Font.Height = -11
Font.Name = 'Arial'
Font.Size = 8
Font.Style = []
Height = 16
Left = 13
Top = 157
Width = 70
HeightPercent = 100.000000000000000000
ParentFont = False
WidthPercent = 100.000000000000000000
end
object WebLabel4: TWebLabel
Left = 29
Top = 83
Width = 52
Height = 14
Caption = 'Username:'
ElementID = 'view.userprofile.form.lblUserName'
ElementPosition = epRelative
......@@ -67,60 +71,49 @@ object FViewUserProfile: TFViewUserProfile
Font.Color = clBlack
Font.Height = -11
Font.Name = 'Arial'
Font.Size = 8
Font.Style = []
Height = 16
Left = 29
Top = 83
Width = 51
HeightPercent = 100.000000000000000000
ParentFont = False
WidthPercent = 100.000000000000000000
end
object WebLabel5: TWebLabel
Caption = 'Full Name:'
ElementID = 'view.userprofile.form.lblFullName'
ElementPosition = epRelative
Font.Charset = ANSI_CHARSET
Font.Color = clBlack
Font.Height = -11
Font.Name = 'Arial'
Font.Size = 8
Font.Style = []
Height = 16
Left = 29
Top = 107
Width = 51
end
object WebLabel6: TWebLabel
Caption = 'Phone Number:'
ElementID = 'view.userprofile.form.lblPhone'
Width = 49
Height = 14
Caption = 'Full Name:'
ElementID = 'view.userprofile.form.lblFullName'
ElementPosition = epRelative
Font.Charset = ANSI_CHARSET
Font.Color = clBlack
Font.Height = -11
Font.Name = 'Arial'
Font.Size = 8
Font.Style = []
Height = 16
Left = 5
Top = 133
Width = 74
HeightPercent = 100.000000000000000000
ParentFont = False
WidthPercent = 100.000000000000000000
end
object lblResult: TWebLabel
Left = 85
Top = 246
Width = 3
Height = 14
ElementID = 'view.userprofile.form.lblresult'
ElementPosition = epRelative
Font.Charset = ANSI_CHARSET
Font.Color = clBlack
Font.Height = -11
Font.Name = 'Arial'
Font.Size = 8
Font.Style = []
Height = 13
Left = 85
Top = 246
Width = 3
HeightPercent = 100.000000000000000000
ParentFont = False
WidthPercent = 100.000000000000000000
end
object edtUsername: TWebEdit
Alignment = taLeftJustify
Color = clWindow
Left = 85
Top = 80
Width = 121
Height = 21
ElementID = 'view.userprofile.form.edtUsername'
ElementPosition = epRelative
Enabled = False
......@@ -128,20 +121,18 @@ object FViewUserProfile: TFViewUserProfile
Font.Color = clBlack
Font.Height = -11
Font.Name = 'Arial'
Font.Size = 8
Font.Style = []
Height = 21
HeightPercent = 100.000000000000000000
HideSelection = False
Left = 85
ParentFont = False
ReadOnly = True
ShowFocus = True
TabOrder = 0
Top = 80
Width = 121
WidthPercent = 100.000000000000000000
end
object edtUserId: TWebEdit
Alignment = taLeftJustify
Color = clWindow
Left = 85
Top = 56
Width = 121
Height = 21
ElementID = 'view.userprofile.form.edtUserID'
ElementPosition = epRelative
Enabled = False
......@@ -149,58 +140,37 @@ object FViewUserProfile: TFViewUserProfile
Font.Color = clBlack
Font.Height = -11
Font.Name = 'Arial'
Font.Size = 8
Font.Style = []
Height = 21
HeightPercent = 100.000000000000000000
HideSelection = False
Left = 85
ParentFont = False
ReadOnly = True
ShowFocus = True
TabOrder = 1
Top = 56
Width = 121
WidthPercent = 100.000000000000000000
end
object edtFullName: TWebEdit
Alignment = taLeftJustify
ChildOrder = 5
Color = clWindow
ElementID = 'view.userprofile.form.edtFullName'
ElementPosition = epRelative
Font.Charset = ANSI_CHARSET
Font.Color = clBlack
Font.Height = -11
Font.Name = 'Arial'
Font.Size = 8
Font.Style = []
Height = 21
HideSelection = False
Left = 85
ShowFocus = True
TabOrder = 0
Top = 104
Width = 121
end
object edtPhone: TWebEdit
Alignment = taLeftJustify
ChildOrder = 7
Color = clWindow
ElementID = 'view.userprofile.form.edtPhone'
Height = 21
ChildOrder = 5
ElementID = 'view.userprofile.form.edtFullName'
ElementPosition = epRelative
Font.Charset = ANSI_CHARSET
Font.Color = clBlack
Font.Height = -11
Font.Name = 'Arial'
Font.Size = 8
Font.Style = []
Height = 21
HeightPercent = 100.000000000000000000
HideSelection = False
Left = 85
ShowFocus = True
TabOrder = 0
Top = 128
Width = 121
ParentFont = False
WidthPercent = 100.000000000000000000
end
object chkAdminUser: TWebCheckBox
Left = 85
Top = 179
Width = 113
Height = 22
Caption = 'chkAdminUser'
ChildOrder = 9
ElementID = 'view.userprofile.form.chkAdminUser'
......@@ -210,128 +180,72 @@ object FViewUserProfile: TFViewUserProfile
Font.Color = clBlack
Font.Height = -11
Font.Name = 'Arial'
Font.Size = 8
Font.Style = []
Height = 22
Left = 85
HeightPercent = 100.000000000000000000
ParentFont = False
Role = 'null'
ShowFocus = True
TabOrder = 0
Top = 179
Width = 113
WidthPercent = 100.000000000000000000
end
object edtEmail: TWebEdit
Alignment = taLeftJustify
Left = 85
Top = 126
Width = 121
Height = 21
ChildOrder = 7
Color = clWindow
ElementID = 'view.userprofile.form.edtEmail'
ElementPosition = epRelative
Font.Charset = ANSI_CHARSET
Font.Color = clBlack
Font.Height = -11
Font.Name = 'Arial'
Font.Size = 8
Font.Style = []
Height = 21
HeightPercent = 100.000000000000000000
HideSelection = False
Left = 85
ShowFocus = True
TabOrder = 0
Top = 152
Width = 121
ParentFont = False
WidthPercent = 100.000000000000000000
end
object btnConfirm: TWebButton
Left = 85
Top = 210
Width = 96
Height = 25
Caption = 'Confirm Changes'
ChildOrder = 12
Color = clNone
ElementID = 'view.userprofile.form.btnconfirm'
ElementPosition = epRelative
Font.Charset = ANSI_CHARSET
Font.Color = clBlack
Font.Height = -11
Font.Name = 'Arial'
Font.Size = 8
Font.Style = []
Height = 25
Left = 85
OnClick = btnConfirmClick
HeightPercent = 100.000000000000000000
ParentFont = False
Role = 'button'
TabOrder = 0
WidthPercent = 100.000000000000000000
OnClick = btnConfirmClick
end
object btnCancel: TWebButton
Left = 208
Top = 210
Width = 96
end
object WebButton1: TWebButton
Height = 25
Caption = 'Cancel Changes'
ChildOrder = 14
Color = clNone
ElementID = 'view.userprofile.form.btncancel'
ElementPosition = epRelative
Font.Charset = ANSI_CHARSET
Font.Color = clBlack
Font.Height = -11
Font.Name = 'Arial'
Font.Size = 8
Font.Style = []
Height = 25
Left = 208
OnClick = WebButton1Click
HeightPercent = 100.000000000000000000
ParentFont = False
Role = 'button'
TabOrder = 0
Top = 210
Width = 96
end
object pnlMessage: TWebPanel
ChildOrder = 17
Color = clBtnFace
ElementID = 'view.login.message'
ElementPosition = epRelative
Font.Charset = ANSI_CHARSET
Font.Color = clBlack
Font.Height = -11
Font.Name = 'Arial'
Font.Size = 8
Font.Style = []
Height = 33
Left = 236
Role = 'null'
TabOrder = 8
TabStop = False
Top = 4
Width = 121
object lblMessage: TWebLabel
Caption = 'Message'
ElementID = 'view.login.message.label'
Font.Charset = ANSI_CHARSET
Font.Color = clBlack
Font.Height = -11
Font.Name = 'Arial'
Font.Size = 8
Font.Style = []
Height = 16
Left = 16
Top = 11
Width = 43
end
object btnCloseNotification: TWebButton
ChildOrder = 1
Color = clNone
ElementID = 'view.login.message.button'
Font.Charset = ANSI_CHARSET
Font.Color = clBlack
Font.Height = -11
Font.Name = 'Arial'
Font.Size = 8
Font.Style = []
Height = 25
Left = 96
OnClick = btnCloseNotificationClick
Role = 'button'
TabOrder = 0
Top = 3
Width = 22
end
WidthPercent = 100.000000000000000000
OnClick = btnCancelClick
end
object XDataWebClient1: TXDataWebClient
Connection = DMConnection.ApiConnection
Left = 359
Top = 52
end
......
<div class="row">
<div class="col-lg-12">
<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 class="container">
<!-- Profile form -->
<div class="row">
<div class="col-lg-8 col-xl-6 mx-auto">
<form id="userprofileform" class="needs-validation" role="form" autocomplete="off" novalidate>
<div class="mb-3">
<label id="view.userprofile.form.lblUserID"
for="view.userprofile.form.edtUserID"
class="form-label">User&nbsp;ID</label>
<input id="view.userprofile.form.edtUserID"
class="form-control"
readonly>
</div>
<div class="mb-3">
<label id="view.userprofile.form.lblUserName"
for="view.userprofile.form.edtUsername"
class="form-label">Username</label>
<input id="view.userprofile.form.edtUsername"
class="form-control"
required>
<div class="invalid-feedback">Username is required.</div>
</div>
<div class="mb-3">
<label id="view.userprofile.form.lblFullName"
for="view.userprofile.form.edtFullName"
class="form-label">Full&nbsp;Name</label>
<input id="view.userprofile.form.edtFullName"
class="form-control"
required>
<div class="invalid-feedback">Full Name is required.</div>
</div>
<div class="mb-3">
<label id="view.userprofile.form.lblEmail"
for="view.userprofile.form.edtEmail"
class="form-label">Email&nbsp;Address</label>
<input id="view.userprofile.form.edtEmail"
type="email"
class="form-control"
required>
<div class="invalid-feedback">Valid email is required.</div>
</div>
<div class="form-check mb-4">
<input type="checkbox"
id="view.userprofile.form.chkAdminUser"
class="form-check-input">
<label for="view.userprofile.form.chkAdminUser"
class="form-check-label">
Admin&nbsp;User
</label>
</div>
<div role="form">
<div class="form-group">
<label id="view.userprofile.form.lblUserID">User ID:</label>
<input id="view.userprofile.form.edtUserID" class="form-control">
</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 class="form-group">
<label id="view.userprofile.form.lblEmail">Email Address:</label>
<input id="view.userprofile.form.edtEmail" class="form-control">
</div>
<div class="custom-control custom-checkbox">
<input type="checkbox" class="custom-control-input" id="view.userprofile.form.chkAdminUser">
<label class="custom-control-label" for="view.userprofile.form.chkAdminUser">Admin User</label>
</div>
<div class="form-group">
<button class="btn btn-primary" id="view.userprofile.form.btnconfirm">Confirm Changes</button>
<button class="btn btn-primary" id="view.userprofile.form.btncancel">Xancel Changes</button>
</div>
<div class="form-group">
<label id="view.userprofile.form.lblresult"></label>
</div>
<div 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>
<label id="view.userprofile.form.lblresult" class="form-text"></label>
</form>
</div>
</div>
</div>
......@@ -6,7 +6,8 @@ uses
System.SysUtils, System.Classes, JS, Web, WEBLib.Graphics, WEBLib.Controls,
WEBLib.Forms, WEBLib.Dialogs, Vcl.Controls, Vcl.StdCtrls, WEBLib.StdCtrls,
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
TFViewUserProfile = class(TWebForm)
......@@ -17,27 +18,18 @@ type
edtUserId: TWebEdit;
edtFullName: TWebEdit;
WebLabel4: TWebLabel;
edtPhone: TWebEdit;
WebLabel5: TWebLabel;
chkAdminUser: TWebCheckBox;
edtEmail: TWebEdit;
WebLabel6: TWebLabel;
btnConfirm: TWebButton;
lblResult: TWebLabel;
XDataWebClient1: TXDataWebClient;
WebButton1: TWebButton;
pnlMessage: TWebPanel;
lblMessage: TWebLabel;
btnCloseNotification: TWebButton;
btnCancel: TWebButton;
procedure WebFormShow(Sender: TObject);
procedure btnConfirmClick(Sender: TObject);
[async] procedure EditUser();
[async] procedure GetUser();
procedure WebButton1Click(Sender: TObject);
procedure HideNotification();
procedure ShowNotification(Notification: string);
procedure btnCloseNotificationClick(Sender: TObject);
function CheckInputs(): boolean;
procedure btnCancelClick(Sender: TObject);
end;
var
......@@ -47,57 +39,83 @@ implementation
uses
Auth.Service,
XData.Model.Classes;
XData.Model.Classes,
Utils,
View.Main;
{$R *.dfm}
procedure TFViewUserProfile.btnCloseNotificationClick(Sender: TObject);
begin
HideNotification;
end;
procedure TFViewUserProfile.btnConfirmClick(Sender: TObject);
var
resultString: string;
FormEl: TJSHTMLFormElement;
begin
FormEl := TJSHTMLFormElement(document.querySelector('form'));
if not FormEl.checkValidity then
begin
FormEl.classList.add('was-validated');
Exit;
end;
asm
var messageDiv = document.getElementById('view.login.message');
messageDiv.classList.remove('alert-success');
messageDiv.classList.add('alert-danger');
var modal = document.getElementById('confirmation_modal');
var btnCancel = document.getElementById('btn_confirm_cancel');
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;
if CheckInputs() then
begin
EditUser();
end
end;
procedure TFViewUserProfile.EditUser();
[async] procedure TFViewUserProfile.EditUser;
var
xdcResponse: TXDataClientResponse;
responseString: TJSObject;
editOptions: string;
editOptions, resultMsg: string;
begin
if(checkInputs()) then
begin
console.log(edtFullName.Text);
try
editOptions := '&username=' + edtUsername.Text +
'&fullname=' + edtFullName.Text +
'&phonenumber=' + edtPhone.Text +
'&email=' + edtEmail.Text;
xdcResponse := await(XDataWebClient1.RawInvokeAsync('ILookupService.EditUser',
[editOptions]));
responseString := TJSObject(xdcResponse.Result);
asm
var messageDiv = document.getElementById('view.login.message');
messageDiv.classList.remove('alert-danger');
messageDiv.classList.add('alert-success');
end;
ShowNotification(string(responseString['value']));
'&fullname=' + edtFullName.Text +
'&email=' + edtEmail.Text;
xdcResponse := await(XDataWebClient1.RawInvokeAsync('ILookupService.EditUser', [editOptions]));
responseString := TJSObject(xdcResponse.Result);
resultMsg := string(responseString['value']);
Utils.ShowToast(resultMsg);
if resultMsg.ToLower.StartsWith('success:') then
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;
procedure TFViewUserProfile.WebButton1Click(Sender: TObject);
procedure TFViewUserProfile.btnCancelClick(Sender: TObject);
var
xdcResponse: TXDataClientResponse;
userList: TJSObject;
......@@ -105,21 +123,17 @@ var
user: TJSObject;
begin
GetUser();
showNotification('Failure:Changes discarded');
showToast('Failure: Changes discarded');
end;
procedure TFViewUserProfile.WebFormShow(Sender: TObject);
var
xdcResponse: TXDataClientResponse;
userList: TJSObject;
data: TJSArray;
user: TJSObject;
begin
HideNotification;
GetUser();
//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;
procedure TFViewUserProfile.GetUser;
......@@ -129,139 +143,22 @@ var
data: TJSArray;
user: TJSObject;
begin
xdcResponse := await(XDataWebClient1.RawInvokeAsync('ILookupService.GetUsers',
[JS.toString(AuthService.TokenPayload.Properties['user_name'])]));
userList := TJSObject(xdcResponse.Result);
data := TJSArray(userList['data']);
user := TJSObject(data[0]);
edtUsername.Text := string(user['username']);
edtFullName.Text := string(user['full_name']);
edtPhone.Text := string(user['phone_number']);
edtEmail.Text := string(user['email_address']);
edtUserId.Text := string(user['userID']);
chkAdminUser.Checked := boolean(user['admin']);
end;
procedure TFViewUserProfile.HideNotification;
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;
try
xdcResponse := await(XDataWebClient1.RawInvokeAsync('ILookupService.GetUsers',
[JS.toString(AuthService.TokenPayload.Properties['user_name'])]));
userList := TJSObject(xdcResponse.Result);
data := TJSArray(userList['data']);
user := TJSObject(data[0]);
edtUsername.Text := string(user['username']);
edtFullName.Text := string(user['full_name']);
edtEmail.Text := string(user['email_address']);
edtUserId.Text := string(user['userID']);
chkAdminUser.Checked := boolean(user['admin']);
except
on E: EXDataClientRequestException do
Utils.ShowErrorModal('Could not retrieve users: ' + E.ErrorResult.ErrorMessage);
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.
......@@ -45,36 +45,6 @@ object FViewUsers: TFViewUsers
WidthPercent = 100.000000000000000000
OnClick = btnConfirmDeleteClick
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
Connection = DMConnection.ApiConnection
Left = 462
......
......@@ -5,10 +5,6 @@
<div class="col-12 col-md-8">
<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>
</div>
......
......@@ -16,9 +16,6 @@ type
btnAddUser: TWebButton;
WebDataSource1: TWebDataSource;
btnConfirmDelete: TWebButton;
pnlMessage: TWebPanel;
lblMessage: TWebLabel;
btnCloseNotification: TWebButton;
XDataWebDataSet1userID: TStringField;
XDataWebDataSet1username: TStringField;
XDataWebDataSet1full_name: TStringField;
......@@ -34,7 +31,6 @@ type
//AField: TField; AValue: string; AElement: TJSHTMLElementRecord);
procedure btnConfirmDeleteClick(Sender: TObject);
procedure btnAddUserClick(Sender: TObject);
procedure btnCloseNotificationClick(Sender: TObject);
//procedure btnApplyClick(Sender: TObject);
//procedure btnSearchClick(Sender: TObject);
private
......@@ -46,8 +42,6 @@ type
[async] procedure DelUser(username: string);
[async] procedure EditUser(row: TJSHTMLElement);
[async] procedure GetUsers(searchOptions: string);
procedure HideNotification;
procedure ShowNotification(Notification: string);
procedure AddRowToTable(UserID, Username, Password, Full_Name, Status,
Email, AType, PID, QBID: string; Rights: integer);
//[async] procedure addUser();
......@@ -98,10 +92,7 @@ begin
PageSize := 10;
GetUsers('');
if Info <> '' then
ShowNotification(Info)
else
HideNotification();
ShowToast(Info)
end;
procedure TFViewUsers.DelUser(username: string);
......@@ -112,7 +103,7 @@ begin
xdcResponse := await(XDataWebClient1.RawInvokeAsync('ILookupService.DelUser',
[username]));
responseString := TJSObject(xdcResponse.Result);
ShowNotification(string(responseString['value']));
ShowToast(string(responseString['value']));
getUsers('');
end;
......@@ -449,7 +440,7 @@ begin
Cell := TJSHTMLElement(document.createElement('td'));
Cell.setAttribute('data-label', 'Edit');
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.addEventListener('click', procedure(Event: TJSMouseEvent)
begin
......@@ -468,43 +459,6 @@ begin
FViewMain.EditUser('Add', '', '', '', '', '', '', '', '', '');
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);
begin
......
......@@ -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>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
<meta content="width=device-width, initial-scale=1" name="viewport"/>
<noscript>Your browser does not support JavaScript!</noscript>
<link href="data:;base64,=" rel="icon"/>
<title>Web KG Orders</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://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 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/spinner.css" rel="stylesheet" type="text/css">
<script src="$(ProjectName).js" type="text/javascript"></script>
<body>
</body>
<script type="text/javascript">rtl.run();</script>
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
<meta content="width=device-width, initial-scale=1" name="viewport"/>
<noscript>Your browser does not support JavaScript!</noscript>
<link href="data:;base64,=" rel="icon"/>
<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://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="css/app.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>
</head>
<body>
</body>
<script type="text/javascript">rtl.run();</script>
</html>
......@@ -69,9 +69,13 @@
<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>
<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>
<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 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>
......@@ -90,13 +94,14 @@
<DCC_RemoteDebug>false</DCC_RemoteDebug>
<VerInfo_IncludeVerInfo>true</VerInfo_IncludeVerInfo>
<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>
<VerInfo_MajorVer>0</VerInfo_MajorVer>
<VerInfo_MinorVer>9</VerInfo_MinorVer>
<TMSWebSingleInstance>1</TMSWebSingleInstance>
<TMSUseJSDebugger>2</TMSUseJSDebugger>
<VerInfo_Release>2</VerInfo_Release>
<VerInfo_Release>5</VerInfo_Release>
<TMSWebBrowser>3</TMSWebBrowser>
</PropertyGroup>
<PropertyGroup Condition="'$(Cfg_2)'!=''">
<DCC_LocalDebugSymbols>false</DCC_LocalDebugSymbols>
......@@ -107,11 +112,13 @@
<TMSWebDefines>RELEASE</TMSWebDefines>
</PropertyGroup>
<PropertyGroup Condition="'$(Cfg_2_Win32)'!=''">
<VerInfo_Build>8</VerInfo_Build>
<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_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_IncludeVerInfo>true</VerInfo_IncludeVerInfo>
<VerInfo_Locale>1033</VerInfo_Locale>
<AppDPIAwarenessMode>PerMonitor</AppDPIAwarenessMode>
<VerInfo_MajorVer>0</VerInfo_MajorVer>
<VerInfo_MinorVer>9</VerInfo_MinorVer>
<VerInfo_Release>6</VerInfo_Release>
</PropertyGroup>
<ItemGroup>
<DelphiCompile Include="$(MainSource)">
......
......@@ -132,6 +132,7 @@ begin
JWT.Claims.SetClaimOfType<string>('user_email', userEmail);
JWT.Claims.SetClaimOfType<string>('user_qb_id', userQBID);
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);
finally
......
......@@ -110,7 +110,7 @@ begin
OrdersDB.UniQuery1.SQL.Text := SQL;
OrdersDB.UniQuery1.ExecSQL;
result := TJSONObject.Create;
result.AddPair('status', 'Success:Address Successfully Deleted');
result.AddPair('status', 'Success: Address Successfully Deleted');
SQL := 'select * FROM customers c LEFT JOIN customers_ship s ON c.CUSTOMER_ID = s.customer_id WHERE c.CUSTOMER_ID = ' + CustomerID;
doQuery(ordersDB.UniQuery1, SQL);
ADDRESS_LIST := TJSONArray.Create;
......@@ -132,6 +132,7 @@ begin
TXDataOperationContext.Current.Handler.ManagedObjects.Add(Result);
end;
function TLookupService.GetCustomers: TCustomerList;
// Retrieves a list of customers and sends it to the client in object form.
// The object contains the ID, Name, Short Name, and the shipping address.
......@@ -254,11 +255,9 @@ end;
function TLookupService.GenerateOrderListPDF(searchOptions: string): string;
// Generates a report pdf based on the last search (if any) Linked to rOrders
// file which does most of the work.
var
SQL: string;
rptOrderList: TrptOrderList; // Local instance of rptOrders
rptOrderList: TrptOrderList;
CompanyID, CompanyName: string;
params: TStringList;
begin
......@@ -267,9 +266,16 @@ begin
try
params := TStringList.Create;
params.StrictDelimiter := true;
// parse the searchOptions
params.Delimiter := '&';
params.DelimitedText := searchOptions;
// Strip paging if this is a PDF export
if params.Values['forPDF'] = 'true' then
begin
params.Values['pagesize'] := '';
params.Values['pagenumber'] := '';
end;
companyID := params.Values['companyID'];
if companyID <> '' then
begin
......@@ -280,11 +286,10 @@ begin
else
CompanyName := '';
SQL := GenerateOrdersSQL(searchOptions).SQL;
SQL := GenerateOrdersSQL(params.DelimitedText).SQL;
result := rptOrderList.PrepareReport(SQL, CompanyName);
// Optionally, log success
Logger.log(5, 'PDF Report successfully generated for searchOptions: ' + searchOptions);
Logger.log(5, 'PDF Report successfully generated for searchOptions: ' + params.DelimitedText);
except
on E: Exception do
raise EXDataHttpException.Create(500, 'Failed to generate PDF: ' + E.Message);
......@@ -295,6 +300,7 @@ begin
end;
function TLookupService.AddShippingAddress(AddressInfo: string): TJSONObject;
var
JSONData: TJSONObject;
......@@ -356,10 +362,10 @@ begin
if mode = 'ADD' then
begin
msg := 'Success:Shipping Address Successfully Added';
msg := 'Success: Shipping Address Successfully Added';
end
else
msg := 'Success:Shipping Address Successfully Edited';
msg := 'Success: Shipping Address Successfully Edited';
// Sends the updated Address List Back.
......@@ -485,9 +491,9 @@ begin
ordersDB.UniQuery1.Post;
if mode = 'ADD' then
msg := 'Success:Customer Successfully Added'
msg := 'Success: Customer Successfully Added'
else
msg := 'Success:Customer Successfully Edited';
msg := 'Success: Customer Successfully Edited';
Result := TJSONObject.Create.AddPair('status', msg);
......@@ -720,104 +726,81 @@ function TLookupService.generateOrdersSQL(searchOptions: string): TSQLQuery;
// searchOptions: search information sent form client to be parsed.
var
params: TStringList;
PageNum: integer;
PageSize: integer;
OrderBy: string;
offset: string;
limit: string;
SQL: string;
whereSQL: string;
orderBySQL: string;
OrderID: string;
CompanyID: string;
JobName: string;
orderType: string;
// These variables apply to the first status sent from the client
status1: TStatusSearchInfo;
// These variables apply to the second status sent from the client
status2: TStatusSearchInfo;
PageNum, PageSize: integer;
OrderBy, offset, limit: string;
SQL, whereSQL, orderBySQL: string;
OrderID, CompanyID, JobName, orderType: string;
status1, status2: TStatusSearchInfo;
ForPDF: Boolean;
begin
result := TSQLQuery.Create;
params := TStringList.Create;
params.StrictDelimiter := true;
// parse the searchOptions
params.Delimiter := '&';
params.DelimitedText := searchOptions;
orderBySQL := '';
PageNum := StrToInt(params.Values['pagenumber']);
PageSize := StrToInt(params.Values['pagesize']);
ForPDF := SameText(params.Values['forPDF'], 'true');
if not ForPDF then
begin
PageNum := StrToIntDef(params.Values['pagenumber'], 1);
PageSize := StrToIntDef(params.Values['pagesize'], 500);
offset := IntToStr((PageNum - 1) * PageSize);
limit := IntToStr(PageSize);
end;
OrderBy := params.Values['orderby'];
orderType := params.Values['orderType'].ToLower();
OrderID := params.Values['orderID'];
companyID := params.Values['companyID'];
jobName := params.Values['jobName'];
// Search infomation for first status type
status1 := createStatusSearchInfo(params, '1');
// Search Information for second status type
status2 := createStatusSearchInfo(params, '2');
offset := IntToStr((PageNum - 1) * PageSize);
limit := IntToStr(PageSize);
SQL := 'SELECT o.ORDER_ID, c.SHORT_NAME, o.LOCATION AS Loc, c.NAME AS COMPANY_NAME, o.JOB_NAME, o.ORDER_TYPE, ';
SQL := 'SELECT o.ORDER_ID, c.SHORT_NAME, o.LOCATION AS Loc, c.NAME AS COMPANY_NAME, o.JOB_NAME, o.ORDER_TYPE, ' +
generateSubquery('PROOF') +
generateSubquery('ART') +
generateSubquery('PLATE') +
generateSubquery('MOUNT') +
generateSubquery('SHIP');
// Generate the subqueries that get the Status Dates(Due and Done)
SQL := SQL + generateSubquery('PROOF');
SQL := SQL + generateSubquery('ART');
SQL := SQL + generateSubquery('PLATE');
SQL := SQL + generateSubquery('MOUNT');
SQL := SQL + generateSubquery('SHIP');
whereSQL := ' FROM orders o JOIN customers c ON c.CUSTOMER_ID = o.COMPANY_ID ' +
'LEFT JOIN qb_sales_orders qb ON qb.ORDER_ID = o.ORDER_ID ' +
'LEFT JOIN corrugated_plate_orders cpo ON o.ORDER_ID = cpo.ORDER_ID ' +
'LEFT JOIN web_plate_orders wpo ON o.ORDER_ID = wpo.ORDER_ID ' +
'LEFT JOIN cutting_die_orders cdo ON o.ORDER_ID = cdo.ORDER_ID WHERE 0 = 0';
// Generate the Where SQL based on if there is a status filter applied or not
whereSQL := 'from orders o join customers c on ' +
'c.CUSTOMER_ID = o.COMPANY_ID left join qb_sales_orders qb on qb.ORDER_ID = o.ORDER_ID ' +
' LEFT JOIN corrugated_plate_orders cpo ON o.ORDER_ID = cpo.ORDER_ID ' +
'LEFT JOIN web_plate_orders wpo ON o.ORDER_ID = wpo.ORDER_ID ' +
'LEFT JOIN cutting_die_orders cdo ON o.ORDER_ID = cdo.ORDER_ID where 0 = 0';
if ( ( status1.filterType <> '' ) and ( status1.filterType <> 'NONE' ) ) then
if (status1.filterType <> '') and (status1.filterType <> 'NONE') then
whereSQL := whereSQL + generateStatusWhereSQL(status1);
if ( (status2.filterType <> '' ) and ( status2.filterType <> 'NONE' ) ) then
if (status2.filterType <> '') and (status2.filterType <> 'NONE') then
whereSQL := whereSQL + generateStatusWhereSQL(status2);
if ( ( orderType <> '' ) and ( orderType <> 'any' ) ) then
if (orderType <> '') and (orderType <> 'any') then
begin
if ( orderType <> 'cutting die') then
whereSQL := whereSQL + ' AND o.ORDER_TYPE = ' + quotedStr(orderType + '_plate')
if (orderType <> 'cutting die') then
whereSQL := whereSQL + ' AND o.ORDER_TYPE = ' + QuotedStr(orderType + '_plate')
else
whereSQL := whereSQL + ' AND o.ORDER_TYPE = ' + quotedStr('cutting_die');
whereSQL := whereSQL + ' AND o.ORDER_TYPE = ' + QuotedStr('cutting_die');
end;
if orderID <> '' then
whereSQL := whereSQL + ' AND o.ORDER_ID = ' + orderID;
if OrderID <> '' then
whereSQL := whereSQL + ' AND o.ORDER_ID = ' + OrderID;
if companyID <> '' then
whereSQL := whereSQL + ' AND c.CUSTOMER_ID = ' + companyID;
if jobName <> '' then
whereSQL := whereSQL + ' AND o.JOB_NAME LIKE ' + quotedStr('%' + jobName + '%');
whereSQL := whereSQL + ' AND o.JOB_NAME LIKE ' + QuotedStr('%' + jobName + '%');
orderBySQL := 'ORDER BY ' + OrderBy;
orderBySQL := ' ORDER BY ' + OrderBy;
SQL := SQL + 'o.PRICE, qb.QB_REF_NUM, ' +
'coalesce( cpo.staff_fields_po_number, wpo.staff_fields_po_number, cdo.staff_fields_po_number ) AS po_number, ' +
'coalesce( cpo.staff_fields_quickbooks_item, wpo.staff_fields_quickbooks_item, cdo.staff_fields_quickbooks_item ) AS quickbooks_item, ' +
'coalesce( cpo.staff_fields_order_date, wpo.staff_fields_order_date, cdo.staff_fields_order_date ) AS ORDER_DATE ' +
whereSQL + ' ' + orderBySQL + ' LIMIT ' + limit + ' OFFSET ' + offset;
SQL := SQL + ' o.PRICE, qb.QB_REF_NUM, ' +
'COALESCE(cpo.staff_fields_po_number, wpo.staff_fields_po_number, cdo.staff_fields_po_number) AS po_number, ' +
'COALESCE(cpo.staff_fields_quickbooks_item, wpo.staff_fields_quickbooks_item, cdo.staff_fields_quickbooks_item) AS quickbooks_item, ' +
'COALESCE(cpo.staff_fields_order_date, wpo.staff_fields_order_date, cdo.staff_fields_order_date) AS ORDER_DATE ';
if not ForPDF then
SQL := SQL + whereSQL + orderBySQL + ' LIMIT ' + limit + ' OFFSET ' + offset
else
SQL := SQL + whereSQL + orderBySQL;
// send the SQL and whereSQL back. whereSQL is needed to get the total count.
// probably a way to getthe TotalCount in original SQL but it was giving me issues
result.SQL := SQL;
result.whereSQL := whereSQL;
end;
......@@ -1426,22 +1409,32 @@ begin
end;
function TLookupService.GetUsers(searchOptions: string): TUserList;
// Gets a list of all users for the user edit page.
// searchOptions: username of a specific user otherwise empty.
// TODO: change SQL to hide passwords instead of storing them in plain text.
// Returns all users, or one specific user when searchOptions <> ''.
// Uses parameterised SQL and the real column name USER_NAME.
var
SQL: string;
user: TUserItem;
begin
try
// Prepare and open the query
ordersDB.UniQuery1.Close;
if searchOptions = '' then
SQL := 'select * from users order by NAME ASC'
begin
ordersDB.UniQuery1.SQL.Text :=
'SELECT * FROM users ORDER BY NAME ASC';
end
else
SQL := 'select * from users where username=' + quotedStr(searchOptions);
doQuery(ordersDB.UniQuery1, SQL);
begin
ordersDB.UniQuery1.SQL.Text :=
'SELECT * FROM users WHERE USER_NAME = :uname';
ordersDB.UniQuery1.ParamByName('uname').AsString := searchOptions;
end;
ordersDB.UniQuery1.Open;
Result := TUserList.Create;
Result.data := TList<TUserItem>.Create;
// Build result list
Result := TUserList.Create;
Result.data := TList<TUserItem>.Create;
TXDataOperationContext.Current.Handler.ManagedObjects.Add(Result.data);
while not ordersDB.UniQuery1.Eof do
......@@ -1449,32 +1442,42 @@ begin
user := TUserItem.Create;
TXDataOperationContext.Current.Handler.ManagedObjects.Add(user);
Result.data.Add(user);
user.userID := ordersDB.UniQuery1.FieldByName('USER_ID').AsString;
user.username := ordersDB.UniQuery1.FieldByName('USER_NAME').AsString;
user.password := ordersDB.UniQuery1.FieldByName('PASSWORD').AsString;
user.full_name := ordersDB.UniQuery1.FieldByName('NAME').AsString;
user.status := ordersDB.UniQuery1.FieldByName('STATUS').AsString;
user.userID := ordersDB.UniQuery1.FieldByName('USER_ID').AsString;
user.username := ordersDB.UniQuery1.FieldByName('USER_NAME').AsString;
user.password := ordersDB.UniQuery1.FieldByName('PASSWORD').AsString;
user.full_name := ordersDB.UniQuery1.FieldByName('NAME').AsString;
user.status := ordersDB.UniQuery1.FieldByName('STATUS').AsString;
user.email_address := ordersDB.UniQuery1.FieldByName('EMAIL').AsString;
user.AType := ordersDB.UniQuery1.FieldByName('ACCESS_TYPE').AsString;
user.rights := ordersDB.UniQuery1.FieldByName('SYSTEM_RIGHTS').AsInteger;
user.AType := ordersDB.UniQuery1.FieldByName('ACCESS_TYPE').AsString;
user.rights := ordersDB.UniQuery1.FieldByName('SYSTEM_RIGHTS').AsInteger;
user.perspectiveID := ordersDB.UniQuery1.FieldByName('PERSPECTIVE_ID').AsString;
user.QBID := ordersDB.UniQuery1.FieldByName('QB_ID').AsString;
user.QBID := ordersDB.UniQuery1.FieldByName('QB_ID').AsString;
ordersDB.UniQuery1.Next;
end;
ordersDB.UniQuery1.Close;
SQL := 'select count(*) as total_count from users';
doQuery(ordersDB.UniQuery1, SQL);
// Get total-row count (keeps old behaviour)
ordersDB.UniQuery1.SQL.Text :=
'SELECT COUNT(*) AS total_count FROM users';
ordersDB.UniQuery1.Open;
Result.count := ordersDB.UniQuery1.FieldByName('total_count').AsInteger;
ordersDB.UniQuery1.Close;
except
on E: Exception do
begin
raise EXDataHttpException.Create(500, 'Unable to retrieve users: ' + E.Message);
ordersDB.UniQuery1.Close;
raise EXDataHttpException.Create(
500,
'Unable to retrieve users: ' + E.Message
);
end;
end;
end;
function TLookupService.EditUser(const editOptions: string): string;
// Edits the user.
// editOptions: all user information that will be changed.
......@@ -1558,7 +1561,7 @@ begin
end;}
ordersDB.UniQuery1.Post;
Result := 'Success: Edit Successful';
Result := 'Success: User Successfully Edited';
end;
ordersDB.UniQuery1.Close;
end;
......@@ -1663,7 +1666,7 @@ begin
else
TDateTimeField(Field).AsDateTime := StrToDate(Pair.JsonValue.Value);
end
else if Pair.JsonValue.Value <> '' then
else
Field.AsString := Pair.JsonValue.Value;
end;
end;
......@@ -1686,9 +1689,9 @@ begin
addToRevisionsTable(intToStr(ORDER_ID), 'corrugated_plate_orders_revisions', JSONData);
if mode = 'ADD' then
msg := 'Success:Order Successfully Added'
msg := 'Success: Order Successfully Added'
else
msg := 'Success:Order Successfully Edited';
msg := 'Success: Order Successfully Edited';
Result := TJSONObject.Create.AddPair('status', msg);
Result.AddPair('OrderID', ORDER_ID);
......@@ -1703,7 +1706,6 @@ begin
end;
function TLookupService.AddStatusSchedule(StatusType: string; order: TJSONObject; ORDER_ID: integer): string;
// Adds/edits orders_status_schedule table.
// StatusType: name of the status getting added to the schedule.
......@@ -1893,9 +1895,9 @@ begin
end;
function TLookupService.AddUser(userInfo: string): string;
// Adds a user to the database
// userInfo - user information being added
var
user: string;
password: string;
......@@ -1908,65 +1910,68 @@ var
QB: string;
SQL: string;
dateCreated: TDateTime;
hashString: string;
hashPW: string;
rightsInt: Integer;
params: TStringList;
begin
try
params := TStringList.Create;
params.StrictDelimiter := true;
// parse the searchOptions
params.StrictDelimiter := True;
params.Delimiter := '&';
params.DelimitedText := userInfo;
dateCreated := now;
user := params.Values['username'];
password := params.Values['password'];
full_name := params.Values['fullname'];
status := params.Values['status'];
email := params.Values['email'];
access := params.Values['access'];
rights := params.Values['rights'];
dateCreated := Now;
user := params.Values['username'];
password := params.Values['password'];
full_name := params.Values['fullname'];
status := params.Values['status'];
email := params.Values['email'];
access := params.Values['access'];
rights := params.Values['rights'];
perspective := params.Values['perspective'];
QB := params.Values['QB'];
//newUser := params.Values['newuser'];
//hashString := DateTimeToStr(dateCreated) + params.Values['password'];
//hashPW := THashSHA2.GetHashString(hashString, THashSHA2.TSHA2Version.SHA512).ToUpper;
SQL := 'select * from users where USER_NAME = ' + QuotedStr(params.Values['username'].toLower);
QB := params.Values['QB'];
SQL := 'SELECT * FROM users WHERE USER_NAME = ' + QuotedStr(user.ToLower);
ordersDB.UniQuery1.Close;
ordersDB.UniQuery1.SQL.Text := SQL;
ordersDB.UniQuery1.Open;
if ordersDB.UniQuery1.IsEmpty then
begin
ordersDB.UniQuery1.Insert;
ordersDB.UniQuery1.FieldByName('USER_NAME').AsString := user;
ordersDB.UniQuery1.FieldByName('PASSWORD').AsString := password;
//THashSHA2.GetHashString(hashString, THashSHA2.TSHA2Version.SHA512).ToUpper;
//ordersDB.UniQuery1.FieldByName('date_created').AsString := DateTimeToStr(dateCreated);
ordersDB.UniQuery1.FieldByName('NAME').AsString := full_name;
ordersDB.UniQuery1.FieldByName('PASSWORD').AsString := password;
ordersDB.UniQuery1.FieldByName('NAME').AsString := full_name;
if( StrToBool(status) ) then
if StrToBoolDef(status, False) then
ordersDB.UniQuery1.FieldByName('STATUS').AsString := 'ACTIVE'
else
ordersDB.UniQuery1.FieldByName('STATUS').AsString := 'INACTIVE';
ordersDB.UniQuery1.FieldByName('EMAIL').AsString := email;
ordersDB.UniQuery1.FieldByName('ACCESS_TYPE').AsString := Access;
ordersDB.UniQuery1.FieldByName('SYSTEM_RIGHTS').AsInteger := StrToInt(rights);
ordersDB.UniQuery1.FieldByName('EMAIL').AsString := email;
ordersDB.UniQuery1.FieldByName('ACCESS_TYPE').AsString := access;
if not TryStrToInt(rights, rightsInt) then
rightsInt := 0;
ordersDB.UniQuery1.FieldByName('SYSTEM_RIGHTS').AsInteger := rightsInt;
ordersDB.UniQuery1.FieldByName('PERSPECTIVE_ID').AsString := perspective;
ordersDB.UniQuery1.FieldByName('QB_ID').AsString := QB;
ordersDB.UniQuery1.FieldByName('QB_ID').AsString := QB;
ordersDB.UniQuery1.Post;
Result := 'Success:User successfully added';
Result := 'Success: User successfully added';
end
else
Result := 'Failure:Username already taken';
Result := 'Failure: Username already taken';
except
on E: Exception do
raise EXDataHttpException.Create(500, 'AddUser failed: ' + E.Message);
end;
end;
function TLookupService.AddItem(itemInfo: string): TJSONObject;
// Adds an item to the database
// itemInfo: item info to add to database
......@@ -2005,7 +2010,7 @@ begin
ordersDB.UniQuery1.FieldByName('status').AsString := 'INACTIVE';
ordersDB.UniQuery1.Post;
Result.AddPair('msg', 'Success:Item successfully added');
Result.AddPair('msg', 'Success: Item successfully added');
end
else
Result.AddPair('msg', 'Failure: Item already exists');
......@@ -2100,7 +2105,7 @@ begin
else
TDateTimeField(Field).AsDateTime := StrToDate(Pair.JsonValue.Value);
end
else if Pair.JsonValue.Value <> '' then
else
Field.AsString := Pair.JsonValue.Value;
end;
end;
......@@ -2122,9 +2127,9 @@ begin
AddToRevisionsTable(IntToStr(ORDER_ID), 'web_plate_orders_revisions', JSONData);
if mode = 'ADD' then
msg := 'Success:Order Successfully Added'
msg := 'Success: Order Successfully Added'
else
msg := 'Success:Order Successfully Edited';
msg := 'Success: Order Successfully Edited';
Result := TJSONObject.Create.AddPair('status', msg);
Result.AddPair('OrderID', ORDER_ID);
......@@ -2195,7 +2200,7 @@ begin
else
TDateTimeField(Field).AsDateTime := StrToDate(Pair.JsonValue.Value);
end
else if Pair.JsonValue.Value <> '' then
else
Field.AsString := Pair.JsonValue.Value;
end;
end;
......@@ -2213,9 +2218,9 @@ begin
AddToRevisionsTable(IntToStr(ORDER_ID), 'cutting_die_orders_revisions', JSONData);
if mode = 'ADD' then
msg := 'Success:Order Successfully Added'
msg := 'Success: Order Successfully Added'
else
msg := 'Success:Order Successfully Edited';
msg := 'Success: Order Successfully Edited';
Result := TJSONObject.Create.AddPair('status', msg);
Result.AddPair('OrderID', ORDER_ID);
......@@ -2424,6 +2429,7 @@ begin
ordersDB.UniQuery1.Post;
end;
function TLookupService.getQBCustomers: TJSONArray;
var
iniFile: TIniFile;
......@@ -2566,6 +2572,7 @@ begin
end;
end;
function TLookupService.GetQBItems: TJSONArray;
var
restClient: TRESTClient;
......@@ -2752,6 +2759,7 @@ begin
end;
end;
procedure TLookupService.SaveTokens(AccessToken, RefreshToken: string);
var
f: TStringList;
......@@ -2845,9 +2853,9 @@ begin
OrdersDB.UniQuery1.Post;
if mode = 'ADD' then
msg := 'Success:Customer Successfully Added'
msg := 'Success: Customer Successfully Added'
else
msg := 'Success:Customer Successfully Edited';
msg := 'Success: Customer Successfully Edited';
Result := TJSONObject.Create;
Result.AddPair('status', msg);
......
......@@ -116,8 +116,8 @@
<DCC_UnitSearchPath>C:\RADTOOLS\FastMM4;$(DCC_UnitSearchPath)</DCC_UnitSearchPath>
<VerInfo_MajorVer>0</VerInfo_MajorVer>
<VerInfo_MinorVer>9</VerInfo_MinorVer>
<VerInfo_Release>4</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_Release>6</VerInfo_Release>
<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 Condition="'$(Cfg_1_Win64)'!=''">
<AppDPIAwarenessMode>PerMonitorV2</AppDPIAwarenessMode>
......
[Settings]
MemoLogLevel=3
FileLogLevel=5
webClientVersion=0.9.4
LogFileNum=735
webClientVersion=0.9.6
LogFileNum=756
[Database]
Server=192.168.159.131
Server=192.168.159.151
--Server=192.168.102.130
--Server=192.168.75.133
Database=kg_order_entry
......@@ -17,6 +17,9 @@ Password=emsys01
CompanyID=9341454272655710
ClientID=ABgO14uvjh8XqLud7spQ8lkb98AUpcdA7HbyMJfCAtl65sQ5yy
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
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