Commit d011eb7b by Mac Stephens

Connected to entcad database, uniqueries created with all fields, initial…

Connected to entcad database, uniqueries created with all fields, initial complaint list endpoint created, cleaned up more envoy calls issues
parent 6fa13c63
object ApiDatabaseModule: TApiDatabaseModule object ApiDatabaseModule: TApiDatabaseModule
OnCreate = DataModuleCreate OnCreate = DataModuleCreate
Height = 480 Height = 491
Width = 640 Width = 640
object ucEnvoy: TUniConnection object ucEnvoy: TUniConnection
ProviderName = 'PostgreSQL' ProviderName = 'PostgreSQL'
...@@ -21,27 +21,16 @@ object ApiDatabaseModule: TApiDatabaseModule ...@@ -21,27 +21,16 @@ object ApiDatabaseModule: TApiDatabaseModule
Left = 363 Left = 363
Top = 138 Top = 138
end end
object ucBooking: TUniConnection
ProviderName = 'Oracle'
Database = 'EMBOOKING'
Username = 'emBooking'
Server = 'EMBOOK-CPS'
LoginPrompt = False
Left = 77
Top = 231
EncryptedPassword = '9AFF92FF9DFF90FF90FF94FFCFFFCEFF'
end
object OracleUniProvider1: TOracleUniProvider object OracleUniProvider1: TOracleUniProvider
Left = 226 Left = 226
Top = 236 Top = 236
end end
object uqBooking: TUniQuery object uqBooking: TUniQuery
Connection = ucBooking
Left = 374 Left = 374
Top = 222 Top = 222
end end
object uqUnitsCurrent: TUniQuery object uqUnitsCurrent: TUniQuery
Connection = ucBooking Connection = ucENTCAD
SQL.Strings = ( SQL.Strings = (
'SELECT' 'SELECT'
' uc.ENTRYID,' ' uc.ENTRYID,'
...@@ -51,11 +40,32 @@ object ApiDatabaseModule: TApiDatabaseModule ...@@ -51,11 +40,32 @@ object ApiDatabaseModule: TApiDatabaseModule
' uc.GPS_LATITUDE,' ' uc.GPS_LATITUDE,'
' uc.GPS_LONGITUDE' ' uc.GPS_LONGITUDE'
'FROM UNITS_CURRENT@AVL_LINK uc') 'FROM UNITS_CURRENT@AVL_LINK uc')
ReadOnly = True
Left = 462 Left = 462
Top = 324 Top = 324
object uqUnitsCurrentENTRYID: TFloatField
FieldName = 'ENTRYID'
end
object uqUnitsCurrentUNITID: TFloatField
FieldName = 'UNITID'
end
object uqUnitsCurrentUNITNAME: TStringField
FieldName = 'UNITNAME'
ReadOnly = True
end
object uqUnitsCurrentUNIT_DISTRICT: TStringField
FieldName = 'UNIT_DISTRICT'
Size = 8
end
object uqUnitsCurrentGPS_LATITUDE: TFloatField
FieldName = 'GPS_LATITUDE'
end
object uqUnitsCurrentGPS_LONGITUDE: TFloatField
FieldName = 'GPS_LONGITUDE'
end
end end
object uqDISUnitsActive: TUniQuery object uqDISUnitsActive: TUniQuery
Connection = ucBooking Connection = ucENTCAD
SQL.Strings = ( SQL.Strings = (
'SELECT' 'SELECT'
' dua.UNITID,' ' dua.UNITID,'
...@@ -103,11 +113,104 @@ object ApiDatabaseModule: TApiDatabaseModule ...@@ -103,11 +113,104 @@ object ApiDatabaseModule: TApiDatabaseModule
'LEFT JOIN UNITS_CURRENT@AVL_LINK uc ON dua.UNITID = uc.UNI' + 'LEFT JOIN UNITS_CURRENT@AVL_LINK uc ON dua.UNITID = uc.UNI' +
'TID') 'TID')
ReadOnly = True
Left = 462 Left = 462
Top = 374 Top = 374
object uqDISUnitsActiveUNITID: TFloatField
FieldName = 'UNITID'
end
object uqDISUnitsActiveUNITNAME: TStringField
FieldName = 'UNITNAME'
Size = 10
end
object uqDISUnitsActiveCARNUMBER_DESC: TStringField
FieldName = 'CARNUMBER_DESC'
ReadOnly = True
Size = 120
end
object uqDISUnitsActiveDISTRICT_DESC: TStringField
FieldName = 'DISTRICT_DESC'
ReadOnly = True
Size = 120
end
object uqDISUnitsActiveSECTOR_DESC: TStringField
FieldName = 'SECTOR_DESC'
ReadOnly = True
Size = 120
end
object uqDISUnitsActiveOFFICER1_EMPNUM: TStringField
FieldName = 'OFFICER1_EMPNUM'
ReadOnly = True
Size = 10
end
object uqDISUnitsActiveOFFICER1_LAST_NAME: TStringField
FieldName = 'OFFICER1_LAST_NAME'
ReadOnly = True
Size = 45
end
object uqDISUnitsActiveOFFICER1_FIRST_NAME: TStringField
FieldName = 'OFFICER1_FIRST_NAME'
ReadOnly = True
Size = 30
end
object uqDISUnitsActiveOFFICER1_MI: TStringField
FieldName = 'OFFICER1_MI'
ReadOnly = True
Size = 1
end
object uqDISUnitsActiveOFFICER2_EMPNUM: TStringField
FieldName = 'OFFICER2_EMPNUM'
ReadOnly = True
Size = 10
end
object uqDISUnitsActiveOFFICER2_LAST_NAME: TStringField
FieldName = 'OFFICER2_LAST_NAME'
ReadOnly = True
Size = 45
end
object uqDISUnitsActiveOFFICER2_FIRST_NAME: TStringField
FieldName = 'OFFICER2_FIRST_NAME'
ReadOnly = True
Size = 30
end
object uqDISUnitsActiveOFFICER2_MI: TStringField
FieldName = 'OFFICER2_MI'
ReadOnly = True
Size = 1
end
object uqDISUnitsActiveLOCATION: TStringField
FieldName = 'LOCATION'
ReadOnly = True
Size = 30
end
object uqDISUnitsActiveCOMPLAINT: TStringField
FieldName = 'COMPLAINT'
ReadOnly = True
Size = 10
end
object uqDISUnitsActiveUNITSTATUS: TFloatField
FieldName = 'UNITSTATUS'
ReadOnly = True
end
object uqDISUnitsActiveUNIT_STATUS_DESC: TStringField
FieldName = 'UNIT_STATUS_DESC'
ReadOnly = True
end
object uqDISUnitsActiveENTRYID: TFloatField
FieldName = 'ENTRYID'
ReadOnly = True
end
object uqDISUnitsActiveGPS_LATITUDE: TFloatField
FieldName = 'GPS_LATITUDE'
ReadOnly = True
end
object uqDISUnitsActiveGPS_LONGITUDE: TFloatField
FieldName = 'GPS_LONGITUDE'
ReadOnly = True
end
end end
object uqCFSActive: TUniQuery object uqCFSActive: TUniQuery
Connection = ucBooking Connection = ucENTCAD
SQL.Strings = ( SQL.Strings = (
'SELECT' 'SELECT'
' ca.COMPLAINTID,' ' ca.COMPLAINTID,'
...@@ -121,17 +224,44 @@ object ApiDatabaseModule: TApiDatabaseModule ...@@ -121,17 +224,44 @@ object ApiDatabaseModule: TApiDatabaseModule
'FROM CFS_ACTIVE ca' 'FROM CFS_ACTIVE ca'
'WHERE ca.COMPLAINTID = :COMPLAINTID' 'WHERE ca.COMPLAINTID = :COMPLAINTID'
'ORDER BY ca.DATEDISPATCHED') 'ORDER BY ca.DATEDISPATCHED')
ReadOnly = True
Left = 278 Left = 278
Top = 318 Top = 318
ParamData = < ParamData = <
item item
DataType = ftUnknown DataType = ftUnknown
Name = 'COMPLAINTID' Name = 'COMPLAINTID'
Value = nil Value = Null
end> end>
object uqCFSActiveCOMPLAINTID: TFloatField
FieldName = 'COMPLAINTID'
end
object uqCFSActiveUNITID: TFloatField
FieldName = 'UNITID'
end
object uqCFSActiveUNITNAME: TStringField
FieldName = 'UNITNAME'
Size = 10
end
object uqCFSActiveDATEDISPATCHED: TDateTimeField
FieldName = 'DATEDISPATCHED'
end
object uqCFSActiveDATERESPONDED: TDateTimeField
FieldName = 'DATERESPONDED'
end
object uqCFSActiveDATEARRIVED: TDateTimeField
FieldName = 'DATEARRIVED'
end
object uqCFSActiveDATECLEARED: TDateTimeField
FieldName = 'DATECLEARED'
end
object uqCFSActiveLOCATION: TStringField
FieldName = 'LOCATION'
Size = 30
end
end end
object uqCFSMemos: TUniQuery object uqCFSMemos: TUniQuery
Connection = ucBooking Connection = ucENTCAD
SQL.Strings = ( SQL.Strings = (
'SELECT' 'SELECT'
' cm.MEMO_ID,' ' cm.MEMO_ID,'
...@@ -143,19 +273,40 @@ object ApiDatabaseModule: TApiDatabaseModule ...@@ -143,19 +273,40 @@ object ApiDatabaseModule: TApiDatabaseModule
'FROM CFS_MEMOS cm' 'FROM CFS_MEMOS cm'
'WHERE cm.CFSID = :CFSID' 'WHERE cm.CFSID = :CFSID'
'ORDER BY cm.TIMESTAMP ASC') 'ORDER BY cm.TIMESTAMP ASC')
ReadOnly = True
Left = 282 Left = 282
Top = 376 Top = 376
ParamData = < ParamData = <
item item
DataType = ftUnknown DataType = ftUnknown
Name = 'CFSID' Name = 'CFSID'
Value = nil Value = Null
end> end>
object uqCFSMemosMEMO_ID: TFloatField
FieldName = 'MEMO_ID'
Required = True
end
object uqCFSMemosCFSID: TFloatField
FieldName = 'CFSID'
end
object uqCFSMemosMEMO_TYPE: TFloatField
FieldName = 'MEMO_TYPE'
end
object uqCFSMemosTIMESTAMP: TDateTimeField
FieldName = 'TIMESTAMP'
end
object uqCFSMemosBADGE_NUMBER: TStringField
FieldName = 'BADGE_NUMBER'
Size = 6
end
object uqCFSMemosREMARKS: TStringField
FieldName = 'REMARKS'
Size = 2048
end
end end
object uqComplaintList: TUniQuery object uqComplaintList: TUniQuery
Connection = ucBooking Connection = ucENTCAD
SQL.Strings = ( SQL.Strings = (
'-- uqComplaintActive_List'
'SELECT' 'SELECT'
' ca.COMPLAINTID,' ' ca.COMPLAINTID,'
' ca.CFSID,' ' ca.CFSID,'
...@@ -190,12 +341,120 @@ object ApiDatabaseModule: TApiDatabaseModule ...@@ -190,12 +341,120 @@ object ApiDatabaseModule: TApiDatabaseModule
'LEFT JOIN CD_DISPATCHCODES cdc ON ca.DISPATCHCODE = cdc.CODE' 'LEFT JOIN CD_DISPATCHCODES cdc ON ca.DISPATCHCODE = cdc.CODE'
'LEFT JOIN CD_CALLSOURCES ccs ON ca.SOURCE = ccs.CODE' 'LEFT JOIN CD_CALLSOURCES ccs ON ca.SOURCE = ccs.CODE'
'WHERE ca.COMPLAINT IS NOT NULL' 'WHERE ca.COMPLAINT IS NOT NULL'
'ORDER BY ct.DATEREPORTED DESC, ca.PRIORITY DESC') 'ORDER BY ct.DATEREPORTED DESC, ca.PRIORITY DESC'
'FETCH FIRST 10 ROWS ONLY')
ReadOnly = True
Left = 76 Left = 76
Top = 320 Top = 322
object uqComplaintListCOMPLAINTID: TFloatField
FieldName = 'COMPLAINTID'
Required = True
end
object uqComplaintListCFSID: TFloatField
FieldName = 'CFSID'
end
object uqComplaintListCOMPLAINT: TStringField
FieldName = 'COMPLAINT'
Size = 10
end
object uqComplaintListAGENCY: TStringField
FieldName = 'AGENCY'
Size = 6
end
object uqComplaintListDISPATCH_CODE_DESC: TStringField
FieldName = 'DISPATCH_CODE_DESC'
ReadOnly = True
Size = 60
end
object uqComplaintListSOURCE: TStringField
FieldName = 'SOURCE'
Size = 6
end
object uqComplaintListSOURCE_DESC: TStringField
FieldName = 'SOURCE_DESC'
ReadOnly = True
Size = 120
end
object uqComplaintListPRIORITY: TStringField
FieldName = 'PRIORITY'
Size = 6
end
object uqComplaintListADDRESSID: TFloatField
FieldName = 'ADDRESSID'
end
object uqComplaintListADDRESS: TStringField
FieldName = 'ADDRESS'
Size = 64
end
object uqComplaintListAPARTMENT: TStringField
FieldName = 'APARTMENT'
Size = 6
end
object uqComplaintListCITY: TStringField
FieldName = 'CITY'
end
object uqComplaintListBUSINESS: TStringField
FieldName = 'BUSINESS'
Size = 35
end
object uqComplaintListDISPATCHDISTRICT: TStringField
FieldName = 'DISPATCHDISTRICT'
Size = 6
end
object uqComplaintListDISPATCHSECTOR: TStringField
FieldName = 'DISPATCHSECTOR'
Size = 6
end
object uqComplaintListADDRESSDISTRICT: TStringField
FieldName = 'ADDRESSDISTRICT'
Size = 5
end
object uqComplaintListADDRESSSECTOR: TStringField
FieldName = 'ADDRESSSECTOR'
Size = 5
end
object uqComplaintListXCOORD: TFloatField
FieldName = 'XCOORD'
end
object uqComplaintListYCOORD: TFloatField
FieldName = 'YCOORD'
end
object uqComplaintListWARNINGS: TFloatField
FieldName = 'WARNINGS'
end
object uqComplaintListCONTACTS: TFloatField
FieldName = 'CONTACTS'
end
object uqComplaintListHISTORY: TFloatField
FieldName = 'HISTORY'
end
object uqComplaintListDATEREPORTED: TDateTimeField
FieldName = 'DATEREPORTED'
ReadOnly = True
end
object uqComplaintListDATERECEIVED: TDateTimeField
FieldName = 'DATERECEIVED'
ReadOnly = True
end
object uqComplaintListDATEDISPATCHED: TDateTimeField
FieldName = 'DATEDISPATCHED'
ReadOnly = True
end
object uqComplaintListDATERESPONDED: TDateTimeField
FieldName = 'DATERESPONDED'
ReadOnly = True
end
object uqComplaintListDATEARRIVED: TDateTimeField
FieldName = 'DATEARRIVED'
ReadOnly = True
end
object uqComplaintListDATECLEARED: TDateTimeField
FieldName = 'DATECLEARED'
ReadOnly = True
end
end end
object uqComplaintDetails: TUniQuery object uqComplaintDetails: TUniQuery
Connection = ucBooking Connection = ucENTCAD
SQL.Strings = ( SQL.Strings = (
'-- uqComplaintActive_Detail' '-- uqComplaintActive_Detail'
'SELECT' 'SELECT'
...@@ -233,13 +492,134 @@ object ApiDatabaseModule: TApiDatabaseModule ...@@ -233,13 +492,134 @@ object ApiDatabaseModule: TApiDatabaseModule
'LEFT JOIN CD_DISPATCHCODES cdc ON ca.DISPATCHCODE = cdc.CODE' 'LEFT JOIN CD_DISPATCHCODES cdc ON ca.DISPATCHCODE = cdc.CODE'
'LEFT JOIN CD_CALLSOURCES ccs ON ca.SOURCE = ccs.CODE' 'LEFT JOIN CD_CALLSOURCES ccs ON ca.SOURCE = ccs.CODE'
'WHERE ca.COMPLAINTID = :COMPLAINTID') 'WHERE ca.COMPLAINTID = :COMPLAINTID')
ReadOnly = True
Left = 74 Left = 74
Top = 376 Top = 376
ParamData = < ParamData = <
item item
DataType = ftUnknown DataType = ftUnknown
Name = 'COMPLAINTID' Name = 'COMPLAINTID'
Value = nil Value = Null
end> end>
object uqComplaintDetailsCOMPLAINTID: TFloatField
FieldName = 'COMPLAINTID'
Required = True
end
object uqComplaintDetailsCFSID: TFloatField
FieldName = 'CFSID'
end
object uqComplaintDetailsCOMPLAINT: TStringField
FieldName = 'COMPLAINT'
Size = 10
end
object uqComplaintDetailsAGENCY: TStringField
FieldName = 'AGENCY'
Size = 6
end
object uqComplaintDetailsDISPATCHCODE: TStringField
FieldName = 'DISPATCHCODE'
Size = 6
end
object uqComplaintDetailsDISPATCH_CODE_DESC: TStringField
FieldName = 'DISPATCH_CODE_DESC'
ReadOnly = True
Size = 60
end
object uqComplaintDetailsSOURCE: TStringField
FieldName = 'SOURCE'
Size = 6
end
object uqComplaintDetailsSOURCE_DESC: TStringField
FieldName = 'SOURCE_DESC'
ReadOnly = True
Size = 120
end
object uqComplaintDetailsPRIORITY: TStringField
FieldName = 'PRIORITY'
Size = 6
end
object uqComplaintDetailsADDRESSID: TFloatField
FieldName = 'ADDRESSID'
end
object uqComplaintDetailsADDRESS: TStringField
FieldName = 'ADDRESS'
Size = 64
end
object uqComplaintDetailsAPARTMENT: TStringField
FieldName = 'APARTMENT'
Size = 6
end
object uqComplaintDetailsCITY: TStringField
FieldName = 'CITY'
end
object uqComplaintDetailsBUSINESS: TStringField
FieldName = 'BUSINESS'
Size = 35
end
object uqComplaintDetailsDISPATCHDISTRICT: TStringField
FieldName = 'DISPATCHDISTRICT'
Size = 6
end
object uqComplaintDetailsDISPATCHSECTOR: TStringField
FieldName = 'DISPATCHSECTOR'
Size = 6
end
object uqComplaintDetailsADDRESSDISTRICT: TStringField
FieldName = 'ADDRESSDISTRICT'
Size = 5
end
object uqComplaintDetailsADDRESSSECTOR: TStringField
FieldName = 'ADDRESSSECTOR'
Size = 5
end
object uqComplaintDetailsXCOORD: TFloatField
FieldName = 'XCOORD'
end
object uqComplaintDetailsYCOORD: TFloatField
FieldName = 'YCOORD'
end
object uqComplaintDetailsWARNINGS: TFloatField
FieldName = 'WARNINGS'
end
object uqComplaintDetailsCONTACTS: TFloatField
FieldName = 'CONTACTS'
end
object uqComplaintDetailsHISTORY: TFloatField
FieldName = 'HISTORY'
end
object uqComplaintDetailsDATEREPORTED: TDateTimeField
FieldName = 'DATEREPORTED'
ReadOnly = True
end
object uqComplaintDetailsDATERECEIVED: TDateTimeField
FieldName = 'DATERECEIVED'
ReadOnly = True
end
object uqComplaintDetailsDATEDISPATCHED: TDateTimeField
FieldName = 'DATEDISPATCHED'
ReadOnly = True
end
object uqComplaintDetailsDATERESPONDED: TDateTimeField
FieldName = 'DATERESPONDED'
ReadOnly = True
end
object uqComplaintDetailsDATEARRIVED: TDateTimeField
FieldName = 'DATEARRIVED'
ReadOnly = True
end
object uqComplaintDetailsDATECLEARED: TDateTimeField
FieldName = 'DATECLEARED'
ReadOnly = True
end
end
object ucENTCAD: TUniConnection
ProviderName = 'Oracle'
Port = 1521
Username = 'ENTCAD'
Server = 'BUFENTCAD'
LoginPrompt = False
Left = 76
Top = 244
EncryptedPassword = 'BAFFB1FFABFFBCFFBEFFBBFF'
end end
end end
// Where the database is kept. Only used by Lookup.ServiceImpl to retrieve info
// from the data base and send it to the client.
// Author: ???
unit Api.Database; unit Api.Database;
interface interface
...@@ -15,7 +12,6 @@ type ...@@ -15,7 +12,6 @@ type
ucEnvoy: TUniConnection; ucEnvoy: TUniConnection;
PostgreSQLUniProvider1: TPostgreSQLUniProvider; PostgreSQLUniProvider1: TPostgreSQLUniProvider;
UniQuery1: TUniQuery; UniQuery1: TUniQuery;
ucBooking: TUniConnection;
OracleUniProvider1: TOracleUniProvider; OracleUniProvider1: TOracleUniProvider;
uqBooking: TUniQuery; uqBooking: TUniQuery;
uqUnitsCurrent: TUniQuery; uqUnitsCurrent: TUniQuery;
...@@ -24,6 +20,104 @@ type ...@@ -24,6 +20,104 @@ type
uqCFSMemos: TUniQuery; uqCFSMemos: TUniQuery;
uqComplaintList: TUniQuery; uqComplaintList: TUniQuery;
uqComplaintDetails: TUniQuery; uqComplaintDetails: TUniQuery;
ucENTCAD: TUniConnection;
uqComplaintListCOMPLAINTID: TFloatField;
uqComplaintListCFSID: TFloatField;
uqComplaintListCOMPLAINT: TStringField;
uqComplaintListAGENCY: TStringField;
uqComplaintListDISPATCH_CODE_DESC: TStringField;
uqComplaintListSOURCE: TStringField;
uqComplaintListSOURCE_DESC: TStringField;
uqComplaintListPRIORITY: TStringField;
uqComplaintListADDRESSID: TFloatField;
uqComplaintListADDRESS: TStringField;
uqComplaintListAPARTMENT: TStringField;
uqComplaintListCITY: TStringField;
uqComplaintListBUSINESS: TStringField;
uqComplaintListDISPATCHDISTRICT: TStringField;
uqComplaintListDISPATCHSECTOR: TStringField;
uqComplaintListADDRESSDISTRICT: TStringField;
uqComplaintListADDRESSSECTOR: TStringField;
uqComplaintListXCOORD: TFloatField;
uqComplaintListYCOORD: TFloatField;
uqComplaintListWARNINGS: TFloatField;
uqComplaintListCONTACTS: TFloatField;
uqComplaintListHISTORY: TFloatField;
uqComplaintListDATEREPORTED: TDateTimeField;
uqComplaintListDATERECEIVED: TDateTimeField;
uqComplaintListDATEDISPATCHED: TDateTimeField;
uqComplaintListDATERESPONDED: TDateTimeField;
uqComplaintListDATEARRIVED: TDateTimeField;
uqComplaintListDATECLEARED: TDateTimeField;
uqComplaintDetailsCOMPLAINTID: TFloatField;
uqComplaintDetailsCFSID: TFloatField;
uqComplaintDetailsCOMPLAINT: TStringField;
uqComplaintDetailsAGENCY: TStringField;
uqComplaintDetailsDISPATCHCODE: TStringField;
uqComplaintDetailsDISPATCH_CODE_DESC: TStringField;
uqComplaintDetailsSOURCE: TStringField;
uqComplaintDetailsSOURCE_DESC: TStringField;
uqComplaintDetailsPRIORITY: TStringField;
uqComplaintDetailsADDRESSID: TFloatField;
uqComplaintDetailsADDRESS: TStringField;
uqComplaintDetailsAPARTMENT: TStringField;
uqComplaintDetailsCITY: TStringField;
uqComplaintDetailsBUSINESS: TStringField;
uqComplaintDetailsDISPATCHDISTRICT: TStringField;
uqComplaintDetailsDISPATCHSECTOR: TStringField;
uqComplaintDetailsADDRESSDISTRICT: TStringField;
uqComplaintDetailsADDRESSSECTOR: TStringField;
uqComplaintDetailsXCOORD: TFloatField;
uqComplaintDetailsYCOORD: TFloatField;
uqComplaintDetailsWARNINGS: TFloatField;
uqComplaintDetailsCONTACTS: TFloatField;
uqComplaintDetailsHISTORY: TFloatField;
uqComplaintDetailsDATEREPORTED: TDateTimeField;
uqComplaintDetailsDATERECEIVED: TDateTimeField;
uqComplaintDetailsDATEDISPATCHED: TDateTimeField;
uqComplaintDetailsDATERESPONDED: TDateTimeField;
uqComplaintDetailsDATEARRIVED: TDateTimeField;
uqComplaintDetailsDATECLEARED: TDateTimeField;
uqCFSActiveCOMPLAINTID: TFloatField;
uqCFSActiveUNITID: TFloatField;
uqCFSActiveUNITNAME: TStringField;
uqCFSActiveDATEDISPATCHED: TDateTimeField;
uqCFSActiveDATERESPONDED: TDateTimeField;
uqCFSActiveDATEARRIVED: TDateTimeField;
uqCFSActiveDATECLEARED: TDateTimeField;
uqCFSActiveLOCATION: TStringField;
uqCFSMemosMEMO_ID: TFloatField;
uqCFSMemosCFSID: TFloatField;
uqCFSMemosMEMO_TYPE: TFloatField;
uqCFSMemosTIMESTAMP: TDateTimeField;
uqCFSMemosBADGE_NUMBER: TStringField;
uqCFSMemosREMARKS: TStringField;
uqUnitsCurrentENTRYID: TFloatField;
uqUnitsCurrentUNITID: TFloatField;
uqUnitsCurrentUNITNAME: TStringField;
uqUnitsCurrentUNIT_DISTRICT: TStringField;
uqUnitsCurrentGPS_LATITUDE: TFloatField;
uqUnitsCurrentGPS_LONGITUDE: TFloatField;
uqDISUnitsActiveUNITID: TFloatField;
uqDISUnitsActiveUNITNAME: TStringField;
uqDISUnitsActiveCARNUMBER_DESC: TStringField;
uqDISUnitsActiveDISTRICT_DESC: TStringField;
uqDISUnitsActiveSECTOR_DESC: TStringField;
uqDISUnitsActiveOFFICER1_EMPNUM: TStringField;
uqDISUnitsActiveOFFICER1_LAST_NAME: TStringField;
uqDISUnitsActiveOFFICER1_FIRST_NAME: TStringField;
uqDISUnitsActiveOFFICER1_MI: TStringField;
uqDISUnitsActiveOFFICER2_EMPNUM: TStringField;
uqDISUnitsActiveOFFICER2_LAST_NAME: TStringField;
uqDISUnitsActiveOFFICER2_FIRST_NAME: TStringField;
uqDISUnitsActiveOFFICER2_MI: TStringField;
uqDISUnitsActiveLOCATION: TStringField;
uqDISUnitsActiveCOMPLAINT: TStringField;
uqDISUnitsActiveUNITSTATUS: TFloatField;
uqDISUnitsActiveUNIT_STATUS_DESC: TStringField;
uqDISUnitsActiveENTRYID: TFloatField;
uqDISUnitsActiveGPS_LATITUDE: TFloatField;
uqDISUnitsActiveGPS_LONGITUDE: TFloatField;
procedure DataModuleCreate(Sender: TObject); procedure DataModuleCreate(Sender: TObject);
private private
{ Private declarations } { Private declarations }
......
unit Api.Service;
interface
uses
XData.Service.Common,
Aurelius.Mapping.Attributes,
System.JSON,
System.Generics.Collections,
System.Classes;
const
API_MODEL = 'Api';
type
[ServiceContract, Model(API_MODEL)]
IApiService = interface(IInvokable)
['{4FCB7FAF-44E5-49D6-9C0F-EE44BFB33313}']
[HttpGet] function GetComplaintList: TJSONObject;
end;
implementation
end.
unit Api.ServiceImpl;
interface
uses
XData.Server.Module, XData.Service.Common, Api.Database, Data.DB,
System.SysUtils, System.Generics.Collections, XData.Sys.Exceptions,
System.Hash, System.Classes, Common.Logging, System.JSON, Api.Service;
type
[ServiceImplementation]
TApiService = class(TInterfacedObject, IApiService)
strict private
ApiDB: TApiDatabaseModule;
private
procedure AfterConstruction; override;
procedure BeforeDestruction; override;
public
function GetComplaintList: TJSONObject;
end;
implementation
uses
uLibrary;
procedure TApiService.AfterConstruction;
begin
inherited;
ApiDB := TApiDatabaseModule.Create(nil);
Logger.Log(3, 'ApiDatabaseModule created');
end;
procedure TApiService.BeforeDestruction;
begin
ApiDB.Free;
inherited;
Logger.Log(3, 'ApiDatabaseModule destroyed');
end;
function TApiService.GetComplaintList: TJSONObject;
var
data: TJSONArray;
begin
Logger.Log(3, '---TApiService.GetComplaintList initiated');
Result := TJSONObject.Create;
TXDataOperationContext.Current.Handler.ManagedObjects.Add(Result);
data := TJSONArray.Create;
try
with ApiDB.uqComplaintList do
begin
Open;
First;
while not Eof do
begin
var status: string;
if not FieldByName('DATECLEARED').IsNull then
status := 'Cleared'
else if not FieldByName('DATEARRIVED').IsNull then
status := 'AtScene'
else if not FieldByName('DATEDISPATCHED').IsNull then
status := 'Dispatched'
else
status := 'Pending';
var item := TJSONObject.Create;
item.AddPair('ComplaintId', ApiDB.uqComplaintListCOMPLAINTID.AsString);
item.AddPair('Agency', ApiDB.uqComplaintListAGENCY.AsString);
item.AddPair('Priority', TJSONNumber.Create(ApiDB.uqComplaintListPRIORITY.AsString));
item.AddPair('DispatchCodeDesc', ApiDB.uqComplaintListDISPATCH_CODE_DESC.AsString);
item.AddPair('Address', ApiDB.uqComplaintListADDRESS.AsString);
item.AddPair('CFSId', ApiDB.uqComplaintListCFSID.AsString);
item.AddPair('Status', status);
item.AddPair('DispatchDistrict', ApiDB.uqComplaintListDISPATCHDISTRICT.AsString);
item.AddPair('DateReported', ApiDB.uqComplaintListDATEREPORTED.AsString);
data.AddElement(item);
Next;
end;
end;
Result.AddPair('count', TJSONNumber.Create(data.Count));
Result.AddPair('returned', TJSONNumber.Create(data.Count));
Result.AddPair('data', data);
except
data.Free;
Logger.Log(3, '---TApiService.GetComplaintList End (error)');
raise EXDataHttpException.Create(500, 'Failed to load complaints list');
end;
Logger.Log(3, '---TApiService.GetComplaintList End');
end;
initialization
RegisterServiceType(TApiService);
end.
// Lookup Service interface which retrieves information from the database
// which is then sent to the client.
// Authors:
// Cameron Hayes
// Mac ...
// Elias Sarraf
unit Lookup.Service;
interface
uses
XData.Service.Common,
Aurelius.Mapping.Attributes,
System.JSON,
System.Generics.Collections,
System.Classes;
const
API_MODEL = 'Api';
type
TCallItem = class
// Class of the info we want from the database from a specific call.
// callSid: SID of the call, 34 digit string.
// fromNumber: Who the phone call was from. (xxx) xxx-xxxx
// toNumber: Who the phone call was to. (xxx) xxx-xxxx
// dateCreated: Date the phone call was created. mm/dd/yyyy hh:nn:ss am/pm
// mediaURL: Link to the recording audio
// duration: Length of the entire call and recording.
// transcription: Transcription of the recording. Not always present due to
// the call being answerered or caller did not leave a message.
public
callSid: string;
fromNumber: string;
toNumber: string;
dateCreated: string;
mediaUrl: string;
duration: string;
transcription: string;
end;
// List of call items
// count: Total amount of records that fit the SQL query
// data: List of retrieved calls
TCallList = class
public
count: integer;
data: TList<TCallItem>;
end;
TUserItem = class
public
userID: string;
username: string;
full_name: string;
phone_number: string;
email_address: string;
admin: boolean;
active: boolean;
password: string;
end;
TUserList = class
public
count: integer;
data: TList<TUserItem>;
end;
type
[ServiceContract, Model(API_MODEL)]
ILookupService = interface(IInvokable)
['{F24E1468-5279-401F-A877-CD48B44F4416}']
[HttpGet] function GetCalls(searchOptions: string): TCallList;
[HttpGet] function Search(phoneNum: string): TCallList;
[HttpGet] function GetUsers(searchOptions: string): TUserList;
function AddUser(userInfo: string): string;
function DelUser(username: string): string;
function EditUser(const editOptions: string): string;
end;
implementation
initialization
RegisterServiceType(TypeInfo(ILookupService));
end.
// Implementation of the Lookup Service interface used to send call information
// to the client.
// Authors:
// Cameron Hayes
// Mac ...
// Elias Sarraf
unit Lookup.ServiceImpl;
interface
uses
XData.Server.Module, XData.Service.Common, Api.Database, Data.DB,
Lookup.Service, System.Hash, System.Classes, Common.Logging;
type
[ServiceImplementation]
TLookupService = class(TInterfacedObject, ILookupService)
strict private
callsDB: TApiDatabaseModule;
private
function GetUsers(searchOptions: string): TUserList;
function GetCalls(searchOptions: string): TCallList;
function EditUser(const editOptions: string): string;
function Search(phoneNum: string): TCallList;
function AddUser(userInfo: string): string;
function DelUser(username: string): string;
procedure AfterConstruction; override;
procedure BeforeDestruction; override;
end;
implementation
uses
System.SysUtils,
System.Generics.Collections,
XData.Sys.Exceptions, uLibrary;
procedure TLookupService.AfterConstruction;
begin
inherited;
callsDB := TApiDatabaseModule.Create(nil);
Logger.Log(3, 'callsDB created');
end;
procedure TLookupService.BeforeDestruction;
begin
callsDB.Free;
inherited;
Logger.Log(3, 'callsDB destroyed');
end;
function TLookupService.Search(phoneNum: string): TCallList;
var
SQL: string;
call: TCallItem;
begin
Logger.Log(3, 'Search called for phone number: ' + phoneNum);
SQL := 'select * ' +
'from calls inner join recordings on calls.sid = recordings.call_sid ' +
'where from_formatted = ' + QuotedStr(phoneNum) +
' order by calls.date_created desc';
Logger.Log(3, 'Search main query: ' + SQL);
doQuery(callsDB.UniQuery1, SQL);
Result := TCallList.Create;
Result.data := TList<TCallItem>.Create;
TXDataOperationContext.Current.Handler.ManagedObjects.Add(Result.data);
while not callsDB.UniQuery1.Eof do
begin
call := TCallItem.Create;
TXDataOperationContext.Current.Handler.ManagedObjects.Add(call);
Result.data.Add(call);
call.callSid := callsDB.UniQuery1.FieldByName('sid').AsString;
call.fromNumber := callsDB.UniQuery1.FieldByName('from_formatted').AsString;
call.ToNumber := callsDB.UniQuery1.FieldByName('to_formatted').AsString;
call.dateCreated := callsDB.UniQuery1.FieldByName('date_created').AsString;
call.mediaUrl := callsDB.UniQuery1.FieldByName('media_url').AsString;
call.duration := callsDB.UniQuery1.FieldByName('duration').AsString;
call.transcription := callsDB.UniQuery1.FieldByName('transcription').AsString;
callsDB.UniQuery1.Next;
end;
callsDB.UniQuery1.Close;
SQL := 'select count(*) as total_count from calls inner join ' +
'recordings on calls.sid = recordings.call_sid where ' +
'from_formatted = ' + QuotedStr(phoneNum);
Logger.Log(3, 'Search count query: ' + SQL);
doQuery(callsDB.UniQuery1, SQL);
Result.count := callsDB.UniQuery1.FieldByName('total_count').AsInteger;
callsDB.UniQuery1.Close;
Logger.Log(3, 'Search completed. Total results: ' + IntToStr(Result.count));
end;
function TLookupService.GetCalls(searchOptions: string): TCallList;
var
params: TStringList;
SQL: string;
DBString: string;
call: TCallItem;
offset: string;
limit: string;
PhoneNum: string;
PageNum: integer;
PageSize: integer;
StartDate: string;
EndDate: string;
OrderBy: string;
whereSQL: string;
orderBySQL: string;
Caller: string;
begin
Logger.Log(3, 'GetCalls called with searchOptions: ' + searchOptions);
params := TStringList.Create;
params.StrictDelimiter := true;
params.Delimiter := '&';
params.DelimitedText := searchOptions;
PhoneNum := params.Values['phonenumber'];
PageNum := StrToInt(params.Values['pagenumber']);
PageSize := StrToInt(params.Values['pagesize']);
StartDate := params.Values['startdate'];
EndDate := params.Values['enddate'];
OrderBy := params.Values['orderby'];
Caller := params.Values['caller'];
offset := IntToStr((PageNum - 1) * PageSize);
limit := IntToStr(PageSize);
whereSQL := 'where ';
if PhoneNum <> '' then
whereSQL := whereSQL + 'to_formatted = ' + QuotedStr(PhoneNum);
if StartDate <> '' then
if whereSQL = 'where ' then
whereSQL := whereSQL + 'calls.date_created > ' + QuotedStr(StartDate)
else
whereSQL := whereSQL + ' AND calls.date_created > ' + QuotedStr(StartDate);
if EndDate <> '' then
if whereSQL = 'where ' then
whereSQL := whereSQL + 'calls.date_created < ' + QuotedStr(EndDate)
else
whereSQL := whereSQL + ' AND calls.date_created < ' + QuotedStr(EndDate);
if Caller <> '' then
if whereSQL = 'where ' then
whereSQL := whereSQL + 'from_formatted = ' + QuotedStr(Caller)
else
whereSQL := whereSQL + ' AND from_formatted = ' + QuotedStr(Caller);
if whereSQL = 'where ' then
whereSQL := '';
if (OrderBy = '') or (OrderBy = 'Date') then
orderBySQL := 'order by calls.date_created desc'
else
orderBySQL := 'order by calls.from_formatted desc';
SQL := 'select * ' +
'from calls inner join recordings on calls.sid = recordings.call_sid ' +
whereSQL + ' ' + orderBySQL + ' limit ' + limit + ' offset ' + offset;
Logger.Log(3, 'GetCalls query: ' + SQL);
doQuery(callsDB.UniQuery1, SQL);
Result := TCallList.Create;
Result.data := TList<TCallItem>.Create;
TXDataOperationContext.Current.Handler.ManagedObjects.Add(Result.data);
while not callsDB.UniQuery1.Eof do
begin
call := TCallItem.Create;
TXDataOperationContext.Current.Handler.ManagedObjects.Add(call);
Result.data.Add(call);
call.callSid := callsDB.UniQuery1.FieldByName('sid').AsString;
call.fromNumber := callsDB.UniQuery1.FieldByName('from_formatted').AsString;
call.ToNumber := callsDB.UniQuery1.FieldByName('to_formatted').AsString;
call.dateCreated := callsDB.UniQuery1.FieldByName('date_created').AsString;
call.mediaUrl := callsDB.UniQuery1.FieldByName('media_url').AsString;
call.duration := callsDB.UniQuery1.FieldByName('duration').AsString;
call.transcription := callsDB.UniQuery1.FieldByName('transcription').AsString;
callsDB.UniQuery1.Next;
end;
callsDB.UniQuery1.Close;
SQL := 'select count(*) as total_count from calls inner join recordings on calls.sid = recordings.call_sid ' + whereSQL;
Logger.Log(3, 'GetCalls count query: ' + SQL);
doQuery(callsDB.UniQuery1, SQL);
Result.count := callsDB.UniQuery1.FieldByName('total_count').AsInteger;
callsDB.UniQuery1.Close;
Logger.Log(3, 'GetCalls completed successfully. Returned count: ' + IntToStr(Result.count));
end;
function TLookupService.GetUsers(searchOptions: string): TUserList;
var
SQL: string;
user: TUserItem;
begin
if searchOptions = '' then
SQL := 'select * from users order by full_name ASC'
else
SQL := 'select * from users where username=' + QuotedStr(searchOptions);
Logger.Log(3, 'GetUsers query: ' + SQL);
doQuery(callsDB.UniQuery1, SQL);
Result := TUserList.Create;
Result.data := TList<TUserItem>.Create;
TXDataOperationContext.Current.Handler.ManagedObjects.Add(Result.data);
while not callsDB.UniQuery1.Eof do
begin
user := TUserItem.Create;
TXDataOperationContext.Current.Handler.ManagedObjects.Add(user);
Result.data.Add(user);
user.userID := callsDB.UniQuery1.FieldByName('user_id').AsString;
user.username := callsDB.UniQuery1.FieldByName('username').AsString;
user.full_name := callsDB.UniQuery1.FieldByName('full_name').AsString;
user.phone_number := callsDB.UniQuery1.FieldByName('phone_number').AsString;
user.email_address := callsDB.UniQuery1.FieldByName('email').AsString;
user.admin := callsDB.UniQuery1.FieldByName('admin').AsBoolean;
user.password := callsDB.UniQuery1.FieldByName('password').AsString;
user.active := callsDB.UniQuery1.FieldByName('active').AsBoolean;
callsDB.UniQuery1.Next;
end;
callsDB.UniQuery1.Close;
SQL := 'select count(*) as total_count from users';
Logger.Log(3, 'GetUsers count query: ' + SQL);
doQuery(callsDB.UniQuery1, SQL);
Result.count := callsDB.UniQuery1.FieldByName('total_count').AsInteger;
callsDB.UniQuery1.Close;
Logger.Log(3, 'GetUsers returned user list, count = ' + IntToStr(Result.count));
end;
function TLookupService.EditUser(const editOptions: string): string;
var
params: TStringList;
user, full_name, email, phone, Admin, newUser, hashString, hashPW, password, active: string;
SQL: string;
begin
Logger.Log(3, 'EditUser called with options: ' + editOptions);
params := TStringList.Create;
params.Delimiter := '&';
params.StrictDelimiter := true;
params.DelimitedText := editOptions;
user := params.Values['username'];
full_name := params.Values['fullname'];
phone := params.Values['phonenumber'];
email := params.Values['email'];
Admin := params.Values['admin'];
newUser := params.Values['newuser'];
password := params.Values['password'];
active := params.Values['active'];
SQL := 'select * from users where username = ' + QuotedStr(user);
Logger.Log(3, 'EditUser query: ' + SQL);
doQuery(callsDB.UniQuery1, SQL);
if callsDB.UniQuery1.IsEmpty then
begin
Result := 'No such user found';
Logger.Log(2, 'EditUser failed: user not found (' + user + ')');
end
else
begin
callsDB.UniQuery1.Edit;
if not newUser.IsEmpty then
callsDB.UniQuery1.FieldByName('username').AsString := newUser;
if not full_name.IsEmpty then
callsDB.UniQuery1.FieldByName('full_name').AsString := full_name;
if not phone.IsEmpty then
callsDB.UniQuery1.FieldByName('phone_number').AsString := phone;
if not email.IsEmpty then
callsDB.UniQuery1.FieldByName('email').AsString := email;
if not Admin.IsEmpty then
callsDB.UniQuery1.FieldByName('admin').AsBoolean := StrToBool(Admin);
if not Active.IsEmpty then
callsDB.UniQuery1.FieldByName('active').AsBoolean := StrToBool(Active);
if (password <> 'hidden') and (not password.IsEmpty) then
begin
hashString := callsDB.UniQuery1.FieldByName('date_created').AsString + password;
hashPW := THashSHA2.GetHashString(hashString, THashSHA2.TSHA2Version.SHA512).ToUpper;
callsDB.UniQuery1.FieldByName('password').AsString := hashPW;
end;
callsDB.UniQuery1.Post;
Result := 'Success:Edit Successful';
Logger.Log(3, 'EditUser success for: ' + user);
end;
callsDB.UniQuery1.Close;
end;
function TLookupService.AddUser(userInfo: string): string;
var
dateCreated: TDateTime;
hashString, hashPW, SQL: string;
params: TStringList;
begin
Logger.Log(3, 'AddUser called with info: ' + userInfo);
params := TStringList.Create;
try
params.StrictDelimiter := true;
params.Delimiter := '&';
params.DelimitedText := userInfo;
dateCreated := Now;
hashString := DateTimeToStr(dateCreated) + params.Values['password'];
hashPW := THashSHA2.GetHashString(hashString, THashSHA2.TSHA2Version.SHA512).ToUpper;
SQL := 'select * from users where username = ' + QuotedStr(params.Values['username'].ToLower);
Logger.Log(3, 'AddUser query: ' + SQL);
callsDB.UniQuery1.Close;
callsDB.UniQuery1.SQL.Text := SQL;
callsDB.UniQuery1.Open;
if callsDB.UniQuery1.IsEmpty then
begin
callsDB.UniQuery1.Insert;
callsDB.UniQuery1.FieldByName('username').AsString := params.Values['username'].ToLower;
callsDB.UniQuery1.FieldByName('password').AsString := hashPW;
callsDB.UniQuery1.FieldByName('date_created').AsString := DateTimeToStr(dateCreated);
callsDB.UniQuery1.FieldByName('full_name').AsString := params.Values['fullname'];
callsDB.UniQuery1.FieldByName('phone_number').AsString := params.Values['phonenumber'];
callsDB.UniQuery1.FieldByName('email').AsString := params.Values['email'];
callsDB.UniQuery1.FieldByName('admin').AsBoolean := StrToBool(params.Values['admin']);
callsDB.UniQuery1.FieldByName('active').AsBoolean := True;
callsDB.UniQuery1.Post;
Result := 'Success:User successfully added';
Logger.Log(3, 'AddUser success: ' + params.Values['username']);
end
else
begin
Result := 'Failure:Username already taken';
Logger.Log(2, 'AddUser failed: Username already taken (' + params.Values['username'] + ')');
end;
finally
params.Free;
end;
end;
function TLookupService.DelUser(username: string): string;
var
SQL: string;
begin
Logger.Log(3, 'DelUser called for: ' + username);
SQL := 'select * from users where username = ' + QuotedStr(username.ToLower);
callsDB.UniQuery1.Close;
callsDB.UniQuery1.SQL.Text := SQL;
callsDB.UniQuery1.Open;
if callsDB.UniQuery1.IsEmpty then
begin
Result := 'Failure:User does not exist';
Logger.Log(2, 'DelUser failed: user not found (' + username + ')');
end
else
begin
SQL := 'DELETE FROM users where username = ' + QuotedStr(username.ToLower);
callsDB.UniQuery1.SQL.Text := SQL;
callsDB.UniQuery1.ExecSQL;
Result := 'Success:User deleted';
Logger.Log(3, 'DelUser success: ' + username);
end;
end;
initialization
RegisterServiceType(TLookupService);
end.
...@@ -7,7 +7,7 @@ uses ...@@ -7,7 +7,7 @@ uses
System.Classes, Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs, System.Classes, Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs,
Vcl.StdCtrls, Vcl.ExtCtrls, System.Generics.Collections, System.IniFiles, Vcl.StdCtrls, Vcl.ExtCtrls, System.Generics.Collections, System.IniFiles,
Auth.Service, Auth.Server.Module, Api.Server.Module, App.Server.Module, Auth.Service, Auth.Server.Module, Api.Server.Module, App.Server.Module,
ExeInfo, Lookup.Service; ExeInfo, Api.Service;
type type
TFMain = class(TForm) TFMain = class(TForm)
......
...@@ -18,9 +18,9 @@ uses ...@@ -18,9 +18,9 @@ uses
Auth.Database in 'Source\Auth.Database.pas' {AuthDatabase: TDataModule}, Auth.Database in 'Source\Auth.Database.pas' {AuthDatabase: TDataModule},
uLibrary in 'Source\uLibrary.pas', uLibrary in 'Source\uLibrary.pas',
Auth.Service in 'Source\Auth.Service.pas', Auth.Service in 'Source\Auth.Service.pas',
Lookup.Service in 'Source\Lookup.Service.pas', Api.Service in 'Source\Api.Service.pas',
Auth.ServiceImpl in 'Source\Auth.ServiceImpl.pas', Auth.ServiceImpl in 'Source\Auth.ServiceImpl.pas',
Lookup.ServiceImpl in 'Source\Lookup.ServiceImpl.pas', Api.ServiceImpl in 'Source\Api.ServiceImpl.pas',
Twilio.Data.Module in 'Source\Twilio.Data.Module.pas' {TwilioDataModule: TDataModule}, Twilio.Data.Module in 'Source\Twilio.Data.Module.pas' {TwilioDataModule: TDataModule},
App.Server.Module in 'Source\App.Server.Module.pas' {AppServerModule: TDataModule}, App.Server.Module in 'Source\App.Server.Module.pas' {AppServerModule: TDataModule},
Common.Ini in 'Source\Common.Ini.pas'; Common.Ini in 'Source\Common.Ini.pas';
......
...@@ -160,9 +160,9 @@ ...@@ -160,9 +160,9 @@
</DCCReference> </DCCReference>
<DCCReference Include="Source\uLibrary.pas"/> <DCCReference Include="Source\uLibrary.pas"/>
<DCCReference Include="Source\Auth.Service.pas"/> <DCCReference Include="Source\Auth.Service.pas"/>
<DCCReference Include="Source\Lookup.Service.pas"/> <DCCReference Include="Source\Api.Service.pas"/>
<DCCReference Include="Source\Auth.ServiceImpl.pas"/> <DCCReference Include="Source\Auth.ServiceImpl.pas"/>
<DCCReference Include="Source\Lookup.ServiceImpl.pas"/> <DCCReference Include="Source\Api.ServiceImpl.pas"/>
<DCCReference Include="Source\Twilio.Data.Module.pas"> <DCCReference Include="Source\Twilio.Data.Module.pas">
<Form>TwilioDataModule</Form> <Form>TwilioDataModule</Form>
<DesignClass>TDataModule</DesignClass> <DesignClass>TDataModule</DesignClass>
......
[Settings] [Settings]
LogFileNum=409 LogFileNum=414
webClientVersion=0.1.0 webClientVersion=0.1.0
TwilioUpdateTime=1 TwilioUpdateTime=1
......
object FViewComplaints: TFViewComplaints object FViewComplaints: TFViewComplaints
Width = 676 Width = 359
Height = 480 Height = 480
CSSLibrary = cssBootstrap CSSLibrary = cssBootstrap
ElementFont = efCSS ElementFont = efCSS
...@@ -11,157 +11,91 @@ object FViewComplaints: TFViewComplaints ...@@ -11,157 +11,91 @@ object FViewComplaints: TFViewComplaints
ParentFont = False ParentFont = False
Visible = True Visible = True
OnCreate = WebFormCreate OnCreate = WebFormCreate
object lblEntries: TWebLabel object WebButton1: TWebButton
Left = 0 Left = 180
Top = 336 Top = 110
Width = 77 Width = 43
Height = 13 Height = 25
Caption = 'Showing 0 of ...' Caption = 'Group'
ElementID = 'lblentries' ChildOrder = 1
ElementClassName = 'btn btn-light'
ElementID = 'complaints_btngroup'
ElementFont = efCSS ElementFont = efCSS
HeightStyle = ssAuto HeightStyle = ssAuto
HeightPercent = 100.000000000000000000 HeightPercent = 100.000000000000000000
Visible = False
WidthPercent = 100.000000000000000000 WidthPercent = 100.000000000000000000
end end
object wcbPageSize: TWebComboBox object WebButton2: TWebButton
Left = 0 Left = 242
Top = 0 Top = 110
Width = 145 Width = 37
Height = 21 Height = 25
ElementClassName = 'custom-select' Caption = 'Filter'
ElementID = 'wcbpagesize' ChildOrder = 1
ElementClassName = 'btn btn-light'
ElementID = 'complaints_btnfilter'
ElementFont = efCSS ElementFont = efCSS
HeightStyle = ssAuto HeightStyle = ssAuto
HeightPercent = 100.000000000000000000 HeightPercent = 100.000000000000000000
Text = '10'
Visible = False
WidthPercent = 100.000000000000000000
ItemIndex = -1
Items.Strings = (
'10'
'25'
'50')
end
object wcbLocation: TWebLookupComboBox
Left = 154
Top = 0
Width = 145
Height = 22
ElementClassName = 'custom-select'
ElementID = 'wcblocation'
ElementFont = efCSS
HeightPercent = 100.000000000000000000
Visible = False
WidthPercent = 100.000000000000000000 WidthPercent = 100.000000000000000000
ItemIndex = -1
LookupValues = <
item
DisplayText = 'All'
end
item
Value = '(716) 681-8820'
DisplayText = 'Galleria'
end
item
Value = '(716) 297-4654'
DisplayText = 'NF Outlet'
end
item
Value = '(585) 445-8911'
DisplayText = 'Rochester'
end end
item object Complaints: TWebButton
Value = '(315) 565-4138' Left = 114
DisplayText = 'Syracuse' Top = 110
end> Width = 53
end Height = 25
object dtpStartDate: TWebEdit Caption = 'Refresh'
Left = 342 ChildOrder = 1
Top = 0 ElementClassName = 'btn btn-light'
Width = 121 ElementID = 'complaints_btnrefresh'
Height = 22
ChildOrder = 10
ElementClassName = 'form-control'
ElementID = 'dtpstartdate'
ElementFont = efCSS ElementFont = efCSS
HeightStyle = ssAuto HeightStyle = ssAuto
HeightPercent = 100.000000000000000000 HeightPercent = 100.000000000000000000
Visible = False
WidthPercent = 100.000000000000000000 WidthPercent = 100.000000000000000000
end end
object dtpEndDate: TWebEdit object dblComplaintsList: TWebDBListControl
Left = 478 Left = 36
Top = 0 Top = 148
Width = 121 Width = 263
Height = 22 Height = 237
ChildOrder = 10 ElementID = 'complaints_dbl_complaint_list'
ElementClassName = 'form-control'
ElementID = 'dtpenddate'
ElementFont = efCSS
HeightStyle = ssAuto HeightStyle = ssAuto
HeightPercent = 100.000000000000000000 HeightPercent = 100.000000000000000000
Visible = False
WidthPercent = 100.000000000000000000 WidthPercent = 100.000000000000000000
end ChildOrder = 3
object wcbSortBy: TWebComboBox DefaultItemClassName = 'list-group-item'
Left = 442 DefaultItemLinkClassName = 'list-group-link'
Top = 52
Width = 145
Height = 21
ElementClassName = 'custom-select'
ElementID = 'wcbsortby'
ElementFont = efCSS ElementFont = efCSS
HeightStyle = ssAuto ElementListClassName = 'list-group'
HeightPercent = 100.000000000000000000 Items = <
Text = 'Date' item
Visible = False ItemClassName = 'list-group-item'
WidthPercent = 100.000000000000000000 Items = <>
ItemIndex = -1 LinkClassName = 'list-group-link'
Items.Strings = ( Text = 'Item 0'
'Date'
'Phone Number')
end end
object btnApply: TWebButton item
Left = 478 ItemClassName = 'list-group-item'
Top = 128 Items = <>
Width = 96 LinkClassName = 'list-group-link'
Height = 25 Text = 'Item 1'
Caption = 'Apply'
ChildOrder = 7
ElementClassName = 'btn btn-light'
ElementID = 'btnapply'
ElementFont = efCSS
HeightStyle = ssAuto
HeightPercent = 100.000000000000000000
Visible = False
WidthPercent = 100.000000000000000000
end end
object edtSearch: TWebEdit item
Left = 50 ItemClassName = 'list-group-item'
Top = 382 Items = <>
Width = 121 LinkClassName = 'list-group-link'
Height = 22 Text = 'Item 2'
HelpType = htKeyword end>
ChildOrder = 8 Style = lsListGroup
ElementClassName = 'form-control'
ElementID = 'edtsearch'
ElementFont = efCSS
HeightStyle = ssAuto
HeightPercent = 100.000000000000000000
HideSelection = False
TextHint = 'Format: (XXX) XXX-XXXX'
Visible = False
WidthPercent = 100.000000000000000000
end end
object XDataWebClient1: TXDataWebClient object xdwcComplaints: TXDataWebClient
Connection = DMConnection.ApiConnection Connection = DMConnection.ApiConnection
Left = 426 Left = 92
Top = 240 Top = 416
end end
object XDataWebDataSet1: TXDataWebDataSet object xdwdsComplaints: TXDataWebDataSet
Connection = DMConnection.ApiConnection Connection = DMConnection.ApiConnection
Left = 440 Left = 214
Top = 300 Top = 414
end end
end end
...@@ -5,20 +5,20 @@ ...@@ -5,20 +5,20 @@
<div class="container-fluid"> <div class="container-fluid">
<div class="row w-100 g-2 align-items-stretch"> <div class="row w-100 g-2 align-items-stretch">
<div class="col"> <div class="col">
<span id="complaints.title" class="navbar-brand mb-0 h5 text-white">Complaints</span> <span id="complaints_title" class="navbar-brand mb-0 h5 text-white">Complaints</span>
</div> </div>
<div class="col"> <div class="col">
<button id="complaints.btnrefresh" type="button" class="btn btn-primary w-100 h-100"> <button id="complaints_btnrefresh" type="button" class="btn btn-primary w-100 h-100">
<i class="fa fa-sync-alt me-1"></i><span class="d-none d-sm-inline">Refresh</span> <i class="fa fa-sync-alt me-1"></i><span class="d-none d-sm-inline">Refresh</span>
</button> </button>
</div> </div>
<div class="col"> <div class="col">
<button id="complaints.btngroup" type="button" class="btn btn-primary w-100 h-100"> <button id="complaints_btngroup" type="button" class="btn btn-primary w-100 h-100">
<i class="fa fa-layer-group me-1"></i><span class="d-none d-sm-inline">Group</span> <i class="fa fa-layer-group me-1"></i><span class="d-none d-sm-inline">Group</span>
</button> </button>
</div> </div>
<div class="col"> <div class="col">
<button id="complaints.btnfilter" type="button" class="btn btn-primary w-100 h-100"> <button id="complaints_btnfilter" type="button" class="btn btn-primary w-100 h-100">
<i class="fa fa-sliders-h me-1"></i><span class="d-none d-sm-inline">Filter</span> <i class="fa fa-sliders-h me-1"></i><span class="d-none d-sm-inline">Filter</span>
</button> </button>
</div> </div>
...@@ -31,38 +31,20 @@ ...@@ -31,38 +31,20 @@
<div class="container-fluid"> <div class="container-fluid">
<div class="input-group"> <div class="input-group">
<span class="input-group-text bg-white"><i class="fa fa-search"></i></span> <span class="input-group-text bg-white"><i class="fa fa-search"></i></span>
<input id="complaints.search" class="form-control" placeholder="Search..."> <input id="complaints_search" class="form-control" placeholder="Search...">
</div> </div>
</div> </div>
</div> </div>
</div> <!-- /sticky-top wrapper --> </div> <!-- /sticky-top wrapper -->
<!-- Existing content (unchanged) --> <!-- Complaints list container -->
<div class="row"> <div class="container-fluid mt-2">
<div class="col-12">
<div class="container mt-4">
<div class="row justify-content-center"> <div class="row justify-content-center">
<div class="col-12 col-md-10 col-lg-8"> <div class="col-12 col-md-10 col-lg-8">
<h1 class="page-header pt-3 pb-2 mb-3 border-bottom fs-4 fw-bold" id="view.calls.title">Complaints</h1> <!-- This is where the DBListControl will inject cards -->
<div id="complaints_dbl_complaint_list" class="d-flex flex-column gap-2">
<!-- Data Table --> <!-- Cards will render here -->
<div class="table-responsive mt-4">
<table class="table table-sm table-striped table-bordered align-middle" id="tblPhoneGrid">
<thead class="table-dark">
<tr>
<th scope="col">Phone Number</th>
<th scope="col">Caller</th>
<th scope="col">Time</th>
<th scope="col">Duration</th>
<th scope="col">Transcript</th>
<th scope="col">Listen</th>
</tr>
</thead>
<tbody>
<!-- Rows added dynamically in Delphi -->
</tbody>
</table>
</div> </div>
<!-- Entry Count Label --> <!-- Entry Count Label -->
...@@ -71,12 +53,11 @@ ...@@ -71,12 +53,11 @@
<!-- Pagination --> <!-- Pagination -->
<nav aria-label="Page navigation"> <nav aria-label="Page navigation">
<ul class="pagination justify-content-center" id="pagination"> <ul class="pagination justify-content-center" id="pagination">
<!-- Pagination items added in Delphi --> <!-- Pagination items rendered in Delphi -->
</ul> </ul>
</nav> </nav>
</div> </div>
</div> </div>
</div>
</div>
</div> </div>
...@@ -5,32 +5,20 @@ interface ...@@ -5,32 +5,20 @@ interface
uses uses
System.SysUtils, System.Classes, Web, WEBLib.Graphics, WEBLib.Forms, WEBLib.Dialogs, System.SysUtils, System.Classes, Web, WEBLib.Graphics, WEBLib.Forms, WEBLib.Dialogs,
Vcl.Controls, Vcl.StdCtrls, WEBLib.StdCtrls, WEBLib.Controls, WEBLib.Grids, WebLib.Lists, Vcl.Controls, Vcl.StdCtrls, WEBLib.StdCtrls, WEBLib.Controls, WEBLib.Grids, WebLib.Lists,
XData.Web.Client, WEBLib.ExtCtrls, DB, XData.Web.JsonDataset, XData.Web.Client, WEBLib.ExtCtrls, DB, XData.Web.JsonDataset, WebLib.DB,
XData.Web.Dataset, XData.Web.Connection, Vcl.Forms, DateUtils, WebAudio; XData.Web.Dataset, XData.Web.Connection, Vcl.Forms, DateUtils, WEBLib.DBCtrls;
type type
TFViewComplaints = class(TWebForm) TFViewComplaints = class(TWebForm)
XDataWebClient1: TXDataWebClient; xdwcComplaints: TXDataWebClient;
XDataWebDataSet1: TXDataWebDataSet; xdwdsComplaints: TXDataWebDataSet;
lblEntries: TWebLabel; WebButton1: TWebButton;
wcbPageSize: TWebComboBox; WebButton2: TWebButton;
wcbLocation: TWebLookupComboBox; Complaints: TWebButton;
dtpStartDate: TWebEdit; dblComplaintsList: TWebDBListControl;
dtpEndDate: TWebEdit;
wcbSortBy: TWebComboBox;
btnApply: TWebButton;
edtSearch: TWebEdit;
procedure WebFormCreate(Sender: TObject); procedure WebFormCreate(Sender: TObject);
procedure btnApplyClick(Sender: TObject);
procedure btnSearchClick(Sender: TObject);
private private
FChildForm: TWebForm; FChildForm: TWebForm;
procedure AddRowToTable(PhoneNumber, Caller, Time, Duration, Transcript, MediaUrl: string);
procedure ClearTable();
procedure GeneratePagination(TotalPages: Integer);
function GenerateSearchOptions(): string;
[async] procedure Search(searchOptions: string);
[async] procedure GetCalls(searchOptions: string);
var var
PageNumber: integer; PageNumber: integer;
PageSize: integer; PageSize: integer;
...@@ -55,422 +43,12 @@ uses ...@@ -55,422 +43,12 @@ uses
{$R *.dfm} {$R *.dfm}
procedure TFViewComplaints.WebFormCreate(Sender: TObject); procedure TFViewComplaints.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.
begin begin
DMConnection.ApiConnection.Connected := True; DMConnection.ApiConnection.Connected := True;
PageNumber := 1;
TotalPages := 1; // Initial total pages
wcbPageSize.Text := '10';
wcbLocation.DisplayText := 'All';
wcbSortBy.Text := 'Date';
// hardcoded default toNumber/location and load grid
wcbLocation.Value := 'Galleria';
PageSize := StrToInt(wcbPageSize.Text);
StartDate := '';
EndDate := '';
OrderBy := wcbSortBy.Text;
Caller := '';
GetCalls(GenerateSearchOptions);
end;
procedure TFViewComplaints.AddRowToTable(PhoneNumber, Caller, Time, Duration, Transcript, MediaUrl: string);
// Adds rows to the table
// PhoneNumber: phone number of the location
// Caller: phone number of the caller
// Duration: duration of the call
// Transcript: transcription of the recording
// MediaUrl: Link to the recording
var
NewRow, Cell, P, Button, Audio: TJSHTMLElement;
begin
NewRow := TJSHTMLElement(document.createElement('tr'));
// Phone Number Cell
Cell := TJSHTMLElement(document.createElement('td'));
Cell.setAttribute('data-label', 'Phone Number');
Cell.innerText := PhoneNumber;
NewRow.appendChild(Cell);
// Caller Cell
Cell := TJSHTMLElement(document.createElement('td'));
Cell.setAttribute('data-label', 'Caller');
Cell.innerText := Caller;
NewRow.appendChild(Cell);
// Time Cell
Cell := TJSHTMLElement(document.createElement('td'));
Cell.setAttribute('data-label', 'Time');
Cell.innerText := DateTimeToStr(IncHour(StrToDateTime(Time), -4));;
NewRow.appendChild(Cell);
// Duration Cell
Cell := TJSHTMLElement(document.createElement('td'));
Cell.setAttribute('data-label', 'Duration');
Cell.innerText := Duration;
NewRow.appendChild(Cell);
// Transcript Cell
Cell := TJSHTMLElement(document.createElement('td'));
Cell.setAttribute('data-label', 'Transcript');
P := TJSHTMLElement(document.createElement('p'));
P.className := 'transcript';
P.innerText := Transcript;
Cell.appendChild(P);
NewRow.appendChild(Cell);
// Listen Button Cell
Cell := TJSHTMLElement(document.createElement('td'));
Cell.setAttribute('data-label', 'Listen');
Button := TJSHTMLElement(document.createElement('button'));
Button.className := 'btn btn-primary';
Button.innerHTML := '<i class="fa fa-play"></i>';
// Open voicemail audio in a new tab on click
Button.addEventListener('click', procedure(Event: TJSMouseEvent)
begin
{$IFNDEF WIN32}
asm
var audioElem = document.getElementById('playerAudio');
audioElem.src = MediaUrl;
audioElem.load();
audioElem.play();
var modal = document.getElementById('playerModal');
if (modal && modal.parentNode !== document.body) {
document.body.appendChild(modal);
}
// Create the Bootstrap modal object
var bsModal = new bootstrap.Modal(modal, { keyboard: false });
// Listen for when the modal *finishes* hiding:
modal.addEventListener('hidden.bs.modal', function (evt) {
// Pause and/or reset the audio
audioElem.pause();
audioElem.currentTime = 0;
}, { once: true });
// Show the modal
bsModal.show();
end;
{$ENDIF}
end);
// Add the button to the cell, and the cell to the row
Cell.appendChild(Button);
NewRow.appendChild(Cell);
// Appends new rows to the table body
TJSHTMLElement(document.getElementById('tblPhoneGrid').getElementsByTagName('tbody')[0]).appendChild(NewRow);
end;
procedure TFViewComplaints.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);
GetCalls(GenerateSearchOptions());
end;
end);
PageItem.appendChild(PageLink);
PaginationElement.appendChild(PageItem);
// Page Numbers
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;
GetCalls(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;
GetCalls(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;
GetCalls(generateSearchOptions());
end);
end;
PageItem.appendChild(PageLink);
PaginationElement.appendChild(PageItem);
// 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);
GetCalls(GenerateSearchOptions());
end;
end);
PageItem.appendChild(PageLink);
PaginationElement.appendChild(PageItem);
end;
procedure TFViewComplaints.GetCalls(searchOptions: string);
// Retrieves list of calls from the server that meet the criteria searchOptions
// searchOptions: information about how to generate the SQL statement based on
// user input.
var
xdcResponse: TXDataClientResponse;
callList : TJSObject;
i: integer;
data: TJSArray;
call: TJSObject;
callListLength: integer;
begin
if PageNumber > 0 then
begin
Utils.ShowSpinner('spinner');
xdcResponse := await(XDataWebClient1.RawInvokeAsync('ILookupService.GetCalls',
[searchOptions]));
callList := TJSObject(xdcResponse.Result);
data := TJSArray(callList['data']);
callListLength := integer(callList['count']);
ClearTable();
Utils.HideSpinner('spinner');
for i := 0 to data.Length - 1 do
begin
call := TJSObject(data[i]);
AddRowToTable(string(call['toNumber']), string(call['fromNumber']), string(call['dateCreated']),
string(call['duration']), string(call['transcription']), string(call['mediaUrl']));
end;
TotalPages := (callListLength + PageSize - 1) div PageSize;
if (PageNumber * PageSize) < callListLength then
begin
lblEntries.Caption := 'Showing entries ' + IntToStr((PageNumber - 1) * PageSize + 1) +
' - ' + IntToStr(PageNumber * PageSize) +
' of ' + IntToStr(callListLength);
end
else
begin
lblEntries.Caption := 'Showing entries ' + IntToStr((PageNumber - 1) * PageSize + 1) +
' - ' + IntToStr(callListLength) +
' of ' + IntToStr(callListLength);
end;
GeneratePagination(TotalPages);
end;
end; end;
procedure TFViewComplaints.btnApplyClick(Sender: TObject);
// Button that effectively functions as a GetCalls() button
var
searchOptions: string;
begin
PageNumber := 1;
PageSize := StrToInt(wcbPageSize.Text);
StartDate := dtpStartDate.Text;
EndDate := dtpEndDate.Text;
OrderBy := wcbSortBy.Text;
Caller := edtSearch.Text;
searchOptions := '&phonenumber=' + wcbLocation.Value +
'&pagenumber=' + IntToStr(PageNumber) +
'&pagesize=' + IntToStr(PageSize) +
'&startdate=' + StartDate +
'&enddate=' + EndDate +
'&orderby=' + OrderBy +
'&caller=' + Caller;
GetCalls(searchOptions);
end;
procedure TFViewComplaints.Search(searchOptions: string);
// Search method that searches the database for a specific phone number
var
xdcResponse: TXDataClientResponse;
callList : TJSObject;
i: integer;
data: TJSArray;
call: TJSObject;
callListLength: integer;
begin
if PageNumber > 0 then
begin
xdcResponse := await(XDataWebClient1.RawInvokeAsync('ILookupService.Search',
[searchOptions]));
callList := TJSObject(xdcResponse.Result);
data := TJSArray(callList['data']);
callListLength := integer(callList['count']);
ClearTable();
for i := 0 to data.Length - 1 do
begin
call := TJSObject(data[i]);
AddRowToTable(string(call['toNumber']), string(call['fromNumber']), string(call['dateCreated']),
string(call['duration']), string(call['transcription']), string(call['mediaUrl']));
end;
TotalPages := (callListLength + PageSize - 1) div PageSize;
lblEntries.Caption := 'Showing entries for phone number: ' + searchOptions;
end;
end;
procedure TFViewComplaints.btnSearchClick(Sender: TObject);
// calls Search method
begin
end;
procedure TFViewComplaints.ClearTable();
// clears the table
var
tbody: TJSHTMLElement;
begin
tbody := TJSHTMLElement(document.getElementById('tblPhoneGrid').getElementsByTagName('tbody')[0]);
tbody.innerHTML := '';
end;
function TFViewComplaints.GenerateSearchOptions(): string;
// Generates searchOptions for get calls.
var
searchOptions: string;
begin
PageSize := StrToInt(wcbPageSize.Text);
StartDate := dtpStartDate.Text;
EndDate := dtpEndDate.Text;
OrderBy := wcbSortBy.Text;
searchOptions := '&phonenumber=' + wcbLocation.Value +
'&pagenumber=' + IntToStr(PageNumber) +
'&pagesize=' + IntToStr(PageSize) +
'&startdate=' + StartDate +
'&enddate=' + EndDate +
'&orderby=' + OrderBy +
'&caller=' + Caller;
Result := searchOptions;
end;
end. end.
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