Commit 35c58bb8 by Mac Stephens

Merge branch 'mac3'

Version 0.9.7 deployed to server, database updated on dbserver
parents 1a5d0980 6d54266c
object FViewAddCustomer: TFViewAddCustomer
Width = 842
Height = 607
OnShow = WebFormShow
CSSLibrary = cssBootstrap
ElementFont = efCSS
object lblFormState: TWebLabel
Left = 18
Top = 16
Width = 3
Height = 15
ElementID = 'lbl_form_state'
HeightPercent = 100.000000000000000000
WidthPercent = 100.000000000000000000
end
object dtpStartDate: TWebDateTimePicker
Left = 19
Top = 216
......@@ -200,44 +210,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
......@@ -274,7 +246,7 @@ object FViewAddCustomer: TFViewAddCustomer
BorderColor = clSilver
ChildOrder = 11
ElementFont = efCSS
ElementHeaderClassName = 'thead-light sticky-top bg-light'
ElementHeaderClassName = 'thead-light sticky-top bg-light border-light'
ElementPosition = epRelative
ElementTableClassName = 'table table-striped table-hover table-bordered text-sm'
Footer.ButtonActiveElementClassName = 'btn btn-primary'
......@@ -296,6 +268,7 @@ object FViewAddCustomer: TFViewAddCustomer
Header.ListItemElementClassName = 'page-item'
Header.ListLinkElementClassName = 'page-link'
WordWrap = True
OnClickCell = wdbtcAddressesDblClickCell
OnDblClickCell = wdbtcAddressesDblClickCell
Columns = <
item
......@@ -350,6 +323,7 @@ object FViewAddCustomer: TFViewAddCustomer
Width = 121
Height = 22
ChildOrder = 22
EditType = weNumeric
ElementID = 'edtshippingzip'
Enabled = False
HeightPercent = 100.000000000000000000
......@@ -392,7 +366,6 @@ object FViewAddCustomer: TFViewAddCustomer
SelLength = 0
SelStart = 0
WidthPercent = 100.000000000000000000
OnChange = memoAddressBlockChange
end
object btnAdd: TWebButton
Left = 19
......@@ -470,18 +443,6 @@ object FViewAddCustomer: TFViewAddCustomer
WidthPercent = 100.000000000000000000
OnClick = btnShipAddClick
end
object btn_confirm_delete: TWebButton
Left = 725
Top = 433
Width = 96
Height = 25
Caption = 'Delete'
ChildOrder = 82
ElementID = 'btn_confirm_delete'
HeightPercent = 100.000000000000000000
WidthPercent = 100.000000000000000000
OnClick = btn_confirm_deleteClick
end
object edtFirstLine: TWebEdit
Left = 190
Top = 430
......@@ -513,12 +474,12 @@ object FViewAddCustomer: TFViewAddCustomer
Top = 72
end
object WebDataSource1: TWebDataSource
AutoEdit = False
DataSet = XDataWebDataSet1
Left = 532
Top = 126
end
object XDataWebDataSet1: TXDataWebDataSet
AfterEdit = XDataWebDataSet1AfterEdit
Connection = DMConnection.ApiConnection
Left = 426
Top = 132
......@@ -566,12 +527,12 @@ object FViewAddCustomer: TFViewAddCustomer
end
end
object wdsShipTo: TWebDataSource
AutoEdit = False
DataSet = xdwdsShipTo
Left = 698
Top = 128
end
object xdwdsShipTo: TXDataWebDataSet
AfterEdit = xdwdsShipToAfterEdit
Left = 698
Top = 44
object xdwdsShipToADDRESS: TStringField
......@@ -603,6 +564,7 @@ object FViewAddCustomer: TFViewAddCustomer
Top = 42
end
object wdsUsers: TWebDataSource
AutoEdit = False
DataSet = xdwdsUsers
Left = 776
Top = 144
......
......@@ -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.7';
procedure InitApp(SuccessProc: TSuccessProc;
UnauthorizedAccessProc: TUnauthorizedAccessProc);
procedure SetClientConfig(Callback: TVersionCheckCallback);
......
......@@ -3,15 +3,18 @@ unit Utils;
interface
uses
System.Classes, SysUtils, JS, Web, WEBLib.Forms, WEBLib.Toast, DateUtils;
System.Classes, SysUtils, JS, Web, WEBLib.Forms, WEBLib.Toast, DateUtils, WebLib.Dialogs;
procedure ShowStatusMessage(const AMessage, AClass: string; const AElementId: string);
procedure HideStatusMessage(const AElementId: string);
procedure ShowSpinner(SpinnerID: string);
procedure HideSpinner(SpinnerID: 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');
procedure ShowConfirmationModal(msg, leftLabel, rightLabel: string; ConfirmProc: TProc<Boolean>);
// function FormatDollarValue(ValueStr: string): string;
......@@ -65,6 +68,13 @@ begin
SpinnerElement := TJSHTMLElement(document.getElementById(SpinnerID));
if Assigned(SpinnerElement) then
begin
// Move spinner to the <body> if it's not already there
asm
if (SpinnerElement.parentNode !== document.body) {
document.body.appendChild(SpinnerElement);
}
end;
SpinnerElement.classList.remove('d-none');
SpinnerElement.classList.add('d-block');
end;
......@@ -83,6 +93,85 @@ begin
end;
procedure ShowErrorModal(msg: string);
begin
asm
var modal = document.getElementById('main_errormodal');
var label = document.getElementById('main_lblmodal_body');
var reloadBtn = document.getElementById('btn_modal_restart');
if (label) label.innerText = msg;
// Ensure modal is a direct child of <body>
if (modal && modal.parentNode !== document.body) {
document.body.appendChild(modal);
}
// Bind hard reload to button
if (reloadBtn) {
reloadBtn.onclick = function () {
window.location.reload(true); // hard reload, bypass cache
};
}
// Show the Bootstrap modal
var bsModal = new bootstrap.Modal(modal, { keyboard: false });
bsModal.show();
end;
end;
// ShowConfirmationModal displays a two-button modal with custom labels.
// Params:
// - messageText: text shown in the modal body
// - leftButtonText: label for the left button (e.g., "Cancel")
// - rightButtonText: label for the right button (e.g., "Delete")
// - callback: procedure(confirmed: Boolean); confirmed = True if right button clicked
//
// Example:
// ShowConfirmationModal('Delete this?', 'Cancel', 'Delete',
// procedure(confirmed: Boolean)
// begin
// if confirmed then DeleteOrder();
// end);
procedure ShowConfirmationModal(msg, leftLabel, rightLabel: string; ConfirmProc: TProc<Boolean>);
begin
asm
var modal = document.getElementById('main_confirmation_modal');
var body = document.getElementById('main_modal_body');
var btnLeft = document.getElementById('btn_confirm_left');
var btnRight = document.getElementById('btn_confirm_right');
var bsModal;
if (body) body.innerText = msg;
if (btnLeft) btnLeft.innerText = leftLabel;
if (btnRight) btnRight.innerText = rightLabel;
if (modal && modal.parentNode !== document.body) {
document.body.appendChild(modal);
}
btnLeft.onclick = null;
btnRight.onclick = null;
btnLeft.onclick = function () {
bsModal.hide();
ConfirmProc(true); // user confirmed
};
btnRight.onclick = function () {
bsModal.hide();
ConfirmProc(false); // user canceled
};
bsModal = new bootstrap.Modal(modal, { keyboard: false });
bsModal.show();
end;
end;
function CalculateAge(DateOfBirth: TDateTime): Integer;
var
Today, BirthDate: TJSDate;
......@@ -126,6 +215,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 fViewAddItem: TfViewAddItem
Width = 640
Height = 480
OnCreate = WebFormCreate
OnShow = WebFormShow
object WebLabel1: TWebLabel
Left = 8
Top = 81
Width = 95
Height = 15
Caption = 'Search Customers'
HeightPercent = 100.000000000000000000
WidthPercent = 100.000000000000000000
end
object WebLabel3: TWebLabel
Left = 131
Top = 81
Width = 137
Height = 15
Caption = 'Selected Quickbooks Item'
HeightPercent = 100.000000000000000000
WidthPercent = 100.000000000000000000
end
object edtSearch: TWebEdit
Left = 4
Top = 102
Width = 121
Height = 22
ChildOrder = 2
HeightPercent = 100.000000000000000000
WidthPercent = 100.000000000000000000
end
object TMSFNCGrid1: TTMSFNCGrid
Left = 0
Top = 163
Width = 640
Height = 317
Align = alBottom
ParentDoubleBuffered = False
DoubleBuffered = True
TabOrder = 1
DefaultRowHeight = 40.000000000000000000
FixedColumns = 0
ColumnCount = 4
Options.Bands.Enabled = True
Options.ColumnSize.Stretch = True
Options.Editing.CalcFormat = '%g'
Options.Grouping.CalcFormat = '%g'
Options.Grouping.GroupCountFormat = '(%d)'
Options.IO.XMLEncoding = 'ISO-8859-1'
Options.Mouse.ClickMargin = 0
Options.Mouse.ColumnSizeMargin = 6
Options.Mouse.RowSizeMargin = 6
Columns = <
item
BorderWidth = 1
FixedFont.Charset = DEFAULT_CHARSET
FixedFont.Color = 4539717
FixedFont.Height = -11
FixedFont.Name = 'Segoe UI'
FixedFont.Style = [fsBold]
Font.Charset = DEFAULT_CHARSET
Font.Color = 8026746
Font.Height = -11
Font.Name = 'Segoe UI'
Font.Style = []
ID = ''
Width = 90.000000000000000000
end
item
BorderWidth = 1
FixedFont.Charset = DEFAULT_CHARSET
FixedFont.Color = 4539717
FixedFont.Height = -11
FixedFont.Name = 'Segoe UI'
FixedFont.Style = [fsBold]
Font.Charset = DEFAULT_CHARSET
Font.Color = 8026746
Font.Height = -11
Font.Name = 'Segoe UI'
Font.Style = []
ID = ''
Width = 150.000000000000000000
end
item
BorderWidth = 1
FixedFont.Charset = DEFAULT_CHARSET
FixedFont.Color = 4539717
FixedFont.Height = -11
FixedFont.Name = 'Segoe UI'
FixedFont.Style = [fsBold]
Font.Charset = DEFAULT_CHARSET
Font.Color = 8026746
Font.Height = -11
Font.Name = 'Segoe UI'
Font.Style = []
ID = ''
Width = 200.000000000000000000
end
item
BorderWidth = 1
FixedFont.Charset = DEFAULT_CHARSET
FixedFont.Color = 4539717
FixedFont.Height = -11
FixedFont.Name = 'Segoe UI'
FixedFont.Style = [fsBold]
Font.Charset = DEFAULT_CHARSET
Font.Color = 8026746
Font.Height = -11
Font.Name = 'Segoe UI'
Font.Style = []
ID = ''
Width = 181.000000000000000000
end
item
BorderWidth = 1
FixedFont.Charset = DEFAULT_CHARSET
FixedFont.Color = 4539717
FixedFont.Height = -11
FixedFont.Name = 'Segoe UI'
FixedFont.Style = [fsBold]
Font.Charset = DEFAULT_CHARSET
Font.Color = 8026746
Font.Height = -11
Font.Name = 'Segoe UI'
Font.Style = []
ID = ''
Width = 90.000000000000000000
end>
DefaultFont.Charset = DEFAULT_CHARSET
DefaultFont.Color = clWindowText
DefaultFont.Height = -11
DefaultFont.Name = 'Segoe UI'
DefaultFont.Style = []
TopRow = 1
Appearance.FixedLayout.Fill.Color = 16380654
Appearance.FixedLayout.Font.Charset = DEFAULT_CHARSET
Appearance.FixedLayout.Font.Color = 4539717
Appearance.FixedLayout.Font.Height = -13
Appearance.FixedLayout.Font.Name = 'Segoe UI'
Appearance.FixedLayout.Font.Style = [fsBold]
Appearance.NormalLayout.Fill.Color = 16578806
Appearance.NormalLayout.Font.Charset = DEFAULT_CHARSET
Appearance.NormalLayout.Font.Color = 8026746
Appearance.NormalLayout.Font.Height = -11
Appearance.NormalLayout.Font.Name = 'Segoe UI'
Appearance.NormalLayout.Font.Style = []
Appearance.GroupLayout.Fill.Color = 12817262
Appearance.GroupLayout.Font.Charset = DEFAULT_CHARSET
Appearance.GroupLayout.Font.Color = clBlack
Appearance.GroupLayout.Font.Height = -11
Appearance.GroupLayout.Font.Name = 'Segoe UI'
Appearance.GroupLayout.Font.Style = []
Appearance.SummaryLayout.Fill.Color = 14009785
Appearance.SummaryLayout.Font.Charset = DEFAULT_CHARSET
Appearance.SummaryLayout.Font.Color = clBlack
Appearance.SummaryLayout.Font.Height = -11
Appearance.SummaryLayout.Font.Name = 'Segoe UI'
Appearance.SummaryLayout.Font.Style = []
Appearance.SelectedLayout.Fill.Color = 16441019
Appearance.SelectedLayout.Font.Charset = DEFAULT_CHARSET
Appearance.SelectedLayout.Font.Color = 4539717
Appearance.SelectedLayout.Font.Height = -11
Appearance.SelectedLayout.Font.Name = 'Segoe UI'
Appearance.SelectedLayout.Font.Style = []
Appearance.FocusedLayout.Fill.Color = 16039284
Appearance.FocusedLayout.Font.Charset = DEFAULT_CHARSET
Appearance.FocusedLayout.Font.Color = 4539717
Appearance.FocusedLayout.Font.Height = -11
Appearance.FocusedLayout.Font.Name = 'Segoe UI'
Appearance.FocusedLayout.Font.Style = []
Appearance.FixedSelectedLayout.Fill.Color = clLightsteelblue
Appearance.FixedSelectedLayout.Font.Charset = DEFAULT_CHARSET
Appearance.FixedSelectedLayout.Font.Color = clBlack
Appearance.FixedSelectedLayout.Font.Height = -11
Appearance.FixedSelectedLayout.Font.Name = 'Segoe UI'
Appearance.FixedSelectedLayout.Font.Style = []
Appearance.BandLayout.Fill.Color = 16711679
Appearance.BandLayout.Font.Charset = DEFAULT_CHARSET
Appearance.BandLayout.Font.Color = 8026746
Appearance.BandLayout.Font.Height = -11
Appearance.BandLayout.Font.Name = 'Segoe UI'
Appearance.BandLayout.Font.Style = []
Appearance.ProgressLayout.Format = '%.0f%%'
LeftCol = 0
ScrollMode = scmItemScrolling
DesignTimeSampleData = True
OnCellClick = TMSFNCGrid1CellClick
end
object btnCancel: TWebButton
Left = 544
Top = 101
Width = 96
Height = 25
Caption = 'Cancel'
ChildOrder = 5
HeightPercent = 100.000000000000000000
WidthPercent = 100.000000000000000000
OnClick = btnCancelClick
end
object btnConfirm: TWebButton
Left = 446
Top = 101
Width = 96
Height = 25
Caption = 'Select'
ChildOrder = 5
HeightPercent = 100.000000000000000000
WidthPercent = 100.000000000000000000
OnClick = btnConfirmClick
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 = 131
Top = 102
Width = 142
Height = 22
ChildOrder = 1
Enabled = False
HeightPercent = 100.000000000000000000
WidthPercent = 100.000000000000000000
end
object XDataWebClient1: TXDataWebClient
Connection = DMConnection.ApiConnection
Left = 612
Top = 47
end
object xdwdsCustomers: TXDataWebDataSet
Connection = DMConnection.ApiConnection
Left = 166
Top = 129
object xdwdsCustomersqb_items_id: TStringField
FieldName = 'qb_items_id'
end
object xdwdsCustomersqb_item_name: TStringField
FieldName = 'qb_item_name'
end
object xdwdsCustomersitem_desc: TStringField
FieldName = 'item_desc'
end
object xdwdsCustomersstatus: TStringField
FieldName = 'status'
end
object xdwdsCustomersqb_items_qb_id: TStringField
FieldName = 'qb_items_qb_id'
end
end
object wdsCustomers: TWebDataSource
DataSet = xdwdsCustomers
Left = 104
Top = 135
end
end
<html>
<head>
<meta http-equiv="Content-type" content="text/html; charset=utf-8" />
<title>TMS Web Project</title>
<style>
</style>
</head>
<body>
</body>
</html>
\ No newline at end of file
unit View.AddItem;
interface
uses
System.SysUtils, System.Generics.Collections, System.Classes, JS, Web, WEBLib.Graphics, WEBLib.Controls,
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, VCL.TMSFNCTypes, VCL.TMSFNCUtils,
VCL.TMSFNCGraphics, VCL.TMSFNCGraphicsTypes, VCL.TMSFNCGridCell,
VCL.TMSFNCGridOptions, VCL.TMSFNCCustomControl, VCL.TMSFNCCustomScrollControl,
VCL.TMSFNCGridData, VCL.TMSFNCCustomGrid, VCL.TMSFNCGrid, Utils;
type
TfViewAddItem = class(TWebForm)
WebLabel1: TWebLabel;
WebLabel3: TWebLabel;
edtSearch: TWebEdit;
TMSFNCGrid1: TTMSFNCGrid;
btnCancel: TWebButton;
btnConfirm: TWebButton;
edtNotification: TWebEdit;
edtName: TWebEdit;
XDataWebClient1: TXDataWebClient;
xdwdsCustomers: TXDataWebDataSet;
wdsCustomers: TWebDataSource;
xdwdsCustomersqb_items_id: TStringField;
xdwdsCustomersqb_item_name: TStringField;
xdwdsCustomersitem_desc: TStringField;
xdwdsCustomersstatus: TStringField;
xdwdsCustomersqb_items_qb_id: TStringField;
procedure WebFormCreate(Sender: TObject);
procedure WebFormShow(Sender: TObject);
procedure TMSFNCGrid1CellClick(Sender: TObject; ACol, ARow: Integer);
procedure btnConfirmClick(Sender: TObject);
procedure btnCancelClick(Sender: TObject);
private
{ Private declarations }
[async] procedure getItems();
procedure PopulateGridManually();
[async] procedure SendItemToServer();
public
{ Public declarations }
notification: string;
end;
var
fViewAddItem: TfViewAddItem;
implementation
{$R *.dfm}
procedure TfViewAddItem.WebFormCreate(Sender: TObject);
begin
if not DMConnection.ApiConnection.Connected then
begin
DMConnection.ApiConnection.OpenAsync;
console.log('report requirements connection open')
end;
end;
procedure TfViewAddItem.WebFormShow(Sender: TObject);
begin
//Utils.ShowSpinner('spinner');
getItems();
end;
procedure TfViewAddItem.btnCancelClick(Sender: TObject);
begin
close();
end;
procedure TfViewAddItem.btnConfirmClick(Sender: TObject);
begin
xdwdsCustomers.Locate('qb_item_name', edtName.Text, []);
if edtName.Text = '' then
edtNotification.Text := 'Please Select an Item'
else if xdwdsCustomers.FieldByName('qb_items_id').AsString <> '' then
edtNotification.Text := 'Item Already In Database'
else
SendItemToServer();
end;
procedure TfViewAddItem.getItems;
var
xdcResponse: TXDataClientResponse;
customerList: TJSObject;
i: integer;
begin
// Fetch data from XData service
xdcResponse := await(XDataWebClient1.RawInvokeAsync('ILookupService.getQBItems', []));
customerList := TJSObject(xdcResponse.Result);
// Load data into TXDataWebDataset
xdwdsCustomers.Close;
xdwdsCustomers.SetJsonData(customerList);
xdwdsCustomers.Open;
// Manually populate the grid
PopulateGridManually;
//Utils.HideSpinner('spinner');
end;
procedure TFViewAddItem.PopulateGridManually;
// populates the grid with customers manually.
var
RowIndex: Integer;
begin
TMSFNCGrid1.BeginUpdate;
try
TMSFNCGrid1.Clear; // Clear any existing data
// Set up column headers
TMSFNCGrid1.ColumnCount := 4;
TMSFNCGrid1.RowCount := 1;
TMSFNCGrid1.Cells[0, 0] := 'KGOrders ID';
TMSFNCGrid1.Cells[1, 0] := 'Item Name';
TMSFNCGrid1.Cells[2, 0] := 'Item Description';
TMSFNCGrid1.Cells[3, 0] := 'Status';
// Populate the grid with data from the dataset
xdwdsCustomers.First;
RowIndex := 1;
while not xdwdsCustomers.EOF do
begin
TMSFNCGrid1.RowCount := RowIndex + 1;
TMSFNCGrid1.Cells[0, RowIndex] := xdwdsCustomers.FieldByName('qb_items_id').AsString;
TMSFNCGrid1.Cells[1, RowIndex] := xdwdsCustomers.FieldByName('qb_item_name').AsString;
TMSFNCGrid1.Cells[2, RowIndex] := xdwdsCustomers.FieldByName('item_desc').AsString;
TMSFNCGrid1.Cells[3, RowIndex] := xdwdsCustomers.FieldByName('status').AsString;
Inc(RowIndex);
xdwdsCustomers.Next;
end;
finally
TMSFNCGrid1.EndUpdate;
end;
Utils.HideSpinner('spinner');
end;
procedure TfViewAddItem.TMSFNCGrid1CellClick(Sender: TObject; ACol,
ARow: Integer);
begin
edtName.Text := TMSFNCGrid1.Cells[1, ARow];
end;
procedure TFViewAddItem.SendItemToServer;
var
ItemJSON: TJSONObject;
Response: TXDataClientResponse;
jsObj: TJSObject;
begin
ItemJSON := TJSONObject.Create;
ItemJSON.AddPair('qb_item_name', xdwdsCustomers.FieldByName('qb_item_name').AsString);
ItemJSON.AddPair('item_desc', xdwdsCustomers.FieldByName('item_desc').AsString);
ItemJSON.AddPair('status', xdwdsCustomers.FieldByName('status').AsString);
ItemJSON.AddPair('qb_items_qb_id', xdwdsCustomers.FieldByName('qb_items_qb_id').AsString);
ItemJSON.AddPair('mode', 'ADD');
// Utils.ShowSpinner('spinner');
Response := await(XDataWebClient1.RawInvokeAsync('ILookupService.AddItem',
[ItemJSON.ToString]));
jsObj := TJSObject(Response.Result);
notification := string(jsObj['msg']);
// Utils.HideSpinner('spinner');
Close();
end;
end.
\ No newline at end of file
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
......
<html>
<head>
<meta http-equiv="Content-type" content="text/html; charset=utf-8" />
<title>TMS Web Project</title>
<style>
</style>
</head>
<body>
</body>
</html>
\ No newline at end of file
<div id="spinner" class="position-absolute top-50 start-50 translate-middle d-none">
<div class="lds-roller">
<div></div><div></div><div></div><div></div>
<div></div><div></div><div></div><div></div>
</div>
</div>
......@@ -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
......
object FViewCustomers: TFViewCustomers
Width = 640
Height = 480
CSSLibrary = cssBootstrap
ElementFont = efCSS
OnCreate = WebFormCreate
object lblEntries: TWebLabel
Left = 12
......@@ -42,6 +44,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';
......@@ -125,39 +126,32 @@ begin
if PageNumber > 0 then
begin
Utils.ShowSpinner('spinner');
xdcResponse := await(XDataWebClient1.RawInvokeAsync('ILookupService.GetCustomers', [searchOptions]));
customerList := TJSObject(xdcResponse.Result);
// Load data into the dataset
xdwdsCustomers.Close;
xdwdsCustomers.SetJsonData(customerList['data']);
xdwdsCustomers.Open;
Utils.HideSpinner('spinner');
customerListLength := integer(customerList['count']);
TotalPages := ( (customerListLength + PageSize - 1) div PageSize);
if customerListLength = 0 then
begin
lblEntries.Caption := 'No entries found';
end
else if (PageNumber * PageSize) < customerListLength then
// Currently these do the same thing. If you want to limit the number of entries
// You will need to edit the server side, and then change this if statement so the label
// Correctly displayes. I believe it is IntToStr(PageSize * PageNum)
begin
lblEntries.Caption := 'Showing entries ' + IntToStr((PageNumber - 1) * PageSize + 1) +
' - ' + IntToStr(customerListLength) +
' of ' + IntToStr(customerListLength);
end
else if (PageNumber * PageSize) >= customerListLength then
begin
lblEntries.Caption := 'Showing entries ' + IntToStr((PageNumber - 1) * PageSize + 1) +
' - ' + IntToStr(customerListLength) +
' of ' + IntToStr(customerListLength);
try
xdcResponse := await(XDataWebClient1.RawInvokeAsync('ILookupService.GetCustomers', [searchOptions]));
customerList := TJSObject(xdcResponse.Result);
xdwdsCustomers.Close;
xdwdsCustomers.SetJsonData(customerList['data']);
xdwdsCustomers.Open;
customerListLength := integer(customerList['count']);
TotalPages := ( (customerListLength + PageSize - 1) div PageSize);
if customerListLength = 0 then
lblEntries.Caption := 'No entries found'
else if (PageNumber * PageSize) < customerListLength then
lblEntries.Caption := 'Showing entries ' + IntToStr((PageNumber - 1) * PageSize + 1) +
' - ' + IntToStr(customerListLength) +
' of ' + IntToStr(customerListLength)
else
lblEntries.Caption := 'Showing entries ' + IntToStr((PageNumber - 1) * PageSize + 1) +
' - ' + IntToStr(customerListLength) +
' of ' + IntToStr(customerListLength);
except
on E: EXDataClientRequestException do
Utils.ShowErrorModal('Could not retrieve customers: ' + E.ErrorResult.ErrorMessage);
end;
Utils.HideSpinner('spinner');
end;
end;
......@@ -180,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,26 +79,12 @@ 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;
function TFViewEditUser.AddUser: string;
// Sends UserInfo over to the server so it can be added to the database
var
userInfo: string;
......@@ -111,35 +92,26 @@ var
responseString: TJSObject;
begin
userInfo := '&username=' + edtUsername.Text +
'&fullname=' + edtFullName.Text +
'&password=' + edtPassword.Text +
'&status=' + BoolToStr(cbStatus.Checked) +
'&email=' + edtEmail.Text +
'&access=' + cbAccess.Text +
'&newuser=' + edtUsername.Text +
'&rights=' + edtRights.Text +
'&QB=' + edtQB.Text;
xdcResponse := await(XDataWebClient1.RawInvokeAsync('ILookupService.AddUser',
[userInfo]));
responseString := TJSObject(xdcResponse.Result);
Info := string(responseString['value']);
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;
'&fullname=' + edtFullName.Text +
'&password=' + edtPassword.Text +
'&status=' + BoolToStr(cbStatus.Checked) +
'&email=' + edtEmail.Text +
'&access=' + cbAccess.Text +
'&newuser=' + edtUsername.Text +
'&rights=' + edtRights.Text +
'&QB=' + edtQB.Text;
try
xdcResponse := await(XDataWebClient1.RawInvokeAsync('ILookupService.AddUser', [userInfo]));
responseString := TJSObject(xdcResponse.Result);
Info := string(responseString['value']);
except
on E: EXDataClientRequestException do
Utils.ShowErrorModal('Could not add user: ' + E.ErrorResult.ErrorMessage);
end;
end;
procedure TFViewEditUser.EditUser();
// Sends EditOptions over to the server so the given user can be editted
var
......@@ -167,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
......@@ -194,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
......@@ -221,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;
FormEl := TJSHTMLFormElement(document.getElementById('edituserform'));
if string(edtPassword.Text).IsEmpty then
if not FormEl.checkValidity then
begin
ShowNotification('Password field is blank!');
exit;
FormEl.classList.add('was-validated');
Exit;
end;
if string(edtConfirmPassword.Text).IsEmpty then
begin
ShowNotification('Please confirm your password!');
exit;
end;
if string(edtPhoneNumber.Text).IsEmpty then
begin
ShowNotification('Phone Number field is blank!');
exit;
end;
Utils.ShowSpinner('spinner');
if string(edtEmail.Text).IsEmpty then
begin
ShowNotification('Email field is blank!');
exit;
end;
if Mode = 'Edit' then
EditUser
else
AddUser;
if checkString.Contains('&') then
begin
ShowNotification('No fields may contain "&&"!');
exit;
end;
WebTimer1.Enabled := True;
end;
if string(edtEmail.Text).Contains('@') = false then
begin
ShowNotification('Please enter a valid email address');
exit;
end;
if (length(string(edtEmail.Text).Split(['@'])) <> 2) or (string(edtEmail.text).CountChar('@') > 1) then
begin
ShowNotification('Please enter a valid email address');
exit;
end;
procedure TFViewEditUser.ValidatePasswords;
var
Pwd, Confirm: string;
PwdInput, ConfirmInput: TJSHTMLInputElement;
begin
PwdInput := TJSHTMLInputElement(edtPassword.ElementHandle);
ConfirmInput := TJSHTMLInputElement(edtConfirmPassword.ElementHandle);
phoneNum := edtPhoneNumber.Text;
Pwd := PwdInput.value.Trim;
Confirm := ConfirmInput.value.Trim;
if (not phoneNum.Contains('(')) or (not phoneNum.Contains(')')) or (not phoneNum.Contains('-')) then
// Disable confirm until password exists
if Pwd = '' then
begin
ShowNotification('Please enter a valid phone number');
exit;
end;
if (phoneNum.CountChar('(') <> 1) or (phoneNum.CountChar(')') <> 1) or (phoneNum.CountChar('-') <> 1) or (phoneNum.CountChar(' ') > 1) then
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
console.log('here');
ShowNotification('Please enter a valid phone number');
exit;
ConfirmInput.setCustomValidity('');
ConfirmInput.classList.add('is-valid');
ConfirmInput.classList.remove('is-invalid');
end
else
begin
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.
......@@ -41,20 +41,19 @@ object FViewItems: TFViewItems
'25'
'50')
end
object btnApply: TWebButton
Left = 478
Top = 128
object btnAdd: TWebButton
Left = 565
Top = 318
Width = 96
Height = 25
Caption = 'Apply'
Caption = 'Add'
ChildOrder = 7
ElementClassName = 'btn btn-light'
ElementID = 'btnapply'
ElementID = 'btnadd'
ElementFont = efCSS
HeightStyle = ssAuto
HeightPercent = 100.000000000000000000
WidthPercent = 100.000000000000000000
OnClick = btnApplyClick
OnClick = btnAddClick
end
object edtName: TWebEdit
Left = 342
......@@ -97,6 +96,70 @@ object FViewItems: TFViewItems
HeightPercent = 100.000000000000000000
WidthPercent = 100.000000000000000000
end
object btnSave: TWebButton
Left = 565
Top = 228
Width = 96
Height = 25
Caption = 'Save'
ChildOrder = 79
ElementID = 'btnconfirm'
ElementFont = efCSS
ElementPosition = epRelative
Enabled = False
HeightStyle = ssAuto
HeightPercent = 100.000000000000000000
Role = 'null'
WidthPercent = 100.000000000000000000
OnClick = btnSaveClick
end
object btnCancel: TWebButton
Left = 565
Top = 256
Width = 96
Height = 25
Caption = 'Cancel'
ChildOrder = 79
ElementID = 'btncancel'
ElementFont = efCSS
ElementPosition = epRelative
Enabled = False
HeightStyle = ssAuto
HeightPercent = 100.000000000000000000
Role = 'null'
WidthPercent = 100.000000000000000000
OnClick = btnCancelClick
end
object btnDelete: TWebButton
Left = 565
Top = 197
Width = 96
Height = 25
Caption = 'Delete'
ChildOrder = 79
ElementID = 'btndelete'
ElementFont = efCSS
Enabled = False
HeightStyle = ssAuto
HeightPercent = 100.000000000000000000
WidthPercent = 100.000000000000000000
OnClick = btnDeleteClick
end
object btnEdit: TWebButton
Left = 565
Top = 287
Width = 96
Height = 25
Caption = 'Edit'
ChildOrder = 83
ElementID = 'btnedit'
ElementFont = efCSS
Enabled = False
HeightStyle = ssAuto
HeightPercent = 100.000000000000000000
WidthPercent = 100.000000000000000000
OnClick = btnEditClick
end
object XDataWebClient1: TXDataWebClient
Connection = DMConnection.ApiConnection
Left = 426
......
<nav class="navbar navbar-expand navbar-light bg-light sticky-top" style="z-index: 100;">
<div class="container-fluid ps-0">
<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>
</li>
<li class="nav-item pe-2">
<button id="btnedit" class="btn btn-primary btn-sm">Edit</button>
</li>
<li class="nav-item pe-2">
<button id="btndelete" class="btn btn-danger btn-sm">Delete</button>
</li>
<li class="nav-item pe-2">
<button id="btnconfirm" class="btn btn-success btn-sm">Save</button>
</li>
<li class="nav-item pe-2">
<button id="btncancel" class="btn btn-danger btn-sm">Cancel</button>
</li>
</ul>
</div>
</nav>
<div class="row">
<div class="col-12">
<div class="container mt-4">
......@@ -30,13 +51,10 @@
<div class="col-sm-5">
<label class="py-2" style="font-weight: 700;">Show <select class="custom-select" id="wcbpagesize" style="font-size: 1.00rem;"></select> entries</label>
</div>
<div class="col-sm-5">
<button class= "ps-3" id="btnapply"></button>
</div>
</div>
</form>
<table class="table table-responsive table-striped table-bordered" id="tblPhoneGrid">
<table class="table table-responsive table-striped table-hover table-bordered" id="tblPhoneGrid">
<thead class="thead-dark">
<tr>
<th scope="col">ID</th>
......
......@@ -57,7 +57,7 @@ object FViewMain: TFViewMain
end
object lblAppTitle: TWebLabel
Left = 57
Top = 31
Top = 33
Width = 75
Height = 14
Caption = 'Koehler-Gibson'
......@@ -157,6 +157,12 @@ object FViewMain: TFViewMain
ChildOrder = 3
ElementFont = efCSS
ElementPosition = epIgnore
Font.Charset = ANSI_CHARSET
Font.Color = clBlack
Font.Height = -11
Font.Name = 'Arial'
Font.Style = []
ParentFont = False
Role = 'null'
TabOrder = 0
end
......@@ -167,12 +173,14 @@ object FViewMain: TFViewMain
Height = 83
ElementID = 'main.debugmemo'
ElementPosition = epRelative
Enabled = False
HeightPercent = 100.000000000000000000
Lines.Strings = (
'WebMemo1')
Role = 'null'
SelLength = 0
SelStart = 0
ShowFocus = False
Visible = False
WidthPercent = 100.000000000000000000
end
......
......@@ -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>
......@@ -69,6 +84,47 @@
</div>
</div>
<div class="modal fade" id="main_errormodal" tabindex="-1" aria-labelledby="main_lblmodal" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content shadow-lg">
<div class="modal-header">
<h5 class="modal-title" id="main_lblmodal">Error</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="main_lblmodal_body">
Please contact EMSystems to solve the issue.
</div>
<div class="modal-footer justify-content-center">
<button type="button" id="btn_modal_restart" class="btn btn-primary">Back to Orders</button>
</div>
</div>
</div>
</div>
<div class="modal fade" id="main_confirmation_modal" tabindex="-1" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content shadow-lg">
<div class="modal-header">
<h5 class="modal-title">Confirm</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body fw-bold" id="main_modal_body">
Placeholder text
</div>
<div class="modal-footer justify-content-center">
<button type="button" class="btn btn-primary me-3" id="btn_confirm_left">Cancel</button>
<button type="button" class="btn btn-secondary" id="btn_confirm_right">Confirm</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,7 @@ type
//procedure EditUser( AParam, BParam, CParam, DParam, EParam: string);
function GetUserInfo: string;
procedure setActive(page: string);
procedure ConfirmLogout;
public
{ Public declarations }
class procedure Display(LogoutProc: TLogoutProc);
......@@ -101,7 +102,6 @@ begin
ShowForm(TFViewOrders);
lblAppTitle.Caption := 'Koehler-Gibson Orders';
lblVersion.Caption := 'v' + DMConnection.clientVersion;
setActive('Orders');
end;
......@@ -117,7 +117,7 @@ begin
setActive('Customers');
end
else
ShowMessage('Please Save or Cancel your changes');
ShowToast('Please Save or Cancel your changes', 'danger');
end;
procedure TFViewMain.lblHomeClick(Sender: TObject);
......@@ -129,12 +129,11 @@ begin
//setActive('Home');
end
else
ShowMessage('Please Save or Cancel your changes');
ShowToast('Please Save or Cancel your changes', 'danger');
end;
procedure TFViewMain.lblordersClick(Sender: TObject);
begin
console.log(change);
if ( not ( change ) ) then
begin
ShowForm(TFViewOrders);
......@@ -142,7 +141,7 @@ begin
setActive('Orders');
end
else
ShowMessage('Please Save or Cancel your changes');
ShowToast('Please Save or Cancel your changes', 'danger');
end;
procedure TFViewMain.lblQuickbooksClick(Sender: TObject);
......@@ -154,7 +153,7 @@ begin
setActive('QuickBooks');
end
else
ShowMessage('Please Save or Cancel your changes');
ShowToast('Please Save or Cancel your changes', 'danger');
end;
procedure TFViewMain.lblUsersClick(Sender: TObject);
......@@ -165,7 +164,7 @@ begin
lblAppTitle.Caption := 'Koehler-Gibson Users';
end
else
ShowMessage('Please Save or Cancel your changes');
ShowToast('Please Save or Cancel your changes', 'danger');
end;
procedure TFViewMain.lblItemsListClick(Sender: TObject);
......@@ -177,7 +176,7 @@ begin
setActive('Items');
end
else
ShowMessage('Please Save or Cancel your changes');
ShowToast('Please Save or Cancel your changes', 'danger');
end;
procedure TFViewMain.setActive(page: string);
......@@ -200,13 +199,28 @@ end;
procedure TFViewMain.mnuLogoutClick(Sender: TObject);
begin
FLogoutProc;
ConfirmLogout;
end;
procedure TFViewMain.wllblLogoutClick(Sender: TObject);
begin
FLogoutProc;
ConfirmLogout;
end;
procedure TFViewMain.ConfirmLogout;
begin
ShowConfirmationModal(
'Are you sure you want to log out?',
'Yes',
'No',
procedure(confirmed: Boolean)
begin
if confirmed and Assigned(FLogoutProc) then
FLogoutProc('');
end
);
end;
......@@ -315,4 +329,5 @@ begin
FChildForm := TFViewUsers.CreateForm(WebPanel1.ElementID, Info);
end;
end.
<nav class="navbar navbar-expand navbar-light bg-light border-light sticky-top" style="z-index: 100;">
<div class="container-fluid d-flex align-items-center ps-0 pe-0">
<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>
</li>
<li class="nav-item pe-2">
<button id="btnedit" class="btn btn-primary btn-sm">Edit</button>
</li>
<li class="nav-item pe-2">
<button id="btncopy" class="btn btn-primary btn-sm">Copy</button>
</li>
<li class="nav-item pe-2">
<button id="btndelete" class="btn btn-danger btn-sm">Delete</button>
</li>
<li class="nav-item pe-2">
<button id="btnpdf" class="btn btn-primary btn-sm">PDF</button>
</li>
<li class="nav-item pe-2">
<button id="btnconfirm" class="btn btn-success btn-sm">Save</button>
</li>
<li class="nav-item pe-2">
<button id="btncancel" class="btn btn-danger btn-sm">Cancel</button>
</li>
<li class="nav-item">
<button id="btnclose" class="btn btn-primary btn-sm">Close</button>
</li>
</ul>
<!-- Left-aligned label -->
<div class="me-auto ps-3">
<label id="lbl_form_state" class="form-label mb-0 fw-bold text-uppercase text-nowrap text-danger" style="font-size: 16px;">Test</label>
</div>
<!-- Right-aligned buttons -->
<ul class="navbar-nav ms-auto pe-2 mb-0">
<li class="nav-item pe-2">
<button id="btnadd" class="btn btn-primary btn-sm">Add</button>
</li>
<li class="nav-item pe-2">
<button id="btnedit" class="btn btn-primary btn-sm">Edit</button>
</li>
<li class="nav-item pe-2">
<button id="btncopy" class="btn btn-primary btn-sm">Copy</button>
</li>
<li class="nav-item pe-2">
<button id="btndelete" class="btn btn-danger btn-sm">Delete</button>
</li>
<li class="nav-item pe-2">
<button id="btnpdf" class="btn btn-primary btn-sm">PDF</button>
</li>
<li class="nav-item pe-2">
<button id="btnconfirm" class="btn btn-success btn-sm">Save</button>
</li>
<li class="nav-item pe-2">
<button id="btncancel" class="btn btn-danger btn-sm">Cancel</button>
</li>
<li class="nav-item">
<button id="btnclose" class="btn btn-primary btn-sm">Close</button>
</li>
</ul>
</div>
</nav>
<div class="row mx-5">
<div class="col-12 col-md-8">
......@@ -220,7 +222,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>
......@@ -362,28 +364,4 @@
<textarea id="edtspecialinstructions" class="form-control" style=" width: 500px; height: 150px;"></textarea>
</div>
</div>
</div>
<div class="modal fade" id="confirmation_modal" tabindex="-1" aria-labelledby="confirmation_modal_label" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<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">
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>
<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>
object FOrderEntryCuttingDie: TFOrderEntryCuttingDie
Width = 956
Height = 728
OnShow = WebFormShow
object WebLabel2: TWebLabel
Left = 26
Top = 72
......@@ -32,6 +31,15 @@ object FOrderEntryCuttingDie: TFOrderEntryCuttingDie
Visible = False
WidthPercent = 100.000000000000000000
end
object lblFormState: TWebLabel
Left = 34
Top = 8
Width = 3
Height = 15
ElementID = 'lbl_form_state'
HeightPercent = 100.000000000000000000
WidthPercent = 100.000000000000000000
end
object edtCompanyAccountName: TWebDBEdit
Left = 24
Top = 120
......@@ -46,10 +54,11 @@ object FOrderEntryCuttingDie: TFOrderEntryCuttingDie
DataSource = WebDataSource1
end
object edtInQuickBooks: TWebDBEdit
Left = 26
Top = 148
Left = 24
Top = 152
Width = 121
Height = 23
AutoCompletion = acNope
AutoSize = True
ChildOrder = 79
ElementID = 'edtinquickbooks'
......@@ -70,7 +79,6 @@ object FOrderEntryCuttingDie: TFOrderEntryCuttingDie
Date = 45638.529943136570000000
Role = ''
Text = ''
OnChange = dtpOrderDateChange
end
object dtpProofDate: TWebDateTimePicker
Left = 22
......@@ -84,7 +92,6 @@ object FOrderEntryCuttingDie: TFOrderEntryCuttingDie
Date = 45638.529943136570000000
Role = ''
Text = ''
OnChange = dtpOrderDateChange
end
object dtpShipDate: TWebDateTimePicker
Left = 22
......@@ -98,7 +105,6 @@ object FOrderEntryCuttingDie: TFOrderEntryCuttingDie
Date = 45638.529943136570000000
Role = ''
Text = ''
OnChange = dtpOrderDateChange
end
object edtShipVia: TWebDBEdit
Left = 24
......@@ -120,6 +126,7 @@ object FOrderEntryCuttingDie: TFOrderEntryCuttingDie
Height = 23
AutoSize = True
ChildOrder = 79
EditType = weNumeric
ElementID = 'edtquantity'
HeightPercent = 100.000000000000000000
WidthPercent = 100.000000000000000000
......@@ -228,43 +235,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
......@@ -338,18 +308,6 @@ object FOrderEntryCuttingDie: TFOrderEntryCuttingDie
WidthPercent = 100.000000000000000000
OnClick = btnCloseClick
end
object btn_confirm_delete: TWebButton
Left = 776
Top = 279
Width = 96
Height = 25
Caption = 'Delete'
ChildOrder = 82
ElementID = 'btn_confirm_delete'
HeightPercent = 100.000000000000000000
WidthPercent = 100.000000000000000000
OnClick = btn_confirm_deleteClick
end
object btnCopy: TWebButton
Left = 746
Top = 453
......@@ -399,15 +357,15 @@ object FOrderEntryCuttingDie: TFOrderEntryCuttingDie
OnClick = WebButton2Click
end
object WebDataSource1: TWebDataSource
AutoEdit = False
DataSet = XDataWebDataSet1
Left = 22
Top = 10
Left = 418
Top = 86
end
object XDataWebDataSet1: TXDataWebDataSet
AfterEdit = XDataWebDataSet1AfterEdit
Connection = DMConnection.ApiConnection
Left = 90
Top = 20
Left = 422
Top = 28
object XDataWebDataSet1COMPANY_ID: TIntegerField
FieldName = 'COMPANY_ID'
end
......@@ -468,40 +426,35 @@ object FOrderEntryCuttingDie: TFOrderEntryCuttingDie
object XDataWebDataSet1staff_fields_quantity: TStringField
FieldName = 'staff_fields_quantity'
end
object XDataWebDataSet1inQuickBooks: TStringField
FieldName = 'inQuickBooks'
end
end
object XDataWebClient1: TXDataWebClient
Connection = DMConnection.ApiConnection
Left = 192
Top = 92
end
object tmrScrollTop: TWebTimer
Interval = 100
OnTimer = tmrScrollTopTimer
Left = 240
Top = 8
Left = 200
Top = 50
end
object wdsShipTo: TWebDataSource
DataSet = xdwdsShipTo
Left = 302
Top = 418
Left = 526
Top = 86
end
object xdwdsShipTo: TXDataWebDataSet
AfterEdit = xdwdsShipToAfterEdit
Left = 288
Top = 370
Left = 528
Top = 26
object xdwdsShipToADDRESS: TStringField
FieldName = 'ADDRESS'
end
end
object wdsQBItem: TWebDataSource
DataSet = xdwdsQBItem
Left = 230
Top = 554
Left = 606
Top = 86
end
object xdwdsQBItem: TXDataWebDataSet
AfterEdit = xdwdsQBItemAfterEdit
Left = 190
Top = 548
Left = 608
Top = 30
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>
</li>
<li class="nav-item pe-2">
<button id="btnedit" class="btn btn-primary btn-sm">Edit</button>
</li>
<li class="nav-item pe-2">
<button id="btncopy" class="btn btn-primary btn-sm">Copy</button>
</li>
<li class="nav-item pe-2">
<button id="btndelete" class="btn btn-danger btn-sm">Delete</button>
</li>
<li class="nav-item pe-2">
<button id="btnpdf" class="btn btn-primary btn-sm">PDF</button>
</li>
<li class="nav-item pe-2">
<button id="btnconfirm" class="btn btn-success btn-sm">Save</button>
</li>
<li class="nav-item pe-2">
<button id="btncancel" class="btn btn-danger btn-sm">Cancel</button>
</li>
<li class="nav-item">
<button id="btnclose" class="btn btn-secondary btn-sm">Close</button>
</li>
</ul>
<nav class="navbar navbar-expand navbar-light bg-light border-light sticky-top" style="z-index: 100;">
<div class="container-fluid d-flex align-items-center ps-0 pe-0">
<!-- Left-aligned label -->
<div class="me-auto ps-3">
<label id="lbl_form_state" class="form-label mb-0 fw-bold text-uppercase text-nowrap text-danger" style="font-size: 16px;">View Mode</label>
</div>
<!-- Right-aligned buttons -->
<ul class="navbar-nav ms-auto pe-2 mb-0">
<li class="nav-item pe-2">
<button id="btnadd" class="btn btn-primary btn-sm">Add</button>
</li>
<li class="nav-item pe-2">
<button id="btnedit" class="btn btn-primary btn-sm">Edit</button>
</li>
<li class="nav-item pe-2">
<button id="btncopy" class="btn btn-primary btn-sm">Copy</button>
</li>
<li class="nav-item pe-2">
<button id="btndelete" class="btn btn-danger btn-sm">Delete</button>
</li>
<li class="nav-item pe-2">
<button id="btnpdf" class="btn btn-primary btn-sm">PDF</button>
</li>
<li class="nav-item pe-2">
<button id="btnconfirm" class="btn btn-success btn-sm">Save</button>
</li>
<li class="nav-item pe-2">
<button id="btncancel" class="btn btn-danger btn-sm">Cancel</button>
</li>
<li class="nav-item">
<button id="btnclose" class="btn btn-primary btn-sm">Close</button>
</li>
</ul>
</div>
</nav>
<div class="row mx-5">
<h4 class="custom-h4 mt-3">Customer</h4>
......@@ -129,26 +132,4 @@
</div>
</div>
</div>
<div class="modal fade" id="confirmation_modal" tabindex="-1" aria-labelledby="confirmation_modal_label" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<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">
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>
<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>
<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>
</li>
<li class="nav-item pe-2">
<button id="btnedit" class="btn btn-primary btn-sm">Edit</button>
</li>
<li class="nav-item pe-2">
<button id="btncopy" class="btn btn-primary btn-sm">Copy</button>
</li>
<li class="nav-item pe-2">
<button id="btndelete" class="btn btn-danger btn-sm">Delete</button>
</li>
<li class="nav-item pe-2">
<button id="btnpdf" class="btn btn-primary btn-sm">PDF</button>
</li>
<li class="nav-item pe-2">
<button id="btnconfirm" class="btn btn-success btn-sm">Save</button>
</li>
<li class="nav-item pe-2">
<button id="btncancel" class="btn btn-danger btn-sm">Cancel</button>
</li>
<li class="nav-item">
<button id="btnclose" class="btn btn-secondary btn-sm">Close</button>
</li>
</ul>
<nav class="navbar navbar-expand navbar-light bg-light border-light sticky-top" style="z-index: 100;">
<div class="container-fluid d-flex align-items-center ps-0 pe-0">
<!-- Left-aligned label -->
<div class="me-auto ps-3">
<label id="lbl_form_state" class="form-label mb-0 fw-bold text-uppercase text-nowrap text-danger" style="font-size: 16px;">Test</label>
</div>
<!-- Right-aligned buttons -->
<ul class="navbar-nav ms-auto pe-2 mb-0">
<li class="nav-item pe-2">
<button id="btnadd" class="btn btn-primary btn-sm">Add</button>
</li>
<li class="nav-item pe-2">
<button id="btnedit" class="btn btn-primary btn-sm">Edit</button>
</li>
<li class="nav-item pe-2">
<button id="btncopy" class="btn btn-primary btn-sm">Copy</button>
</li>
<li class="nav-item pe-2">
<button id="btndelete" class="btn btn-danger btn-sm">Delete</button>
</li>
<li class="nav-item pe-2">
<button id="btnpdf" class="btn btn-primary btn-sm">PDF</button>
</li>
<li class="nav-item pe-2">
<button id="btnconfirm" class="btn btn-success btn-sm">Save</button>
</li>
<li class="nav-item pe-2">
<button id="btncancel" class="btn btn-danger btn-sm">Cancel</button>
</li>
<li class="nav-item">
<button id="btnclose" class="btn btn-primary btn-sm">Close</button>
</li>
</ul>
</div>
</nav>
<div class="row mx-5">
<h4 class="custom-h4 mt-3">Customer</h4>
......@@ -248,25 +251,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>
......@@ -404,53 +425,5 @@
<textarea id="edtcomments" class="form-control" style=" width: 500px; height: 150px;"></textarea>
</div>
</div>
<div class="row">
<div class="col-auto">
<button id="btnconfirm" class="btn btn-primary btn-sm float-end my-2">Save</button>
</div>
<div class="col-auto">
<button id="btncancel" class="btn btn-primary btn-sm float-end my-2">Cancel</button>
</div>
<div class="col-auto">
<button id="btncopy" class="btn btn-primary btn-sm float-end my-2">Copy</button>
</div>
<div class="col-auto">
<button id="btnpdf" class="btn btn-primary btn-sm float-end my-2">PDF</button>
</div>
<div class="col-auto">
<button id="btndelete" class="btn btn-primary btn-sm float-end my-2">Delete</button>
</div>
<div class="col-auto">
<button id="btnclose" class="btn btn-primary btn-sm float-end my-2">Close</button>
</div>
<div class="col-auto">
<button id="btnedit" class="btn btn-primary btn-sm float-end my-2">Edit</button>
</div>
<div class="col-auto">
<button id="btnadd" class="btn btn-primary btn-sm float-end my-2">Add</button>
</div>
</div>
</div>
<div class="modal fade" id="confirmation_modal" tabindex="-1" aria-labelledby="confirmation_modal_label" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<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">
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>
<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>
......@@ -237,9 +237,7 @@ object FViewOrders: TFViewOrders
ItemIndex = -1
LookupValues = <
item
Value =
'COALESCE(cpo.staff_fields_order_date, wpo.staff_fields_order_dat' +
'e, cdo.staff_fields_order_date) DESC'
Value = 'o.ORDER_ID DESC'
DisplayText = 'ID'
end
item
......@@ -251,7 +249,9 @@ object FViewOrders: TFViewOrders
DisplayText = 'Job Name'
end
item
Value = 'o.ORDER_DATE DESC'
Value =
'COALESCE(cpo.staff_fields_order_date, wpo.staff_fields_order_dat' +
'e, cdo.staff_fields_order_date) DESC'
DisplayText = 'Order Date'
end
item
......@@ -309,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">
......
......@@ -231,6 +231,7 @@ object FSearch: TFSearch
TabStop = False
Text = 'PROOF DONE'
WidthPercent = 100.000000000000000000
OnChange = wcbFilterType1Change
ItemIndex = -1
Items.Strings = (
'NONE'
......@@ -365,6 +366,7 @@ object FSearch: TFSearch
TabStop = False
Text = 'PROOF DONE'
WidthPercent = 100.000000000000000000
OnChange = wcbFilterType2Change
ItemIndex = -1
Items.Strings = (
'NONE'
......
......@@ -64,6 +64,8 @@ type
procedure btnClearClick(Sender: TObject);
procedure cbNull1Click(Sender: TObject);
procedure cbNull2Click(Sender: TObject);
procedure wcbFilterType1Change(Sender: TObject);
procedure wcbFilterType2Change(Sender: TObject);
private
//FJSONProc: TJSONProc;
[async] procedure getCustomers;
......@@ -118,8 +120,8 @@ begin
DateFormatSettings.ShortDateFormat := 'yyyy/mm/dd';
wcbOrderType.Text := UpperCase(Copy(params.Values['orderType'], 1, 1)) + LowerCase(Copy(params.Values['orderType'], 2, MaxInt));
edtOrderID.Text := params.Values['orderID'];
edtCompanyID.Text := params.Values['companyID'];
edtJobName.Text := params.Values['jobName'];
DBID := params.Values['companyID'];
// Status 1
if params.Values['filterType1'] <> '' then
......@@ -175,9 +177,9 @@ begin
end;
end;
getCustomers();
params.Free;
getCustomers();
end;
procedure TFSearch.btnCancelClick(Sender: TObject);
......@@ -257,6 +259,13 @@ begin
// Manually populate the grid
PopulateGridManually;
if DBID <> '' then
begin
xdwdsCustomers.Locate('CUSTOMER_ID', DBID, []);
edtCompanyID.Text := xdwdsCustomers.FieldByName('SHORT_NAME').AsString;
edtCompanyName.Text := xdwdsCustomers.FieldByName('NAME').AsString;
end;
end;
procedure TFSearch.TMSFNCGrid1CellClick(Sender: TObject; ACol, ARow: Integer);
......@@ -267,6 +276,39 @@ begin
end;
procedure TFSearch.wcbFilterType1Change(Sender: TObject);
begin
if wcbFilterType1.Text = 'NONE' then
begin
dtpStartDate1.Visible := false;
dtpEndDate1.Visible := false;
cbNull1.Visible := false;
end
else
begin
dtpStartDate1.Visible := True;
dtpEndDate1.Visible := True;
cbNull1.Visible := True;
end;
end;
procedure TFSearch.wcbFilterType2Change(Sender: TObject);
begin
if wcbFilterType2.Text = 'NONE' then
begin
dtpStartDate2.Visible := false;
dtpEndDate2.Visible := false;
cbNull2.Visible := false;
end
else
begin
dtpStartDate2.Visible := True;
dtpEndDate2.Visible := True;
cbNull2.Visible := True;
end;
end;
procedure TFSearch.PopulateGridManually;
var
RowIndex: Integer;
......
object FSelectCustomer: TFSelectCustomer
Width = 765
Height = 480
Height = 416
OnCreate = WebFormCreate
OnShow = WebFormShow
object WebLabel1: TWebLabel
Left = 8
Top = 81
Top = 27
Width = 95
Height = 15
Caption = 'Search Customers'
......@@ -14,7 +14,7 @@ object FSelectCustomer: TFSelectCustomer
end
object WebLabel2: TWebLabel
Left = 279
Top = 81
Top = 27
Width = 134
Height = 15
Caption = 'Selected Customer Name'
......@@ -23,7 +23,7 @@ object FSelectCustomer: TFSelectCustomer
end
object WebLabel3: TWebLabel
Left = 131
Top = 81
Top = 27
Width = 113
Height = 15
Caption = 'Selected Customer ID'
......@@ -32,16 +32,17 @@ object FSelectCustomer: TFSelectCustomer
end
object edtSearch: TWebEdit
Left = 4
Top = 102
Top = 48
Width = 121
Height = 22
ChildOrder = 2
HeightPercent = 100.000000000000000000
WidthPercent = 100.000000000000000000
OnChange = edtSearchChange
end
object edtName: TWebEdit
Left = 279
Top = 102
Top = 48
Width = 142
Height = 22
ChildOrder = 1
......@@ -51,7 +52,7 @@ object FSelectCustomer: TFSelectCustomer
end
object TMSFNCGrid1: TTMSFNCGrid
Left = 0
Top = 163
Top = 99
Width = 765
Height = 317
Align = alBottom
......@@ -205,20 +206,22 @@ object FSelectCustomer: TFSelectCustomer
ScrollMode = scmItemScrolling
DesignTimeSampleData = True
OnCellClick = TMSFNCGrid1CellClick
ExplicitTop = 163
end
object btnCancel: TWebButton
Left = 556
Top = 101
Top = 47
Width = 96
Height = 25
Caption = 'Cancel'
ChildOrder = 5
HeightPercent = 100.000000000000000000
WidthPercent = 100.000000000000000000
OnClick = btnCancelClick
end
object btnConfirm: TWebButton
Left = 440
Top = 101
Top = 47
Width = 96
Height = 25
Caption = 'Select'
......@@ -227,30 +230,9 @@ object FSelectCustomer: TFSelectCustomer
WidthPercent = 100.000000000000000000
OnClick = btnConfirmClick
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 edtID: TWebEdit
Left = 131
Top = 102
Top = 48
Width = 142
Height = 22
ChildOrder = 1
......
<html>
<head>
<meta http-equiv="Content-type" content="text/html; charset=utf-8" />
<title>TMS Web Project</title>
<style>
</style>
</head>
<body>
</body>
</html>
\ No newline at end of file
<div id="spinner" class="position-absolute top-50 start-50 translate-middle d-none">
<div class="lds-roller">
<div></div><div></div><div></div><div></div>
<div></div><div></div><div></div><div></div>
</div>
</div>
......@@ -21,7 +21,6 @@ type
TMSFNCGrid1: TTMSFNCGrid;
btnCancel: TWebButton;
btnConfirm: TWebButton;
edtNotification: TWebEdit;
XDataWebClient1: TXDataWebClient;
xdwdsCustomers: TXDataWebDataSet;
wdsCustomers: TWebDataSource;
......@@ -46,11 +45,14 @@ type
procedure TMSFNCGrid1CellDblClick(Sender: TObject; ACol, ARow: Integer);
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();
[Async] procedure SendCustomerToServer();
procedure PopulateGridManually();
procedure ApplyFilter();
public
{ Public declarations }
end;
......@@ -75,14 +77,18 @@ end;
procedure TFSelectCustomer.WebFormShow(Sender: TObject);
begin
Utils.ShowSpinner('spinner');
getCustomers();
end;
procedure TFSelectCustomer.btnCancelClick(Sender: TObject);
begin
Close();
end;
procedure TFSelectCustomer.btnConfirmClick(Sender: TObject);
begin
if edtID.Text = '' then
edtNotification.Text := 'Please Select a Customer'
ShowToast('Please Select a Customer', 'danger')
else
begin
xdwdsCustomers.Locate('Id', edtID.Text, []);
......@@ -90,29 +96,38 @@ begin
end;
end;
[async] procedure TFSelectCustomer.getCustomers();
procedure TFSelectCustomer.edtSearchChange(Sender: TObject);
begin
ApplyFilter();
end;
procedure TFSelectCustomer.getCustomers();
// retrieves customer list from server
var
xdcResponse: TXDataClientResponse;
customerList: TJSObject;
i: integer;
begin
// Fetch data from XData service
xdcResponse := await(XDataWebClient1.RawInvokeAsync('ILookupService.getQBCustomers', []));
customerList := TJSObject(xdcResponse.Result);
//console.log(customerList);
// Load data into TXDataWebDataset
xdwdsCustomers.Close;
xdwdsCustomers.SetJsonData(customerList);
xdwdsCustomers.Open;
// Manually populate the grid
PopulateGridManually;
Utils.HideSpinner('spinner');
try
Utils.ShowSpinner('spinner');
// Fetch data from XData service
xdcResponse := await(XDataWebClient1.RawInvokeAsync('ILookupService.getQBCustomers', []));
customerList := TJSObject(xdcResponse.Result);
// Load data into TXDataWebDataset
xdwdsCustomers.Close;
xdwdsCustomers.SetJsonData(customerList);
xdwdsCustomers.Open;
// Manually populate the grid
PopulateGridManually;
except
on E: EXDataClientRequestException do
Utils.ShowErrorModal('Could not retrieve QuickBooks customers: ' + E.ErrorResult.ErrorMessage);
end;
end;
procedure TFSelectCustomer.PopulateGridManually;
// populates the grid with customers manually.
var
......@@ -148,6 +163,7 @@ begin
finally
TMSFNCGrid1.EndUpdate;
end;
Utils.HideSpinner('spinner');
end;
procedure TFSelectCustomer.TMSFNCGrid1CellClick(Sender: TObject; ACol,
......@@ -202,4 +218,35 @@ begin
end;
procedure TFSelectCustomer.ApplyFilter;
// filters the grid based on search textbox contents.
var
fd: TTMSFNCGridFilterData;
i: Integer;
SearchText: string;
begin
SearchText := Trim(edtSearch.Text);
TMSFNCGrid1.RemoveFilter;
TMSFNCGrid1.Filter.Clear;
// match on first 3 columns
for i := 0 to 2 do
begin
fd := TMSFNCGrid1.Filter.Add;
fd.Column := i;
fd.Condition := '*' + SearchText + '*'; // Match text anywhere in the cell
fd.CaseSensitive := False; // Make the filter case-insensitive
// Use foOR for "match any column" logic
if i > 0 then
fd.Operation := foOR
else
fd.Operation := foNONE; // First filter has no logical operation
end;
// Apply the filters to the grid
TMSFNCGrid1.ApplyFilter;
end;
end.
\ No newline at end of file
object FSetStatus: TFSetStatus
Width = 640
Height = 361
Height = 278
OnShow = WebFormShow
object lblStatus1: TWebLabel
Left = 326
Top = 80
Left = 328
Top = 32
Width = 38
Height = 14
Caption = 'Status:'
......@@ -18,8 +18,8 @@ object FSetStatus: TFSetStatus
WidthPercent = 100.000000000000000000
end
object WebLabel1: TWebLabel
Left = 484
Top = 80
Left = 486
Top = 32
Width = 91
Height = 14
Caption = 'Date Completed:'
......@@ -33,8 +33,8 @@ object FSetStatus: TFSetStatus
WidthPercent = 100.000000000000000000
end
object WebLabel2: TWebLabel
Left = 14
Top = 80
Left = 16
Top = 32
Width = 48
Height = 14
Caption = 'Order ID:'
......@@ -48,8 +48,8 @@ object FSetStatus: TFSetStatus
WidthPercent = 100.000000000000000000
end
object WebLabel3: TWebLabel
Left = 172
Top = 78
Left = 174
Top = 30
Width = 57
Height = 14
Caption = 'Job Name:'
......@@ -63,8 +63,8 @@ object FSetStatus: TFSetStatus
WidthPercent = 100.000000000000000000
end
object WebLabel4: TWebLabel
Left = 11
Top = 142
Left = 13
Top = 94
Width = 51
Height = 14
Caption = 'Ship Due:'
......@@ -78,8 +78,8 @@ object FSetStatus: TFSetStatus
WidthPercent = 100.000000000000000000
end
object WebLabel5: TWebLabel
Left = 169
Top = 142
Left = 171
Top = 94
Width = 78
Height = 14
Caption = 'New Due Date:'
......@@ -93,8 +93,8 @@ object FSetStatus: TFSetStatus
WidthPercent = 100.000000000000000000
end
object lblMount: TWebLabel
Left = 324
Top = 200
Left = 326
Top = 152
Width = 62
Height = 14
Caption = 'Mount Due:'
......@@ -108,8 +108,8 @@ object FSetStatus: TFSetStatus
WidthPercent = 100.000000000000000000
end
object lblMountNew: TWebLabel
Left = 482
Top = 200
Left = 484
Top = 152
Width = 78
Height = 14
Caption = 'New Due Date:'
......@@ -123,8 +123,8 @@ object FSetStatus: TFSetStatus
WidthPercent = 100.000000000000000000
end
object lblPlate: TWebLabel
Left = 11
Top = 200
Left = 13
Top = 152
Width = 54
Height = 14
Caption = 'Plate Due:'
......@@ -138,8 +138,8 @@ object FSetStatus: TFSetStatus
WidthPercent = 100.000000000000000000
end
object lblPlateNew: TWebLabel
Left = 169
Top = 200
Left = 171
Top = 152
Width = 78
Height = 14
Caption = 'New Due Date:'
......@@ -153,8 +153,8 @@ object FSetStatus: TFSetStatus
WidthPercent = 100.000000000000000000
end
object lblArt: TWebLabel
Left = 324
Top = 142
Left = 326
Top = 94
Width = 44
Height = 14
Caption = 'Art Due:'
......@@ -168,8 +168,8 @@ object FSetStatus: TFSetStatus
WidthPercent = 100.000000000000000000
end
object lblArtNew: TWebLabel
Left = 482
Top = 142
Left = 484
Top = 94
Width = 78
Height = 14
Caption = 'New Due Date:'
......@@ -183,8 +183,8 @@ object FSetStatus: TFSetStatus
WidthPercent = 100.000000000000000000
end
object wlcbStatus: TWebLookupComboBox
Left = 326
Top = 100
Left = 328
Top = 52
Width = 145
Height = 22
ElementClassName = 'custom-select'
......@@ -194,8 +194,8 @@ object FSetStatus: TFSetStatus
LookupValues = <>
end
object dtpDate: TWebDateTimePicker
Left = 484
Top = 100
Left = 486
Top = 52
Width = 145
Height = 22
BorderStyle = bsSingle
......@@ -206,8 +206,8 @@ object FSetStatus: TFSetStatus
Text = ''
end
object btnConfirm: TWebButton
Left = 14
Top = 273
Left = 16
Top = 225
Width = 96
Height = 25
Caption = 'Confirm'
......@@ -222,8 +222,8 @@ object FSetStatus: TFSetStatus
OnClick = btnConfirmClick
end
object btnCancel: TWebButton
Left = 125
Top = 273
Left = 127
Top = 225
Width = 96
Height = 25
Caption = 'Cancel'
......@@ -238,8 +238,8 @@ object FSetStatus: TFSetStatus
OnClick = btnCancelClick
end
object edtOrderID: TWebEdit
Left = 14
Top = 100
Left = 16
Top = 52
Width = 145
Height = 22
HelpType = htKeyword
......@@ -259,31 +259,9 @@ object FSetStatus: TFSetStatus
TabOrder = 1
WidthPercent = 100.000000000000000000
end
object edtNotification: TWebEdit
Left = 14
Top = 24
Width = 457
Height = 22
HelpType = htKeyword
TabStop = False
ChildOrder = 8
ElementClassName = 'form-control'
ElementFont = efCSS
Enabled = False
Font.Charset = ANSI_CHARSET
Font.Color = clBlack
Font.Height = -8
Font.Name = 'Arial'
Font.Style = []
HeightPercent = 100.000000000000000000
HideSelection = False
ParentFont = False
TabOrder = 1
WidthPercent = 100.000000000000000000
end
object edtJobName: TWebEdit
Left = 172
Top = 100
Left = 174
Top = 52
Width = 145
Height = 22
HelpType = htKeyword
......@@ -304,8 +282,8 @@ object FSetStatus: TFSetStatus
WidthPercent = 100.000000000000000000
end
object dtpShipDue: TWebDateTimePicker
Left = 11
Top = 162
Left = 13
Top = 114
Width = 145
Height = 22
BorderStyle = bsSingle
......@@ -317,8 +295,8 @@ object FSetStatus: TFSetStatus
Text = ''
end
object dtpNewShipDue: TWebDateTimePicker
Left = 169
Top = 162
Left = 171
Top = 114
Width = 145
Height = 22
BorderStyle = bsSingle
......@@ -329,8 +307,8 @@ object FSetStatus: TFSetStatus
Text = ''
end
object dtpMountDue: TWebDateTimePicker
Left = 324
Top = 220
Left = 326
Top = 172
Width = 145
Height = 22
BorderStyle = bsSingle
......@@ -342,8 +320,8 @@ object FSetStatus: TFSetStatus
Text = ''
end
object dtpNewMountDue: TWebDateTimePicker
Left = 482
Top = 220
Left = 484
Top = 172
Width = 145
Height = 22
BorderStyle = bsSingle
......@@ -354,8 +332,8 @@ object FSetStatus: TFSetStatus
Text = ''
end
object dtpPlateDue: TWebDateTimePicker
Left = 11
Top = 220
Left = 13
Top = 172
Width = 145
Height = 22
BorderStyle = bsSingle
......@@ -367,8 +345,8 @@ object FSetStatus: TFSetStatus
Text = ''
end
object dtpNewPlateDue: TWebDateTimePicker
Left = 169
Top = 220
Left = 171
Top = 172
Width = 145
Height = 22
BorderStyle = bsSingle
......@@ -379,8 +357,8 @@ object FSetStatus: TFSetStatus
Text = ''
end
object dtpArtDue: TWebDateTimePicker
Left = 324
Top = 162
Left = 326
Top = 114
Width = 145
Height = 22
BorderStyle = bsSingle
......@@ -392,8 +370,8 @@ object FSetStatus: TFSetStatus
Text = ''
end
object dtpNewArtDue: TWebDateTimePicker
Left = 482
Top = 162
Left = 484
Top = 114
Width = 145
Height = 22
BorderStyle = bsSingle
......
......@@ -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)
......@@ -17,7 +17,6 @@ type
btnCancel: TWebButton;
WebLabel2: TWebLabel;
edtOrderID: TWebEdit;
edtNotification: TWebEdit;
edtJobName: TWebEdit;
WebLabel3: TWebLabel;
WebLabel4: TWebLabel;
......@@ -41,8 +40,6 @@ type
procedure btnCancelClick(Sender: TObject);
private
{ Private declarations }
procedure HideNotification;
procedure ShowNotification(Notification: string);
public
{ Public declarations }
confirm: boolean;
......@@ -65,14 +62,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 +81,6 @@ var
i: integer;
filteredItems: TJSArray;
begin
HideNotification();
edtOrderID.Text := OrderID;
dtpDate.Date := 0;
edtJobName.Text := JobName;
......@@ -137,17 +134,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
<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,81 +39,92 @@ 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
asm
var messageDiv = document.getElementById('view.login.message');
messageDiv.classList.remove('alert-success');
messageDiv.classList.add('alert-danger');
end;
if CheckInputs() then
FormEl := TJSHTMLFormElement(document.querySelector('form'));
if not FormEl.checkValidity then
begin
EditUser();
end
FormEl.classList.add('was-validated');
Exit;
end;
ShowConfirmationModal(
'Are you sure you want to save changes to your profile?',
'Save',
'Cancel',
procedure(confirmed: Boolean)
begin
if confirmed then
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);
var
xdcResponse: TXDataClientResponse;
userList: TJSObject;
data: TJSArray;
user: TJSObject;
procedure TFViewUserProfile.btnCancelClick(Sender: TObject);
begin
GetUser();
showNotification('Failure:Changes discarded');
ShowConfirmationModal(
'Are you sure you want to cancel all your changes?',
'Yes',
'No',
procedure(confirmed: Boolean)
begin
if confirmed then
begin
GetUser();
ShowToast('Changes discarded', 'danger');
end;
end
);
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;
var
xdcResponse: TXDataClientResponse;
......@@ -129,139 +132,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>
......@@ -47,22 +43,5 @@
</div>
</div>
</div>
<!--</div> -->
<!--</div> -->
<div class="modal fade" id="confirmation_modal" tabindex="-1" aria-labelledby="confirmation_modal_label" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<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">
Are you sure you want to make these changes?
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Cancel</button>
<button type="button" class="btn btn-primary" data-bs-dismiss="modal" id="btn_confirm_delete" >Confirm</button>
</div>
</div>
</div>
</div>
......@@ -6,7 +6,7 @@ uses
System.SysUtils, System.Classes, Web, WEBLib.Graphics, WEBLib.Forms, WEBLib.Dialogs,
Vcl.Controls, Vcl.StdCtrls, WEBLib.StdCtrls, WEBLib.Controls, WEBLib.Grids, WebLib.Lists,
XData.Web.Client, WEBLib.ExtCtrls, DB, XData.Web.JsonDataset,
XData.Web.Dataset, XData.Web.Connection, Vcl.Forms, WEBLib.DBCtrls, JS;
XData.Web.Dataset, XData.Web.Connection, Vcl.Forms, WEBLib.DBCtrls, JS, Utils;
type
TFViewUsers = class(TWebForm)
......@@ -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;
......@@ -330,44 +321,50 @@ var
data: TJSArray;
user: TJSObject;
userListLength: integer;
begin
if PageNumber > 0 then
begin
xdcResponse := await(XDataWebClient1.RawInvokeAsync('ILookupService.GetUsers',
[searchOptions]));
userList := TJSObject(xdcResponse.Result);
data := TJSArray(userList['data']);
userListLength := integer(userList['count']);
ClearTable();
XDataWebDataSet1.Close;
XDataWebDataSet1.SetJsonData(userList['data']);
XDataWebDataSet1.Open;
for i := 0 to data.Length - 1 do
begin
user := TJSObject(data[i]);
AddRowToTable(XDataWebDataSet1userID.AsString, XDataWebDataSet1username.AsString,
XDataWebDataSet1password.AsString, XDataWebDataSet1full_name.AsString,
XDataWebDataSet1status.AsString, XDataWebDataSet1email_address.AsString,
XDataWebDataSet1Atype.AsString, XDataWebDataSet1perspectiveID.AsString,
XDataWebDataSet1QBID.AsString, XDataWebDataSet1rights.AsInteger);
XDataWebDataSet1.Next;
end;
TotalPages := (userListLength + PageSize - 1) div PageSize;
if (PageNumber * PageSize) < userListLength then
begin
lblEntries.Caption := 'Showing entries ' + IntToStr((PageNumber - 1) * PageSize + 1) +
' - ' + IntToStr(PageNumber * PageSize) +
' of ' + IntToStr(userListLength);
end
else
begin
lblEntries.Caption := 'Showing entries ' + IntToStr((PageNumber - 1) * PageSize + 1) +
' - ' + IntToStr(userListLength) +
' of ' + IntToStr(userListLength);
Utils.ShowSpinner('spinner');
try
xdcResponse := await(XDataWebClient1.RawInvokeAsync('ILookupService.GetUsers',
[searchOptions]));
userList := TJSObject(xdcResponse.Result);
data := TJSArray(userList['data']);
userListLength := integer(userList['count']);
ClearTable();
XDataWebDataSet1.Close;
XDataWebDataSet1.SetJsonData(userList['data']);
XDataWebDataSet1.Open;
for i := 0 to data.Length - 1 do
begin
user := TJSObject(data[i]);
AddRowToTable(XDataWebDataSet1userID.AsString, XDataWebDataSet1username.AsString,
XDataWebDataSet1password.AsString, XDataWebDataSet1full_name.AsString,
XDataWebDataSet1status.AsString, XDataWebDataSet1email_address.AsString,
XDataWebDataSet1Atype.AsString, XDataWebDataSet1perspectiveID.AsString,
XDataWebDataSet1QBID.AsString, XDataWebDataSet1rights.AsInteger);
XDataWebDataSet1.Next;
end;
TotalPages := (userListLength + PageSize - 1) div PageSize;
if (PageNumber * PageSize) < userListLength then
begin
lblEntries.Caption := 'Showing entries ' + IntToStr((PageNumber - 1) * PageSize + 1) +
' - ' + IntToStr(PageNumber * PageSize) +
' of ' + IntToStr(userListLength);
end
else
begin
lblEntries.Caption := 'Showing entries ' + IntToStr((PageNumber - 1) * PageSize + 1) +
' - ' + IntToStr(userListLength) +
' of ' + IntToStr(userListLength);
end;
GeneratePagination(TotalPages);
except
on E: EXDataClientRequestException do
Utils.ShowErrorModal('Could not retrieve users: ' + E.ErrorResult.ErrorMessage);
end;
GeneratePagination(TotalPages);
Utils.HideSpinner('spinner');
end;
end;
......@@ -443,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
......@@ -462,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
......
This source diff could not be displayed because it is too large. You can view the blob instead.
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