Commit 731ef776 by Mac Stephens

Units is up and working

parent d011eb7b
...@@ -67,52 +67,51 @@ object ApiDatabaseModule: TApiDatabaseModule ...@@ -67,52 +67,51 @@ object ApiDatabaseModule: TApiDatabaseModule
object uqDISUnitsActive: TUniQuery object uqDISUnitsActive: TUniQuery
Connection = ucENTCAD Connection = ucENTCAD
SQL.Strings = ( SQL.Strings = (
'SELECT' 'SELECT dua.UNITID, dua.UNITNAME,'
' dua.UNITID,' ' cun.CODE_DESC AS CARNUMBER_DESC,'
' dua.UNITNAME,' ' cd.CODE_DESC AS DISTRICT_DESC,'
' cun.CODE_DESC AS CARNUMBER_DESC,' ' cs.CODE_DESC AS SECTOR_DESC,'
' cd.CODE_DESC AS DISTRICT_DESC,' ' p1.PF_EMPNUM AS OFFICER1_EMPNUM,'
' cs.CODE_DESC AS SECTOR_DESC,' ' p1.PF_LNAME AS OFFICER1_LAST_NAME,'
' p1.PF_EMPNUM AS OFFICER1_EMPNUM,' ' p1.PF_FNAME AS OFFICER1_FIRST_NAME,'
' p1.PF_LNAME AS OFFICER1_LAST_NAME,' ' p1.PF_MI AS OFFICER1_MI,'
' p1.PF_FNAME AS OFFICER1_FIRST_NAME,' ' p2.PF_EMPNUM AS OFFICER2_EMPNUM,'
' p1.PF_MI AS OFFICER1_MI,' ' p2.PF_LNAME AS OFFICER2_LAST_NAME,'
' p2.PF_EMPNUM AS OFFICER2_EMPNUM,' ' p2.PF_FNAME AS OFFICER2_FIRST_NAME,'
' p2.PF_LNAME AS OFFICER2_LAST_NAME,' ' p2.PF_MI AS OFFICER2_MI,'
' p2.PF_FNAME AS OFFICER2_FIRST_NAME,' ' ca.LOCATION,'
' p2.PF_MI AS OFFICER2_MI,' ' ca.COMPLAINT,'
' ca.LOCATION,' ' ca.UNITSTATUS,'
' ca.COMPLAINT,' ' cus.CODE_DESC AS UNIT_STATUS_DESC,'
' ca.UNITSTATUS,' ' uc.ENTRYID,'
' cus.CODE_DESC AS UNIT_STATUS_DESC,' ' uc.GPS_LATITUDE,'
' uc.ENTRYID,' ' uc.GPS_LONGITUDE'
' uc.GPS_LATITUDE,'
' uc.GPS_LONGITUDE'
'FROM DIS_UNITS_ACTIVE dua' 'FROM DIS_UNITS_ACTIVE dua'
'LEFT JOIN CD_UNIT_NUMBER cun ON cun.AGENCYCODE = dua.CA' + 'LEFT JOIN CD_UNIT_NUMBER cun ON cun.AGENCYCODE = dua.CAR' +
'RNUMBER' 'NUMBER'
'LEFT JOIN CD_DISTRICT cd ON cd.AGENCYCODE = dua.DI' + 'LEFT JOIN CD_DISTRICT cd ON cd.AGENCYCODE = dua.DIS' +
'STRICT' 'TRICT'
'LEFT JOIN CD_SECTOR cs ON cs.AGENCYCODE = dua.SE' + 'LEFT JOIN CD_SECTOR cs ON cs.AGENCYCODE = dua.SEC' +
'CTOR AND cs.CODE_TYPE = cd.AGENCYCODE' 'TOR AND cs.CODE_TYPE = cd.AGENCYCODE'
'LEFT JOIN PERSONNEL p1 ON dua.OFFICER1ID = p1.PF_' + 'LEFT JOIN PERSONNEL p1 ON dua.OFFICER1ID = p1.PF_N' +
'NAMEID' 'AMEID'
'LEFT JOIN PERSONNEL p2 ON dua.OFFICER2ID = p2.PF_' + 'LEFT JOIN PERSONNEL p2 ON dua.OFFICER2ID = p2.PF_N' +
'NAMEID' 'AMEID'
'LEFT JOIN CFS_ACTIVE ca ON dua.UNITID = ca.UNI' + 'LEFT JOIN CFS_ACTIVE ca ON dua.UNITID = ca.UNIT' +
'TID' 'ID'
'LEFT JOIN CD_UNITSTATUS cus ON ca.UNITSTATUS = cus.CO' + 'LEFT JOIN CD_UNITSTATUS cus ON ca.UNITSTATUS = cus.COD' +
'DE' 'E'
'LEFT JOIN UNITS_CURRENT@AVL_LINK uc ON dua.UNITID = uc.UNI' + 'LEFT JOIN UNITS_CURRENT@AVL_LINK uc ON dua.UNITID = uc.UNIT' +
'TID') 'ID'
'FETCH FIRST 100 ROWS ONLY')
ReadOnly = True ReadOnly = True
Left = 462 Left = 462
Top = 374 Top = 374
...@@ -188,14 +187,6 @@ object ApiDatabaseModule: TApiDatabaseModule ...@@ -188,14 +187,6 @@ object ApiDatabaseModule: TApiDatabaseModule
ReadOnly = True ReadOnly = True
Size = 10 Size = 10
end end
object uqDISUnitsActiveUNITSTATUS: TFloatField
FieldName = 'UNITSTATUS'
ReadOnly = True
end
object uqDISUnitsActiveUNIT_STATUS_DESC: TStringField
FieldName = 'UNIT_STATUS_DESC'
ReadOnly = True
end
object uqDISUnitsActiveENTRYID: TFloatField object uqDISUnitsActiveENTRYID: TFloatField
FieldName = 'ENTRYID' FieldName = 'ENTRYID'
ReadOnly = True ReadOnly = True
...@@ -208,6 +199,14 @@ object ApiDatabaseModule: TApiDatabaseModule ...@@ -208,6 +199,14 @@ object ApiDatabaseModule: TApiDatabaseModule
FieldName = 'GPS_LONGITUDE' FieldName = 'GPS_LONGITUDE'
ReadOnly = True ReadOnly = True
end end
object uqDISUnitsActiveUNITSTATUS: TFloatField
FieldName = 'UNITSTATUS'
ReadOnly = True
end
object uqDISUnitsActiveUNIT_STATUS_DESC: TStringField
FieldName = 'UNIT_STATUS_DESC'
ReadOnly = True
end
end end
object uqCFSActive: TUniQuery object uqCFSActive: TUniQuery
Connection = ucENTCAD Connection = ucENTCAD
...@@ -335,17 +334,32 @@ object ApiDatabaseModule: TApiDatabaseModule ...@@ -335,17 +334,32 @@ object ApiDatabaseModule: TApiDatabaseModule
' ct.DATEDISPATCHED,' ' ct.DATEDISPATCHED,'
' ct.DATERESPONDED,' ' ct.DATERESPONDED,'
' ct.DATEARRIVED,' ' ct.DATEARRIVED,'
' ct.DATECLEARED' ' ct.DATECLEARED,'
' cp.COLOR AS PRIORITY_COLOR,'
' cd.CODE_DESC AS DISTRICT_DESC,'
' cs.CODE_DESC AS SECTOR_DESC'
'FROM COMPLAINT_ACTIVE ca' 'FROM COMPLAINT_ACTIVE ca'
'JOIN COMPLAINT_TIMES ct ON ca.COMPLAINTID = ct.COMPLAINTID' 'JOIN COMPLAINT_TIMES ct ON ca.COMPLAINTID = ct.COMPLAINTID'
'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'
'LEFT JOIN CD_CALLPRIORITIES cp ON cp.CODE = ca.PRIORITY AND cp.A' +
'GENCY = ca.AGENCY'
'LEFT JOIN CD_DISTRICT cd ON cd.AGENCYCODE = ca.DISPATCHDI' +
'STRICT'
'LEFT JOIN CD_SECTOR cs ON cs.AGENCYCODE = ca.DISPATCHSE' +
'CTOR AND cs.CODE_TYPE = cd.AGENCYCODE '
'WHERE ca.COMPLAINT IS NOT NULL' 'WHERE ca.COMPLAINT IS NOT NULL'
'ORDER BY ct.DATEREPORTED DESC, ca.PRIORITY DESC'
'ORDER BY ca.DISPATCHDISTRICT, ct.DATEREPORTED DESC, ca.PRIORITY ' +
'DESC'
'FETCH FIRST 10 ROWS ONLY') 'FETCH FIRST 10 ROWS ONLY')
ReadOnly = True ReadOnly = True
OnCalcFields = uqComplaintListCalcFields
Left = 76 Left = 76
Top = 322 Top = 324
object uqComplaintListCOMPLAINTID: TFloatField object uqComplaintListCOMPLAINTID: TFloatField
FieldName = 'COMPLAINTID' FieldName = 'COMPLAINTID'
Required = True Required = True
...@@ -452,6 +466,26 @@ object ApiDatabaseModule: TApiDatabaseModule ...@@ -452,6 +466,26 @@ object ApiDatabaseModule: TApiDatabaseModule
FieldName = 'DATECLEARED' FieldName = 'DATECLEARED'
ReadOnly = True ReadOnly = True
end end
object uqComplaintListcomplaintNumber: TStringField
FieldKind = fkCalculated
FieldName = 'complaintNumber'
Size = 11
Calculated = True
end
object uqComplaintListPRIORITY_COLOR: TFloatField
FieldName = 'PRIORITY_COLOR'
ReadOnly = True
end
object uqComplaintListDISTRICT_DESC: TStringField
FieldName = 'DISTRICT_DESC'
ReadOnly = True
Size = 120
end
object uqComplaintListSECTOR_DESC: TStringField
FieldName = 'SECTOR_DESC'
ReadOnly = True
Size = 120
end
end end
object uqComplaintDetails: TUniQuery object uqComplaintDetails: TUniQuery
Connection = ucENTCAD Connection = ucENTCAD
...@@ -617,6 +651,7 @@ object ApiDatabaseModule: TApiDatabaseModule ...@@ -617,6 +651,7 @@ object ApiDatabaseModule: TApiDatabaseModule
Port = 1521 Port = 1521
Username = 'ENTCAD' Username = 'ENTCAD'
Server = 'BUFENTCAD' Server = 'BUFENTCAD'
Connected = True
LoginPrompt = False LoginPrompt = False
Left = 76 Left = 76
Top = 244 Top = 244
......
...@@ -113,12 +113,17 @@ type ...@@ -113,12 +113,17 @@ type
uqDISUnitsActiveOFFICER2_MI: TStringField; uqDISUnitsActiveOFFICER2_MI: TStringField;
uqDISUnitsActiveLOCATION: TStringField; uqDISUnitsActiveLOCATION: TStringField;
uqDISUnitsActiveCOMPLAINT: TStringField; uqDISUnitsActiveCOMPLAINT: TStringField;
uqDISUnitsActiveUNITSTATUS: TFloatField;
uqDISUnitsActiveUNIT_STATUS_DESC: TStringField;
uqDISUnitsActiveENTRYID: TFloatField; uqDISUnitsActiveENTRYID: TFloatField;
uqDISUnitsActiveGPS_LATITUDE: TFloatField; uqDISUnitsActiveGPS_LATITUDE: TFloatField;
uqDISUnitsActiveGPS_LONGITUDE: TFloatField; uqDISUnitsActiveGPS_LONGITUDE: TFloatField;
uqComplaintListcomplaintNumber: TStringField;
uqComplaintListPRIORITY_COLOR: TFloatField;
uqComplaintListDISTRICT_DESC: TStringField;
uqComplaintListSECTOR_DESC: TStringField;
uqDISUnitsActiveUNITSTATUS: TFloatField;
uqDISUnitsActiveUNIT_STATUS_DESC: TStringField;
procedure DataModuleCreate(Sender: TObject); procedure DataModuleCreate(Sender: TObject);
procedure uqComplaintListCalcFields(DataSet: TDataSet);
private private
{ Private declarations } { Private declarations }
public public
...@@ -194,4 +199,19 @@ begin ...@@ -194,4 +199,19 @@ begin
end; end;
end; end;
procedure TApiDatabaseModule.uqComplaintListCalcFields(DataSet: TDataSet);
var
raw: string;
begin
raw := uqComplaintListCOMPLAINT.AsString.Trim;
if raw.Length >= 3 then
uqComplaintListcomplaintNumber.AsString := Copy(raw, 1, 2) + '-' + Copy(raw, 3, MaxInt)
else if raw.Length = 2 then
uqComplaintListcomplaintNumber.AsString := raw + '-'
else
uqComplaintListcomplaintNumber.AsString := raw;
end;
end. end.
...@@ -17,6 +17,7 @@ type ...@@ -17,6 +17,7 @@ type
IApiService = interface(IInvokable) IApiService = interface(IInvokable)
['{4FCB7FAF-44E5-49D6-9C0F-EE44BFB33313}'] ['{4FCB7FAF-44E5-49D6-9C0F-EE44BFB33313}']
[HttpGet] function GetComplaintList: TJSONObject; [HttpGet] function GetComplaintList: TJSONObject;
[HttpGet] function GetUnitList: TJSONObject;
end; end;
implementation implementation
......
...@@ -4,8 +4,8 @@ interface ...@@ -4,8 +4,8 @@ interface
uses uses
XData.Server.Module, XData.Service.Common, Api.Database, Data.DB, XData.Server.Module, XData.Service.Common, Api.Database, Data.DB,
System.SysUtils, System.Generics.Collections, XData.Sys.Exceptions, System.SysUtils, System.Generics.Collections, XData.Sys.Exceptions, System.StrUtils,
System.Hash, System.Classes, Common.Logging, System.JSON, Api.Service; System.Hash, System.Classes, Common.Logging, System.JSON, Api.Service, VCL.Forms;
type type
...@@ -18,6 +18,7 @@ type ...@@ -18,6 +18,7 @@ type
procedure BeforeDestruction; override; procedure BeforeDestruction; override;
public public
function GetComplaintList: TJSONObject; function GetComplaintList: TJSONObject;
function GetUnitList: TJSONObject;
end; end;
implementation implementation
...@@ -42,6 +43,7 @@ end; ...@@ -42,6 +43,7 @@ end;
function TApiService.GetComplaintList: TJSONObject; function TApiService.GetComplaintList: TJSONObject;
var var
data: TJSONArray; data: TJSONArray;
lastDistrict: string;
begin begin
Logger.Log(3, '---TApiService.GetComplaintList initiated'); Logger.Log(3, '---TApiService.GetComplaintList initiated');
...@@ -50,6 +52,7 @@ begin ...@@ -50,6 +52,7 @@ begin
data := TJSONArray.Create; data := TJSONArray.Create;
try try
lastDistrict := '';
with ApiDB.uqComplaintList do with ApiDB.uqComplaintList do
begin begin
Open; Open;
...@@ -67,14 +70,35 @@ begin ...@@ -67,14 +70,35 @@ begin
status := 'Pending'; status := 'Pending';
var item := TJSONObject.Create; var item := TJSONObject.Create;
// Add a section header only when the district changes
var curDistrict := ApiDB.uqComplaintListDISPATCHDISTRICT.AsString;
if not SameText(curDistrict, lastDistrict) then
item.AddPair('DistrictHeader', curDistrict);
lastDistrict := curDistrict;
var districtSector := ApiDB.uqComplaintListDISTRICT_DESC.AsString + ApiDB.uqComplaintListSECTOR_DESC.AsString;
item.AddPair('DistrictSector', districtSector);
// existing color hex
var colorVal := ApiDB.uqComplaintListPRIORITY_COLOR.AsInteger;
item.AddPair('PriorityColor', '#' + IntToHex(colorVal and $FFFFFF, 6));
// Text is white only for the deep blue (255 = $0000FF), black otherwise
if (colorVal and $FFFFFF) = $0000FF then
item.AddPair('PriorityTextColor', '#FFFFFF')
else
item.AddPair('PriorityTextColor', '#000000');
item.AddPair('ComplaintId', ApiDB.uqComplaintListCOMPLAINTID.AsString); item.AddPair('ComplaintId', ApiDB.uqComplaintListCOMPLAINTID.AsString);
item.AddPair('Complaint', ApiDB.uqComplaintListcomplaintNumber.AsString);
item.AddPair('Agency', ApiDB.uqComplaintListAGENCY.AsString); item.AddPair('Agency', ApiDB.uqComplaintListAGENCY.AsString);
item.AddPair('Priority', TJSONNumber.Create(ApiDB.uqComplaintListPRIORITY.AsString)); item.AddPair('Priority', ApiDB.uqComplaintListPRIORITY.AsString);
item.AddPair('DispatchCodeDesc', ApiDB.uqComplaintListDISPATCH_CODE_DESC.AsString); item.AddPair('DispatchCodeDesc', ApiDB.uqComplaintListDISPATCH_CODE_DESC.AsString);
item.AddPair('Address', ApiDB.uqComplaintListADDRESS.AsString); item.AddPair('Address', ApiDB.uqComplaintListADDRESS.AsString);
item.AddPair('CFSId', ApiDB.uqComplaintListCFSID.AsString); item.AddPair('CFSId', ApiDB.uqComplaintListCFSID.AsString);
item.AddPair('Status', status); item.AddPair('Status', status);
item.AddPair('DispatchDistrict', ApiDB.uqComplaintListDISPATCHDISTRICT.AsString); item.AddPair('DispatchDistrict', curDistrict);
item.AddPair('DateReported', ApiDB.uqComplaintListDATEREPORTED.AsString); item.AddPair('DateReported', ApiDB.uqComplaintListDATEREPORTED.AsString);
data.AddElement(item); data.AddElement(item);
...@@ -95,6 +119,91 @@ begin ...@@ -95,6 +119,91 @@ begin
end; end;
function TApiService.GetUnitList: TJSONObject;
var
data: TJSONArray;
lastDistrict: string;
begin
Logger.Log(3, '---TApiService.GetUnitList initiated');
Result := TJSONObject.Create;
TXDataOperationContext.Current.Handler.ManagedObjects.Add(Result);
data := TJSONArray.Create;
try
lastDistrict := '';
with ApiDB.uqDISUnitsActive do
begin
Open;
First;
while not Eof do
begin
var item := TJSONObject.Create;
// Group header: show once when district changes (e.g., "1", "A")
var curDistrict := ApiDB.uqDISUnitsActiveDISTRICT_DESC.AsString;
if not SameText(curDistrict, lastDistrict) then
item.AddPair('DistrictHeader', curDistrict);
lastDistrict := curDistrict;
// Core unit identity
item.AddPair('UnitId', ApiDB.uqDISUnitsActiveUNITID.AsString);
item.AddPair('UnitName', ApiDB.uqDISUnitsActiveUNITNAME.AsString);
item.AddPair('CarNumberDesc', ApiDB.uqDISUnitsActiveCARNUMBER_DESC.AsString);
item.AddPair('District', curDistrict);
item.AddPair('Sector', ApiDB.uqDISUnitsActiveSECTOR_DESC.AsString);
// Current assignment (if any)
item.AddPair('Location', ApiDB.uqDISUnitsActiveLOCATION.AsString);
item.AddPair('Complaint', ApiDB.uqDISUnitsActiveCOMPLAINT.AsString);
// Status: default to "Available" when no active CFS row
var statusDesc := ApiDB.uqDISUnitsActiveUNIT_STATUS_DESC.AsString;
if statusDesc = '' then
statusDesc := 'Available';
item.AddPair('Status', statusDesc);
// Officers (LAST, FIRST [MI])
var o1 := Trim(ApiDB.uqDISUnitsActiveOFFICER1_LAST_NAME.AsString);
var f1 := Trim(ApiDB.uqDISUnitsActiveOFFICER1_FIRST_NAME.AsString);
var m1 := Trim(ApiDB.uqDISUnitsActiveOFFICER1_MI.AsString);
if o1 <> '' then
begin
if f1 <> '' then o1 := o1 + ', ' + f1;
if m1 <> '' then o1 := o1 + ' ' + m1;
item.AddPair('Officer1', o1);
end;
var o2 := Trim(ApiDB.uqDISUnitsActiveOFFICER2_LAST_NAME.AsString);
var f2 := Trim(ApiDB.uqDISUnitsActiveOFFICER2_FIRST_NAME.AsString);
var m2 := Trim(ApiDB.uqDISUnitsActiveOFFICER2_MI.AsString);
if o2 <> '' then
begin
if f2 <> '' then o2 := o2 + ', ' + f2;
if m2 <> '' then o2 := o2 + ' ' + m2;
item.AddPair('Officer2', o2);
end;
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.GetUnitList End (error)');
raise EXDataHttpException.Create(500, 'Failed to load units list');
end;
Logger.Log(3, '---TApiService.GetUnitList End');
end;
initialization initialization
RegisterServiceType(TApiService); RegisterServiceType(TApiService);
......
...@@ -71,6 +71,7 @@ begin ...@@ -71,6 +71,7 @@ begin
FData.Free; FData.Free;
end; end;
procedure TFMain.ContactFormData(AText: String); procedure TFMain.ContactFormData(AText: String);
begin begin
if memoInfo.CanFocus then if memoInfo.CanFocus then
......
[Settings] [Settings]
LogFileNum=414 LogFileNum=451
webClientVersion=0.1.0 webClientVersion=0.1.0
TwilioUpdateTime=1 TwilioUpdateTime=0
[Database] [Database]
Server=192.168.102.130 Server=192.168.102.130
......
...@@ -11,7 +11,19 @@ object FViewComplaints: TFViewComplaints ...@@ -11,7 +11,19 @@ object FViewComplaints: TFViewComplaints
ParentFont = False ParentFont = False
Visible = True Visible = True
OnCreate = WebFormCreate OnCreate = WebFormCreate
object WebButton1: TWebButton object lblEntries: TWebLabel
Left = 44
Top = 88
Width = 43
Height = 13
Caption = 'lblEntries'
ElementFont = efCSS
HeightStyle = ssAuto
HeightPercent = 100.000000000000000000
Visible = False
WidthPercent = 100.000000000000000000
end
object btnGroup: TWebButton
Left = 180 Left = 180
Top = 110 Top = 110
Width = 43 Width = 43
...@@ -25,7 +37,7 @@ object FViewComplaints: TFViewComplaints ...@@ -25,7 +37,7 @@ object FViewComplaints: TFViewComplaints
HeightPercent = 100.000000000000000000 HeightPercent = 100.000000000000000000
WidthPercent = 100.000000000000000000 WidthPercent = 100.000000000000000000
end end
object WebButton2: TWebButton object btnFilter: TWebButton
Left = 242 Left = 242
Top = 110 Top = 110
Width = 37 Width = 37
...@@ -39,7 +51,7 @@ object FViewComplaints: TFViewComplaints ...@@ -39,7 +51,7 @@ object FViewComplaints: TFViewComplaints
HeightPercent = 100.000000000000000000 HeightPercent = 100.000000000000000000
WidthPercent = 100.000000000000000000 WidthPercent = 100.000000000000000000
end end
object Complaints: TWebButton object btnRefresh: TWebButton
Left = 114 Left = 114
Top = 110 Top = 110
Width = 53 Width = 53
...@@ -52,6 +64,7 @@ object FViewComplaints: TFViewComplaints ...@@ -52,6 +64,7 @@ object FViewComplaints: TFViewComplaints
HeightStyle = ssAuto HeightStyle = ssAuto
HeightPercent = 100.000000000000000000 HeightPercent = 100.000000000000000000
WidthPercent = 100.000000000000000000 WidthPercent = 100.000000000000000000
OnClick = btnRefreshClick
end end
object dblComplaintsList: TWebDBListControl object dblComplaintsList: TWebDBListControl
Left = 36 Left = 36
...@@ -63,39 +76,82 @@ object FViewComplaints: TFViewComplaints ...@@ -63,39 +76,82 @@ object FViewComplaints: TFViewComplaints
HeightPercent = 100.000000000000000000 HeightPercent = 100.000000000000000000
WidthPercent = 100.000000000000000000 WidthPercent = 100.000000000000000000
ChildOrder = 3 ChildOrder = 3
DefaultItemClassName = 'list-group-item' DefaultItemClassName = 'list-group-item p-1 border-0'
DefaultItemLinkClassName = 'list-group-link' DefaultItemLinkClassName = 'list-group-link'
ElementFont = efCSS ElementFont = efCSS
ElementListClassName = 'list-group' ElementListClassName = 'list-group list-group-flush border-0'
Items = < Items = <>
item
ItemClassName = 'list-group-item'
Items = <>
LinkClassName = 'list-group-link'
Text = 'Item 0'
end
item
ItemClassName = 'list-group-item'
Items = <>
LinkClassName = 'list-group-link'
Text = 'Item 1'
end
item
ItemClassName = 'list-group-item'
Items = <>
LinkClassName = 'list-group-link'
Text = 'Item 2'
end>
Style = lsListGroup Style = lsListGroup
DataSource = wdsComplaints
ItemTemplate =
'<div class="list-section-header small fw-semibold bg-body-second' +
'ary text-dark rounded-1 px-2 mb-1"> (%DistrictHeader%)</div><di' +
'v class="card border shadow-sm" style="--bs-card-bg:(%Priori' +
'tyColor%); --bs-card-color:(%PriorityTextColor%);"> <div class=' +
'"card-body py-2 px-3"> <div class="fw-bold text-uppercase sma' +
'll">(%Priority%): (%DispatchCodeDesc%)</div> <div class="smal' +
'l">(%Address%)</div> <div class="small text-opacity-75">(%Com' +
'plaint%): (%Status%)&nbsp;&nbsp;(%DistrictSector%)</div> <div' +
' class="small text-opacity-75">(%DateReported%)</div> </div></d' +
'iv>'
ListSource = wdsComplaints
end end
object xdwcComplaints: TXDataWebClient object xdwcComplaints: TXDataWebClient
Connection = DMConnection.ApiConnection Connection = DMConnection.ApiConnection
Left = 92 Left = 58
Top = 416 Top = 410
end end
object xdwdsComplaints: TXDataWebDataSet object xdwdsComplaints: TXDataWebDataSet
Connection = DMConnection.ApiConnection Connection = DMConnection.ApiConnection
Left = 214 Left = 260
Top = 414 Top = 412
object xdwdsComplaintsComplaintId: TStringField
FieldName = 'ComplaintId'
end
object xdwdsComplaintsComplaint: TStringField
FieldName = 'Complaint'
end
object xdwdsComplaintsAgency: TStringField
FieldName = 'Agency'
end
object xdwdsComplaintsPriority: TStringField
FieldName = 'Priority'
end
object xdwdsComplaintsDispatchCodeDesc: TStringField
FieldName = 'DispatchCodeDesc'
end
object xdwdsComplaintsAddress: TStringField
FieldName = 'Address'
end
object xdwdsComplaintsStatus: TStringField
FieldName = 'Status'
end
object xdwdsComplaintsDispatchDistrict: TStringField
FieldName = 'DispatchDistrict'
end
object xdwdsComplaintsDateReported: TStringField
FieldName = 'DateReported'
end
object xdwdsComplaintsDistrictHeader: TStringField
FieldName = 'DistrictHeader'
end
object xdwdsComplaintsStatusColor: TStringField
FieldName = 'StatusColor'
end
object xdwdsComplaintsPriorityColor: TStringField
FieldName = 'PriorityColor'
end
object xdwdsComplaintsPriorityTextColor: TStringField
FieldName = 'PriorityTextColor'
end
object xdwdsComplaintsDistrictSector: TStringField
FieldName = 'DistrictSector'
end
end
object wdsComplaints: TWebDataSource
AutoEdit = False
DataSet = xdwdsComplaints
Left = 156
Top = 410
end end
end end
...@@ -48,7 +48,7 @@ ...@@ -48,7 +48,7 @@
</div> </div>
<!-- Entry Count Label --> <!-- Entry Count Label -->
<label id="lblentries" class="mt-2 d-block"></label> <label id="complaints_lblentries" class="mt-2 d-block"></label>
<!-- Pagination --> <!-- Pagination -->
<nav aria-label="Page navigation"> <nav aria-label="Page navigation">
......
...@@ -5,30 +5,40 @@ interface ...@@ -5,30 +5,40 @@ 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, WebLib.DB, XData.Web.Client, WEBLib.ExtCtrls, XData.Web.JsonDataset,
XData.Web.Dataset, XData.Web.Connection, Vcl.Forms, DateUtils, WEBLib.DBCtrls; XData.Web.Dataset, XData.Web.Connection, Vcl.Forms, DateUtils, WEBLib.DBCtrls, System.Generics.Collections,
WEBLib.Menus, WEBLib.JSON, Auth.Service, WebLib.Storage, ConnectionModule, App.Types,
WEBLib.DB, Data.DB, XData.Web.DatasetCommon, JS, XData.Model.Classes, Utils;
type type
TFViewComplaints = class(TWebForm) TFViewComplaints = class(TWebForm)
xdwcComplaints: TXDataWebClient; xdwcComplaints: TXDataWebClient;
xdwdsComplaints: TXDataWebDataSet; xdwdsComplaints: TXDataWebDataSet;
WebButton1: TWebButton;
WebButton2: TWebButton;
Complaints: TWebButton;
dblComplaintsList: TWebDBListControl; dblComplaintsList: TWebDBListControl;
xdwdsComplaintsComplaint: TStringField;
xdwdsComplaintsAgency: TStringField;
xdwdsComplaintsPriority: TStringField;
xdwdsComplaintsDispatchCodeDesc: TStringField;
xdwdsComplaintsAddress: TStringField;
xdwdsComplaintsStatus: TStringField;
xdwdsComplaintsDispatchDistrict: TStringField;
xdwdsComplaintsDateReported: TStringField;
lblEntries: TWebLabel;
btnRefresh: TWebButton;
btnGroup: TWebButton;
btnFilter: TWebButton;
wdsComplaints: TWebDataSource;
xdwdsComplaintsComplaintId: TStringField;
xdwdsComplaintsDistrictHeader: TStringField;
xdwdsComplaintsStatusColor: TStringField;
xdwdsComplaintsPriorityColor: TStringField;
xdwdsComplaintsPriorityTextColor: TStringField;
xdwdsComplaintsDistrictSector: TStringField;
procedure WebFormCreate(Sender: TObject); procedure WebFormCreate(Sender: TObject);
procedure btnRefreshClick(Sender: TObject);
private private
FChildForm: TWebForm; [async] procedure GetComplaints;
var
PageNumber: integer;
PageSize: integer;
TotalPages: integer;
StartDate: string;
EndDate: string;
OrderBy: string;
Caller: string;
public public
end; end;
var var
...@@ -36,18 +46,71 @@ var ...@@ -36,18 +46,71 @@ var
implementation implementation
uses
JS, XData.Model.Classes,
ConnectionModule, Utils;
{$R *.dfm} {$R *.dfm}
procedure TFViewComplaints.WebFormCreate(Sender: TObject); procedure TFViewComplaints.WebFormCreate(Sender: TObject);
begin begin
console.log('WebFormCreate: Starting setup...');
DMConnection.ApiConnection.Connected := True; DMConnection.ApiConnection.Connected := True;
console.log('API connection active:', DMConnection.ApiConnection.Connected);
GetComplaints;
end;
//HTML for individual complaint cards can be found in the twebdblistcontrol HTMLString property
procedure TFViewComplaints.btnRefreshClick(Sender: TObject);
begin
GetComplaints;
end; end;
procedure TFViewComplaints.GetComplaints;
var
xdcResponse: TXDataClientResponse;
respObj: TJSObject;
complaintsCount: Integer;
begin
console.log('GetComplaints: Invoking API...');
Utils.ShowSpinner('spinner');
try
try
xdcResponse := await(xdwcComplaints.RawInvokeAsync('IApiService.GetComplaintList', []));
console.log('RawInvoke returned:', xdcResponse.Result);
respObj := TJSObject(xdcResponse.Result);
xdwdsComplaints.Close;
console.log('Dataset closed');
xdwdsComplaints.SetJsonData(respObj['data']);
console.log('JsonData set on dataset:', respObj['data']);
xdwdsComplaints.Open;
console.log('PriorityColor field name = ' +
xdwdsComplaintsPriorityColor.FieldName +
' sample value = ' +
xdwdsComplaintsPriorityColor.AsString);
if xdwdsComplaints.RecordCount > 0 then
begin
console.log('First record - Complaint:' + xdwdsComplaints.FieldByName('Complaint').AsString);
end;
complaintsCount := Integer(respObj['count']);
lblEntries.Caption := Format('%d active complaints', [complaintsCount]);
console.log('Label updated:' + lblEntries.Caption);
except
on E: EXDataClientRequestException do
begin
console.log('XData exception:' + E.ErrorResult.ErrorMessage);
Utils.ShowErrorModal(E.ErrorResult.ErrorMessage);
end;
end;
finally
Utils.HideSpinner('spinner');
console.log('GetComplaints complete');
end;
end;
end. end.
......
object FViewUnits: TFViewUnits object FViewUnits: TFViewUnits
Width = 534 Width = 359
Height = 426 Height = 480
Font.Charset = DEFAULT_CHARSET Font.Charset = DEFAULT_CHARSET
Font.Color = clWindowText Font.Color = clWindowText
Font.Height = -11 Font.Height = -11
Font.Name = 'Tahoma' Font.Name = 'Tahoma'
Font.Style = [] Font.Style = []
ParentFont = False ParentFont = False
OnCreate = WebFormCreate
object lblEntries: TWebLabel
Left = 54
Top = 46
Width = 43
Height = 13
Caption = 'lblEntries'
ElementFont = efCSS
HeightStyle = ssAuto
HeightPercent = 100.000000000000000000
Visible = False
WidthPercent = 100.000000000000000000
end
object dblUnitsList: TWebDBListControl
Left = 50
Top = 146
Width = 263
Height = 237
ElementID = 'units_dbl_unit_list'
HeightStyle = ssAuto
HeightPercent = 100.000000000000000000
WidthPercent = 100.000000000000000000
ChildOrder = 3
DefaultItemClassName = 'list-group-item p-1 border-0'
DefaultItemLinkClassName = 'list-group-link'
ElementFont = efCSS
ElementListClassName = 'list-group list-group-flush border-0'
Items = <>
Style = lsListGroup
DataSource = wdsUnits
ItemTemplate =
'<div class="list-section-header small fw-semibold bg-body-second' +
'ary text-dark rounded-1 px-2 mb-1"> (%DistrictHeader%)</div><di' +
'v class="card border shadow-sm"> <div class="card-body py-2 px-' +
'3"> <div class="d-flex justify-content-between align-items-ba' +
'seline"> <div class="fw-bold fs-6">(%UnitName%)</div> ' +
'<div class="small text-end text-body-secondary ms-3 text-truncat' +
'e">(%Location%)</div> </div> <div class="small">(%Status%)' +
'</div> <div class="small">(%Officer1%)</div> <div class="s' +
'mall">(%Officer2%)</div> </div></div>'
ListSource = wdsUnits
end
object btnRefresh: TWebButton
Left = 110
Top = 82
Width = 53
Height = 25
Caption = 'Refresh'
ChildOrder = 1
ElementClassName = 'btn btn-light'
ElementID = 'units_btnrefresh'
ElementFont = efCSS
HeightStyle = ssAuto
HeightPercent = 100.000000000000000000
WidthPercent = 100.000000000000000000
OnClick = btnRefreshClick
end
object btnGroup: TWebButton
Left = 186
Top = 82
Width = 43
Height = 25
Caption = 'Group'
ChildOrder = 1
ElementClassName = 'btn btn-light'
ElementID = 'units_btngroup'
ElementFont = efCSS
HeightStyle = ssAuto
HeightPercent = 100.000000000000000000
WidthPercent = 100.000000000000000000
end
object btnFilter: TWebButton
Left = 250
Top = 82
Width = 37
Height = 25
Caption = 'Filter'
ChildOrder = 1
ElementClassName = 'btn btn-light'
ElementID = 'units_btnfilter'
ElementFont = efCSS
HeightStyle = ssAuto
HeightPercent = 100.000000000000000000
WidthPercent = 100.000000000000000000
end
object wdsUnits: TWebDataSource
AutoEdit = False
DataSet = xdwdsUnits
Left = 156
Top = 410
end
object xdwdsUnits: TXDataWebDataSet
Connection = DMConnection.ApiConnection
Left = 260
Top = 412
object xdwdsUnitsDistrictHeader: TStringField
FieldName = 'DistrictHeader'
end
object xdwdsUnitsUnitId: TStringField
FieldName = 'UnitId'
end
object xdwdsUnitsUnitName: TStringField
FieldName = 'UnitName'
end
object xdwdsUnitsLocation: TStringField
FieldName = 'Location'
end
object xdwdsUnitsStatus: TStringField
FieldName = 'Status'
end
object xdwdsUnitsOfficer1: TStringField
FieldName = 'Officer1'
end
object xdwdsUnitsOfficer2: TStringField
FieldName = 'Officer2'
end
end
object xdwcUnits: TXDataWebClient
Connection = DMConnection.ApiConnection
Left = 58
Top = 410
end
end end
<div class="sticky-top"> <div class="sticky-top">
<!-- Local navbar (Complaints) --> <!-- Local navbar (Units) -->
<nav class="navbar navbar-dark bg-primary py-2"><!-- removed sticky-top --> <nav class="navbar navbar-dark bg-primary py-2"><!-- removed sticky-top -->
<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="units.title" class="navbar-brand mb-0 h5 text-white">Units</span> <span id="units_title" class="navbar-brand mb-0 h5 text-white">Units</span>
</div> </div>
<div class="col"> <div class="col">
<button id="units.btnrefresh" type="button" class="btn btn-primary w-100 h-100"> <button id="units_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="units.btngroup" type="button" class="btn btn-primary w-100 h-100"> <button id="units_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="units.btnfilter" type="button" class="btn btn-primary w-100 h-100"> <button id="units_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,51 +31,33 @@ ...@@ -31,51 +31,33 @@
<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="units.search" class="form-control" placeholder="Search..."> <input id="units_search" class="form-control" placeholder="Search...">
</div> </div>
</div> </div>
</div> </div>
</div> <!-- /sticky-top wrapper --> </div> <!-- /sticky-top wrapper -->
<!-- Existing content (unchanged) --> <!-- Units list container -->
<div class="row"> <div class="container-fluid mt-2">
<div class="col-12"> <div class="row justify-content-center">
<div class="container mt-4"> <div class="col-12 col-md-10 col-lg-8">
<div class="row justify-content-center"> <!-- This is where the DBListControl will inject cards -->
<div class="col-12 col-md-10 col-lg-8"> <div id="units_dbl_unit_list" class="d-flex flex-column gap-2">
<h1 class="page-header pt-3 pb-2 mb-3 border-bottom fs-4 fw-bold" id="view.calls.title">Units</h1> <!-- Cards will render here -->
<!-- Data Table --> </div>
<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>
<!-- Entry Count Label --> <!-- Entry Count Label -->
<label id="lblentries" class="mt-2 d-block"></label> <label id="unitss_lblentries" class="mt-2 d-block"></label>
<!-- 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>
...@@ -3,13 +3,34 @@ unit View.Units; ...@@ -3,13 +3,34 @@ unit View.Units;
interface interface
uses uses
System.SysUtils, System.Classes, WEBLib.Graphics, WEBLib.Controls, WEBLib.Forms, WEBLib.Dialogs, System.SysUtils, System.Classes, Web, WEBLib.Graphics, WEBLib.Forms, WEBLib.Dialogs,
Vcl.Controls, Vcl.StdCtrls, Vcl.Controls, Vcl.StdCtrls, WEBLib.StdCtrls, WEBLib.Controls, WEBLib.Grids, WebLib.Lists,
XData.Web.Client, WEBLib.ExtCtrls, XData.Web.JsonDataset,
XData.Web.Connection, WEBLib.StdCtrls; XData.Web.Dataset, XData.Web.Connection, Vcl.Forms, DateUtils, WEBLib.DBCtrls, System.Generics.Collections,
WEBLib.Menus, WEBLib.JSON, Auth.Service, WebLib.Storage, ConnectionModule, App.Types,
WEBLib.DB, Data.DB, XData.Web.DatasetCommon, JS, XData.Model.Classes, Utils;
type type
TFViewUnits = class(TWebForm) TFViewUnits = class(TWebForm)
dblUnitsList: TWebDBListControl;
btnRefresh: TWebButton;
btnGroup: TWebButton;
btnFilter: TWebButton;
wdsUnits: TWebDataSource;
xdwdsUnits: TXDataWebDataSet;
xdwcUnits: TXDataWebClient;
lblEntries: TWebLabel;
xdwdsUnitsDistrictHeader: TStringField;
xdwdsUnitsUnitId: TStringField;
xdwdsUnitsUnitName: TStringField;
xdwdsUnitsLocation: TStringField;
xdwdsUnitsStatus: TStringField;
xdwdsUnitsOfficer1: TStringField;
xdwdsUnitsOfficer2: TStringField;
procedure WebFormCreate(Sender: TObject);
procedure btnRefreshClick(Sender: TObject);
private
[async] procedure GetUnits;
public public
end; end;
...@@ -21,7 +42,61 @@ implementation ...@@ -21,7 +42,61 @@ implementation
{$R *.dfm} {$R *.dfm}
{ TFViewErrorPage }
procedure TFViewUnits.WebFormCreate(Sender: TObject);
begin
console.log('Units.WebFormCreate: Starting setup...');
DMConnection.ApiConnection.Connected := True;
console.log('API connection active:', DMConnection.ApiConnection.Connected);
GetUnits;
end;
procedure TFViewUnits.btnRefreshClick(Sender: TObject);
begin
GetUnits;
end;
procedure TFViewUnits.GetUnits;
var
xdcResponse: TXDataClientResponse;
respObj: TJSObject;
unitCount: Integer;
begin
console.log('GetUnits: Invoking API...');
Utils.ShowSpinner('spinner');
try
try
xdcResponse := await(xdwcUnits.RawInvokeAsync('IApiService.GetUnitList', []));
console.log('RawInvoke returned:', xdcResponse.Result);
respObj := TJSObject(xdcResponse.Result);
xdwdsUnits.Close;
console.log('Units dataset closed');
xdwdsUnits.SetJsonData(respObj['data']);
console.log('JsonData set on units dataset:', respObj['data']);
xdwdsUnits.Open;
console.log('Units dataset opened. Record count:', xdwdsUnits.RecordCount);
unitCount := Integer(respObj['count']);
lblEntries.Caption := Format('%d units', [unitCount]);
console.log('Units label updated:', lblEntries.Caption);
except
on E: EXDataClientRequestException do
begin
console.log('XData exception (units):', E.ErrorResult.ErrorMessage);
Utils.ShowErrorModal(E.ErrorResult.ErrorMessage);
end;
end;
finally
Utils.HideSpinner('spinner');
console.log('GetUnits complete');
end;
end;
end. end.
{
"AuthUrl" : "http://localhost:2009/emimobile/auth/",
"ApiUrl" : "http://localhost:2009/emimobile/api/",
"AppUrl" : "http://localhost:2009/emimobile/app/"
}
\ No newline at end of file
.login-card {
display: inline-block;
width: 300px; /* Adjust width as needed */
padding: 0;
border-radius: 10px;
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
background-color: #fff;
}
.mr-2 {
margin-right: 0.5rem;
}
.table tbody tr:hover {
background-color: #d1e7fd; /* Light blue color for hover effect */
cursor: pointer;
}
.form-input{
display: table;
}
.form-cells{
display: table-cell
}
.table tbody tr {
transition: background-color 0.3s ease;
}
.table {
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
border-radius: 5px;
}
@media (max-width: 1200px) {
.table-responsive {
display: block;
width: 100%;
overflow-x: auto;
-webkit-overflow-scrolling: touch;
}
.table thead {
display: none;
}
.table tbody, .table tr, .table td {
display: block;
width: 100%;
}
.table tr {
margin-bottom: 1rem;
}
.table td {
text-align: right;
padding-left: 50%; /* Adjust padding to accommodate the data-label */
position: relative;
}
.table td::before {
content: attr(data-label);
position: absolute;
left: 0;
width: 50%;
padding-left: 15px; /* Adjust as necessary */
font-weight: bold;
text-align: left;
}
.table td .transcript {
margin-top: 20px; /* Set top margin to 20px */
text-align: left; /* Ensure text alignment is left */
margin-left: 8px;
white-space: normal; /* Prevent text from being cut off */
}
}
.login-navbar {
max-width: 1200px; /* Set the max-width to match a medium screen */
margin: auto;
border-bottom-left-radius: 10px; /* Round the bottom left corner */
border-bottom-right-radius: 10px; /* Round the bottom right corner */
border: 1px solid #d3d3d3;
}
.navbar-toggler {
display: none;
}
.dropdown-menu a {
display: flex; /* Use flexbox for alignment */
align-items: center; /* Vertically center the content */
width: 100%; /* Ensure they take up the full width */
padding: 0.5rem 1rem; /* Add padding to make them clickable */
color: #000; /* Adjust the text color if necessary */
text-decoration: none; /* Remove underlines */
}
.dropdown-menu a:hover {
background-color: #204d74;
color: #fff;
}
.dropdown-menu a span {
flex-grow: 1; /* Make the span take up the remaining space */
}
/* Style for the selected number */
.selected-number .page-link {
background-color: #204d74;
color: #fff !important;
}
/* Style for the unselected numbers and text (previous/next) */
.pagination .page-item a,
.pagination .page-item span {
color: #204d74;
}
.pagination .page-item.active .page-link,
.pagination .page-item.active .page-link:hover,
.pagination .page-item.active .page-link:focus {
background-color: #204d74;
border-color: #204d74;
color: #fff !important;
}
/* This is needed to get rid of the line that was appearing. */
span.card {
border: none;
}
.modal-backdrop {
z-index: 1040 !important;
}
.modal {
z-index: 1055 !important;
}
.list-section-header:empty { display: none; }
.lds-roller {
display: inline-block;
position: relative;
width: 80px;
height: 80px;
}
.lds-roller div {
animation: lds-roller 1.2s cubic-bezier(0.5, 0, 0.5, 1) infinite;
transform-origin: 40px 40px;
}
.lds-roller div:after {
content: " ";
display: block;
position: absolute;
width: 10px;
height: 10px;
border-radius: 50%;
background: var(--bs-primary);
margin: -5px 0 0 -5px;
}
.lds-roller div:nth-child(1) {
animation-delay: -0.036s;
}
.lds-roller div:nth-child(1):after {
top: 63px;
left: 63px;
}
.lds-roller div:nth-child(2) {
animation-delay: -0.072s;
}
.lds-roller div:nth-child(2):after {
top: 68px;
left: 56px;
}
.lds-roller div:nth-child(3) {
animation-delay: -0.108s;
}
.lds-roller div:nth-child(3):after {
top: 71px;
left: 48px;
}
.lds-roller div:nth-child(4) {
animation-delay: -0.144s;
}
.lds-roller div:nth-child(4):after {
top: 72px;
left: 40px;
}
.lds-roller div:nth-child(5) {
animation-delay: -0.18s;
}
.lds-roller div:nth-child(5):after {
top: 71px;
left: 32px;
}
.lds-roller div:nth-child(6) {
animation-delay: -0.216s;
}
.lds-roller div:nth-child(6):after {
top: 68px;
left: 24px;
}
.lds-roller div:nth-child(7) {
animation-delay: -0.252s;
}
.lds-roller div:nth-child(7):after {
top: 63px;
left: 17px;
}
.lds-roller div:nth-child(8) {
animation-delay: -0.288s;
}
.lds-roller div:nth-child(8):after {
top: 56px;
left: 12px;
}
@keyframes lds-roller {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(360deg);
}
}
<html> <!DOCTYPE html>
<head> <html lang="en">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/> <head>
<meta content="width=device-width, initial-scale=1" name="viewport"/> <meta charset="utf-8"/>
<noscript>Your browser does not support JavaScript!</noscript> <meta content="width=device-width, initial-scale=1" name="viewport"/>
<link href="data:;base64,=" rel="icon"/> <noscript>Your browser does not support JavaScript!</noscript>
<title>emiMobile</title> <link href="data:;base64,=" rel="icon"/>
<script crossorigin="anonymous" integrity="sha256-9/aliU8dGd2tb6OSsuzixeV4y/faTqgFtohetphbbj0=" src="https://code.jquery.com/jquery-3.5.1.min.js" type="text/javascript"></script> <title>emiMobile</title>
<link href="https://cdnjs.cloudflare.com/ajax/libs/flag-icon-css/2.3.1/css/flag-icon.min.css" rel="stylesheet"/>
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet"/> <!-- jQuery -->
<link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.0/css/all.min.css" rel="stylesheet"/> <script crossorigin="anonymous" integrity="sha256-9/aliU8dGd2tb6OSsuzixeV4y/faTqgFtohetphbbj0=" src="https://code.jquery.com/jquery-3.5.1.min.js" type="text/javascript"></script>
<link href="css/app.css" rel="stylesheet" type="text/css"/>
<link href="css/spinner.css" rel="stylesheet" type="text/css"/> <!-- Icons & fonts -->
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.7/dist/js/bootstrap.bundle.min.js" type="text/javascript"></script> <link href="https://cdnjs.cloudflare.com/ajax/libs/flag-icon-css/2.3.1/css/flag-icon.min.css" rel="stylesheet"/>
<link crossorigin="anonymous" href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.7/dist/css/bootstrap.min.css" rel="stylesheet"/> <link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet"/>
<script src="https://unpkg.com/leaflet@1.7.1/dist/leaflet.js" type="text/javascript"></script> <link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.0/css/all.min.css" rel="stylesheet"/>
<link href="https://unpkg.com/leaflet@1.7.1/dist/leaflet.css" rel="stylesheet"/>
<script src="$(ProjectName).js" type="text/javascript"></script> <!-- Bootstrap -->
<style> <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.7/dist/js/bootstrap.bundle.min.js" type="text/javascript"></script>
</style> <link crossorigin="anonymous" href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.7/dist/css/bootstrap.min.css" rel="stylesheet"/>
</head>
<body> <!-- Leaflet -->
<script type="text/javascript">rtl.run();</script> <script src="https://unpkg.com/leaflet@1.7.1/dist/leaflet.js" type="text/javascript"></script>
</body> <link href="https://unpkg.com/leaflet@1.7.1/dist/leaflet.css" rel="stylesheet"/>
<!-- App bundle -->
<script src="$(ProjectName).js" type="text/javascript"></script>
<!-- App styles -->
<style></style>
<link href="css/app.css" rel="stylesheet"/>
<link href="css/spinner.css" rel="stylesheet" type="text/css"/>
</head>
<body>
<script type="text/javascript">rtl.run();</script>
</body>
</html> </html>
...@@ -177,6 +177,7 @@ ...@@ -177,6 +177,7 @@
</DCCReference> </DCCReference>
<None Include="index.html"/> <None Include="index.html"/>
<None Include="css\app.css"/> <None Include="css\app.css"/>
<None Include="css\spinner.css"/>
<BuildConfiguration Include="Base"> <BuildConfiguration Include="Base">
<Key>Base</Key> <Key>Base</Key>
</BuildConfiguration> </BuildConfiguration>
...@@ -219,6 +220,12 @@ ...@@ -219,6 +220,12 @@
<Overwrite>true</Overwrite> <Overwrite>true</Overwrite>
</Platform> </Platform>
</DeployFile> </DeployFile>
<DeployFile LocalName="css\spinner.css" Configuration="Debug" Class="ProjectFile">
<Platform Name="Win32">
<RemoteDir>.\</RemoteDir>
<Overwrite>true</Overwrite>
</Platform>
</DeployFile>
<DeployFile LocalName="index.html" Configuration="Debug" Class="ProjectFile"/> <DeployFile LocalName="index.html" Configuration="Debug" Class="ProjectFile"/>
<DeployFile LocalName="index.html" Configuration="Debug" Class="ProjectFile"> <DeployFile LocalName="index.html" Configuration="Debug" Class="ProjectFile">
<Platform Name="Win32"> <Platform Name="Win32">
......
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