unit View.Customers; 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, XData.Web.JsonDataset, WEBLib.DB, Data.DB, XData.Web.Dataset, WEBLib.Grids; type TFViewCustomers = class(TWebForm) lblEntries: TWebLabel; btnAddCustomer: TWebButton; wdbtcCustomers: TWebDBTableControl; wcbPageSize: TWebComboBox; pnlMessage: TWebPanel; lblMessage: TWebLabel; btnCloseNotification: TWebButton; XDataWebClient1: TXDataWebClient; wdsCustomers: TWebDataSource; xdwdsCustomers: TXDataWebDataSet; xdwdsCustomersNAME: TStringField; xdwdsCustomersSTART_DATE: TStringField; procedure WebFormCreate(Sender: TObject); private { Private declarations } procedure GeneratePagination(TotalPages: Integer); [async] procedure GetCustomers(searchOptions: string); function GenerateSearchOptions(): string; procedure HideNotification(); procedure ShowNotification(Notification: string); var PageNumber: integer; PageSize: integer; TotalPages: integer; info: string; public { Public declarations } end; var FViewCustomers: TFViewCustomers; implementation uses XData.Model.Classes, View.Main; {$R *.dfm} Procedure TFViewCustomers.WebFormCreate(Sender: TObject); // Initializes important values: // PageNumber: What page number the user is on IE 1: 1-10, 2: 11-20 etc // TotalPages: Total number of pages returned from the search. // PageSize: Number of entries per page. var today: TDateTime; begin DMConnection.ApiConnection.Connected := True; PageNumber := 1; TotalPages := 1; // Initial total pages wcbPageSize.Text := '500'; PageSize := 500; HideNotification(); getCustomers(GenerateSearchOptions()); end; procedure TFViewCustomers.GetCustomers(searchOptions: string); // retrieves a list of Customers that fit a given search criteria // searchOptions: search info to be sent to the server var xdcResponse: TXDataClientResponse; customerList: TJSObject; customerListLength: integer; TotalPages: integer; begin if PageNumber > 0 then begin asm startSpinner(); end; xdcResponse := await(XDataWebClient1.RawInvokeAsync('ILookupService.GetCustomers', [searchOptions])); customerList := TJSObject(xdcResponse.Result); // Load data into the dataset xdwdsCustomers.Close; xdwdsCustomers.SetJsonData(customerList['data']); xdwdsCustomers.Open; asm endSpinner(); end; 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 begin lblEntries.Caption := 'Showing entries ' + IntToStr((PageNumber - 1) * PageSize + 1) + ' - ' + IntToStr(PageNumber * PageSize) + ' 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); end; // Optional: Continue using pagination if needed GeneratePagination(TotalPages); end; end; function TFViewCustomers.GenerateSearchOptions(): string; // Generates searchOptions for GetOrders. var searchOptions: string; begin searchOptions := '&pagenumber=' + IntToStr(PageNumber) + '&pagesize=' + IntToStr(PageSize); Result := searchOptions; end; procedure TFViewCustomers.HideNotification; begin pnlMessage.ElementHandle.hidden := True; info := ''; end; procedure TFViewCustomers.ShowNotification(Notification: string); var splitNotification: TArray<string>; begin if Notification <> '' then begin splitNotification := Notification.Split([':']); if(splitNotification[0] = 'Success') then begin asm var messageDiv = document.getElementById('view.login.message'); messageDiv.classList.remove('alert-danger'); messageDiv.classList.add('alert-success'); end; end else begin asm var messageDiv = document.getElementById('view.login.message'); messageDiv.classList.remove('alert-success'); messageDiv.classList.add('alert-danger'); end; end; lblMessage.Caption := splitNotification[1]; pnlMessage.ElementHandle.hidden := False; end; end; procedure TFViewCustomers.GeneratePagination(TotalPages: Integer); // Generates pagination for the table. // TotalPages: Total amount of pages generated by the search var PaginationElement, PageItem, PageLink: TJSHTMLElement; I, Start, Finish: Integer; begin PaginationElement := TJSHTMLElement(document.getElementById('pagination')); PaginationElement.innerHTML := ''; // Clear existing pagination // Previous Button PageItem := TJSHTMLElement(document.createElement('li')); PageItem.className := 'page-item'; if PageNumber = 1 then PageItem.classList.add('disabled'); PageLink := TJSHTMLElement(document.createElement('a')); PageLink.className := 'page-link'; PageLink.innerText := 'Previous'; PageLink.setAttribute('href', 'javascript:void(0)'); PageLink.addEventListener('click', procedure(Event: TJSMouseEvent) begin if PageNumber > 1 then begin Dec(PageNumber); GetCustomers(GenerateSearchOptions()); end; end); PageItem.appendChild(PageLink); PaginationElement.appendChild(PageItem); // Page Numbers if TotalPages <= 7 then begin for I := 1 to 7 do begin if I <= TotalPages then begin PageItem := TJSHTMLElement(document.createElement('li')); PageItem.className := 'page-item'; if I = PageNumber then PageItem.classList.add('selected-number'); // Add the selected-number class PageLink := TJSHTMLElement(document.createElement('a')); PageLink.className := 'page-link'; PageLink.innerText := IntToStr(I); PageLink.setAttribute('href', 'javascript:void(0)'); PageLink.addEventListener('click', procedure(Event: TJSMouseEvent) var PageNum: Integer; begin PageNum := StrToInt((Event.currentTarget as TJSHTMLElement).innerText); PageNumber := PageNum; GetCustomers(GenerateSearchOptions()); end); PageItem.appendChild(PageLink); PaginationElement.appendChild(PageItem); end; end; end else begin if PageNumber <= 4 then // If page number is low enough no early elipsis needed Begin Start := 2; Finish := 5; End else if (PageNumber >= (TotalPages - 3)) then // If page number is high enough no late elipsis needed begin Start := TotalPages - 3; Finish := TotalPages - 1; end else begin Start := PageNumber - 1; Finish := PageNumber + 1; end; PageItem := TJSHTMLElement(document.createElement('li')); PageItem.className := 'page-item'; if 1 = PageNumber then PageItem.classList.add('selected-number'); // Add the selected-number class PageLink := TJSHTMLElement(document.createElement('a')); PageLink.className := 'page-link'; PageLink.innerText := '1'; PageLink.setAttribute('href', 'javascript:void(0)'); PageLink.addEventListener('click', procedure(Event: TJSMouseEvent) var PageNum: Integer; begin PageNum := StrToInt((Event.currentTarget as TJSHTMLElement).innerText); PageNumber := PageNum; GetCustomers(GenerateSearchOptions()); end); PageItem.appendChild(PageLink); PaginationElement.appendChild(PageItem); // Adds Elipse to pagination if page number is too big if PageNumber > 4 then begin PageItem := TJSHTMLElement(document.createElement('li')); PageItem.className := 'page-item'; PageItem.classList.add('disabled'); PageLink := TJSHTMLElement(document.createElement('a')); PageLink.className := 'page-link'; PageLink.innerText := '...'; PageLink.setAttribute('href', 'javascript:void(0)'); PageItem.appendChild(PageLink); PaginationElement.appendChild(PageItem); end; // Adds Page, page - 1, and page + 1 to pagination for I := Start to Finish do begin if ( I > 1) and (I < TotalPages) then begin PageItem := TJSHTMLElement(document.createElement('li')); PageItem.className := 'page-item'; if I = PageNumber then PageItem.classList.add('selected-number'); // Add the selected-number class PageLink := TJSHTMLElement(document.createElement('a')); PageLink.className := 'page-link'; PageLink.innerText := IntToStr(I); PageLink.setAttribute('href', 'javascript:void(0)'); PageLink.addEventListener('click', procedure(Event: TJSMouseEvent) var PageNum: Integer; begin PageNum := StrToInt((Event.currentTarget as TJSHTMLElement).innerText); PageNumber := PageNum; GetCustomers(GenerateSearchOptions()); end); PageItem.appendChild(PageLink); PaginationElement.appendChild(PageItem); end; end; // adds ellipse if number is too small if PageNumber < TotalPages - 4 then begin PageItem := TJSHTMLElement(document.createElement('li')); PageItem.className := 'page-item'; PageItem.classList.add('disabled'); PageLink := TJSHTMLElement(document.createElement('a')); PageLink.className := 'page-link'; PageLink.innerText := '...'; PageLink.setAttribute('href', 'javascript:void(0)'); PageItem.appendChild(PageLink); PaginationElement.appendChild(PageItem); end; if TotalPages <> 1 then begin PageItem := TJSHTMLElement(document.createElement('li')); PageItem.className := 'page-item'; if TotalPages = PageNumber then PageItem.classList.add('selected-number'); PageLink := TJSHTMLElement(document.createElement('a')); PageLink.className := 'page-link'; PageLink.innerText := IntToStr(TotalPages); PageLink.setAttribute('href', 'javascript:void(0)'); PageLink.addEventListener('click', procedure(Event: TJSMouseEvent) var PageNum: Integer; begin PageNum := StrToInt((Event.currentTarget as TJSHTMLElement).innerText); PageNumber := PageNum; GetCustomers(generateSearchOptions()); end); end; PageItem.appendChild(PageLink); PaginationElement.appendChild(PageItem); end; // Next Button PageItem := TJSHTMLElement(document.createElement('li')); PageItem.className := 'page-item'; if PageNumber = TotalPages then PageItem.classList.add('disabled'); PageLink := TJSHTMLElement(document.createElement('a')); PageLink.className := 'page-link'; PageLink.innerText := 'Next'; PageLink.setAttribute('href', 'javascript:void(0)'); PageLink.addEventListener('click', procedure(Event: TJSMouseEvent) begin if PageNumber < TotalPages then begin Inc(PageNumber); GetCustomers(GenerateSearchOptions()); end; end); PageItem.appendChild(PageLink); PaginationElement.appendChild(PageItem); end; end.