Commit 6ff4c10a by Mac Stephens

update complaint and unit markers

parent 2607279b
......@@ -13,6 +13,7 @@ object ApiDatabaseModule: TApiDatabaseModule
'ER::text) AS UNITNAME,'
' ag.AGENCYID AS AGENCY,'
' ag.AGENCYNAME AS AGENCY_NAME,'
' ag.AGENCYTYPE AS AGENCYTYPE,'
' uc.GPS_LATITUDE,'
' uc.GPS_LONGITUDE,'
' cdc.CODE_DESC AS CALL_TYPE,'
......@@ -126,6 +127,11 @@ object ApiDatabaseModule: TApiDatabaseModule
ReadOnly = True
Size = 10
end
object uqMapUnitsagencytype: TStringField
FieldName = 'agencytype'
ReadOnly = True
Size = 10
end
end
object uqUnitList: TUniQuery
Connection = ucENTCAD
......@@ -826,6 +832,8 @@ object ApiDatabaseModule: TApiDatabaseModule
' ca.AGENCY AS AGENCY,'
' ag.AGENCYNAME AS AGENCY_NAME,'
' ca.PRIORITY AS PRIORITY,'
' ct.DATEDISPATCHED AS DATEDISPATCHED,'
' ct.DATEARRIVED AS DATEARRIVED,'
' ca.BUSINESS,'
' cdc.CATEGORY AS DISPATCHCODECATEGORY,'
''
......@@ -904,16 +912,6 @@ object ApiDatabaseModule: TApiDatabaseModule
FieldName = 'address'
Size = 64
end
object uqMapComplaintspriorityKey: TStringField
FieldKind = fkCalculated
FieldName = 'priorityKey'
Calculated = True
end
object uqMapComplaintspngName: TStringField
FieldKind = fkCalculated
FieldName = 'pngName'
Calculated = True
end
object uqMapComplaintsagency: TStringField
FieldName = 'agency'
Size = 6
......@@ -923,6 +921,32 @@ object ApiDatabaseModule: TApiDatabaseModule
ReadOnly = True
Size = 40
end
object uqMapComplaintsdatedispatched: TDateTimeField
FieldName = 'datedispatched'
ReadOnly = True
end
object uqMapComplaintsdatearrived: TDateTimeField
FieldName = 'datearrived'
ReadOnly = True
end
object uqMapComplaintspriorityBadge: TStringField
FieldKind = fkCalculated
FieldName = 'priorityBadge'
Size = 80
Calculated = True
end
object uqMapComplaintscomplaintStatusKey: TStringField
FieldKind = fkCalculated
FieldName = 'complaintStatusKey'
Size = 80
Calculated = True
end
object uqMapComplaintspngName: TStringField
FieldKind = fkCalculated
FieldName = 'pngName'
Size = 80
Calculated = True
end
end
object uqBadgeCounts: TUniQuery
Connection = ucENTCAD
......
......@@ -142,8 +142,6 @@ type
uqMapComplaintslat: TFloatField;
uqMapComplaintsdispatch_code_desc: TStringField;
uqMapComplaintsaddress: TStringField;
uqMapComplaintspriorityKey: TStringField;
uqMapComplaintspngName: TStringField;
uqComplaintUnitscomplaintid: TFloatField;
uqComplaintUnitsunitid: TFloatField;
uqComplaintUnitsunitname: TStringField;
......@@ -197,13 +195,18 @@ type
uqMapUnitsofficer2_empnum: TStringField;
uqMapComplaintsagency: TStringField;
uqMapComplaintsagency_name: TStringField;
uqMapComplaintsdatedispatched: TDateTimeField;
uqMapComplaintsdatearrived: TDateTimeField;
uqMapComplaintspriorityBadge: TStringField;
uqMapComplaintscomplaintStatusKey: TStringField;
uqMapComplaintspngName: TStringField;
uqMapUnitsagencytype: TStringField;
procedure uqComplaintListCalcFields(DataSet: TDataSet);
procedure uqMapComplaintsCalcFields(DataSet: TDataSet);
procedure DataModuleCreate(Sender: TObject);
private
{ Private declarations }
public
function DerivePriorityKeyFromPriorityString(const priorityString: string): string;
function HandleUniqueFilenames(const category: string): string;
function BadgeCounts(const BaseQuery: TUniQuery): Integer;
end;
......@@ -254,21 +257,32 @@ procedure TApiDatabaseModule.uqMapComplaintsCalcFields(DataSet: TDataSet);
var
rawCategory: string;
rawPriority: string;
derivedPriorityKey: string;
computedPngName: string;
statusKey: string;
priorityBadge: string;
begin
rawCategory := DataSet.FieldByName('DISPATCHCODECATEGORY').AsString;
rawPriority := DataSet.FieldByName('PRIORITY').AsString;
rawPriority := Trim(DataSet.FieldByName('PRIORITY').AsString);
derivedPriorityKey := DerivePriorityKeyFromPriorityString(rawPriority);
DataSet.FieldByName('priorityKey').AsString := derivedPriorityKey;
if not DataSet.FieldByName('DATEARRIVED').IsNull then
statusKey := 'onscene'
else if not DataSet.FieldByName('DATEDISPATCHED').IsNull then
statusKey := 'attached'
else
statusKey := 'notattached';
if Trim(rawCategory) = '' then
computedPngName := Format('default_%s.png', [derivedPriorityKey])
if rawPriority = '' then
priorityBadge := '?'
else
computedPngName := Format('%s_%s.png', [HandleUniqueFilenames(rawCategory), derivedPriorityKey]);
priorityBadge := UpperCase(Copy(rawPriority, 1, 1));
DataSet.FieldByName('pngName').AsString := computedPngName;
DataSet.FieldByName('complaintStatusKey').AsString := statusKey;
DataSet.FieldByName('priorityBadge').AsString := priorityBadge;
if Trim(rawCategory) = '' then
DataSet.FieldByName('pngName').AsString := Format('default_%s.png', [statusKey])
else
DataSet.FieldByName('pngName').AsString :=
Format('%s_%s.png', [HandleUniqueFilenames(rawCategory), statusKey]);
end;
function TApiDatabaseModule.HandleUniqueFilenames(const category: string): string;
......@@ -291,22 +305,6 @@ begin
end;
function TApiDatabaseModule.DerivePriorityKeyFromPriorityString(const priorityString: string): string;
var
firstChar: Char;
begin
if priorityString <> '' then
begin
firstChar := priorityString[1]; // handles "3J", "3P", etc.
if (firstChar >= '1') and (firstChar <= '4') then
Exit(string(firstChar));
if (firstChar >= '5') and (firstChar <= '9') then
Exit('5-9');
end;
Result := '5-9';
end;
function TApiDatabaseModule.BadgeCounts(const BaseQuery: TUniQuery): Integer;
var
Q: TUniQuery;
......
......@@ -159,8 +159,9 @@ begin
item.AddPair('DispatchCodeDesc',ApiDB.uqMapComplaintsDISPATCH_CODE_DESC.AsString);
item.AddPair('DispatchCodeCategory',ApiDB.uqMapComplaintsDISPATCHCODECATEGORY.AsString);
item.AddPair('Priority',ApiDB.uqMapComplaintsPRIORITY.AsString);
item.AddPair('priorityKey',ApiDB.uqMapComplaintspriorityKey.AsString);
item.AddPair('pngName',ApiDB.uqMapComplaintspngName.AsString);
item.AddPair('PriorityBadge', ApiDB.uqMapComplaintspriorityBadge.AsString);
item.AddPair('ComplaintStatusKey', ApiDB.uqMapComplaintscomplaintStatusKey.AsString);
item.AddPair('pngName', ApiDB.uqMapComplaintspngName.AsString);
item.AddPair('Address',ApiDB.uqMapComplaintsADDRESS.AsString);
item.AddPair('Business',ApiDB.uqMapComplaintsBUSINESS.AsString);
......@@ -230,6 +231,7 @@ begin
item.AddPair('UnitBadge', ApiDB.uqMapUnitsUNITNAME.AsString);
item.AddPair('Agency', ApiDB.uqMapUnitsAGENCY.AsString);
item.AddPair('AgencyName', ApiDB.uqMapUnitsAGENCY_NAME.AsString);
item.AddPair('AgencyType', ApiDB.uqMapUnitsAGENCYTYPE.AsString);
item.AddPair('Lat', TJSONNumber.Create(ApiDB.uqMapUnitsGPS_LATITUDE.AsFloat));
item.AddPair('Lng', TJSONNumber.Create(ApiDB.uqMapUnitsGPS_LONGITUDE.AsFloat));
......
[Settings]
LogFileNum=706
LogFileNum=712
webClientVersion=0.1.0
[Database]
......
......@@ -273,9 +273,9 @@ var
i, ui: Integer;
m: TTMSFNCMapsMarker;
lat, lng: Double;
uName, unitBadge, agencyId, agencyName, agency: string;
uName, unitBadge, agencyType, agencyId, agencyName, agency: string;
unitId, callType, priorityText, statusText: string;
complaintId, codeDesc, priority, business, address: string;
complaintId, codeDesc, priority, priorityBadge, complaintStatusKey, business, address: string;
pngName, iconUrl, rowsHtml: string;
officer1Lname, officer1Fname, officer1Empnum: string;
officer2Lname, officer2Fname, officer2Empnum: string;
......@@ -358,6 +358,17 @@ begin
if Trim(agency) = '' then
agency := agencyId;
agencyType := UpperCase(Trim(GetJsonString(item, 'AgencyType')));
if agencyType = 'FIR' then
iconUrl := 'assets/markers/car_fire.png'
else if agencyType = 'EMS' then
iconUrl := 'assets/markers/car_ems.png'
else if agencyType = 'POL' then
iconUrl := 'assets/markers/car_police.png'
else
iconUrl := 'assets/markers/car_police.png';
callType := GetJsonString(item, 'CallType');
priorityText := GetJsonString(item, 'Priority');
statusText := GetJsonString(item, 'Status');
......@@ -454,7 +465,7 @@ begin
'</div>';
m.DataString := 'unit|' + unitId + '|' + StringReplace(unitBadge, '|', '/', [rfReplaceAll]);
m.IconURL := CarIconForAgency(agencyId);
m.IconURL := iconUrl;
end;
end;
......@@ -476,6 +487,15 @@ begin
agency := agencyId;
priority := GetJsonString(item, 'Priority');
priorityBadge := GetJsonString(item, 'PriorityBadge');
if Trim(priorityBadge) = '' then
priorityBadge := '?';
complaintStatusKey := LowerCase(Trim(GetJsonString(item, 'ComplaintStatusKey')));
if complaintStatusKey = '' then
complaintStatusKey := 'notattached';
business := GetJsonString(item, 'Business');
address := GetJsonString(item, 'Address');
......@@ -489,7 +509,7 @@ begin
if Trim(pngName) <> '' then
iconUrl := 'assets/markers/' + pngName
else
iconUrl := 'assets/markers/default_5-9.png';
iconUrl := 'assets/markers/default_notattached.png';
rowsHtml := '';
units := TJSArray(item['Units']);
......@@ -519,8 +539,13 @@ begin
m.IconURL := iconUrl;
m.Title :=
'<span class="emi-marker-meta" data-marker-type="complaint" data-priority-badge="' +
HtmlAttrEncode(priorityBadge) +
'" data-complaint-status="' +
HtmlAttrEncode(complaintStatusKey) +
'" style="display:none"></span>' +
'<div class="d-flex flex-column gap-1 px-1 py-1" style="width:260px;">' +
'<div class="fw-semibold small">' +
'<div class="fw-semibold small">' +
'<span class="fw-bold">Complaint:</span> ' + complaintId +
'</div>' +
'<div class="small">' +
......@@ -602,49 +627,45 @@ begin
'var markerType = "";' + #13#10 +
'var unitBadgeText = "";' + #13#10 +
'var complaintBadgeText = "";' + #13#10 +
'var complaintStatus = "";' + #13#10 +
'try {' + #13#10 +
' var temp = document.createElement("div");' + #13#10 +
' temp.innerHTML = t;' + #13#10 +
' var meta = temp.querySelector(".emi-marker-meta");' + #13#10 +
' if (meta) {' + #13#10 +
' complaintBadgeText = meta.getAttribute("data-priority-badge") || "";' + #13#10 +
' markerType = meta.getAttribute("data-marker-type") || "";' + #13#10 +
' unitBadgeText = meta.getAttribute("data-unit-badge") || "";' + #13#10 +
' complaintStatus = meta.getAttribute("data-complaint-status") || "";' + #13#10 +
' }' + #13#10 +
'} catch(e) {}' + #13#10 +
'var isUnit = markerType === "unit";' + #13#10 +
'var isComplaint = markerType === "complaint";' + #13#10 +
'var unitBadgeColor = "#2563EB";' + #13#10 +
'if (u && u.indexOf("car_fire") >= 0) unitBadgeColor = "#DC2626";' + #13#10 +
'else if (u && u.indexOf("car_ems") >= 0) unitBadgeColor = "#16A34A";' + #13#10 +
'else if (u && u.indexOf("car_police") >= 0) unitBadgeColor = "#2563EB";' + #13#10 +
'var complaintBadgeColor = "#FF8080";' + #13#10 +
'var complaintBadgeTextColor = "#FFFFFF";' + #13#10 +
'if (complaintStatus === "onscene") {' + #13#10 +
' complaintBadgeColor = "#22C55E";' + #13#10 +
' complaintBadgeTextColor = "#FFFFFF";' + #13#10 +
'} else if (complaintStatus === "attached") {' + #13#10 +
' complaintBadgeColor = "#FFFF00";' + #13#10 +
' complaintBadgeTextColor = "#111827";' + #13#10 +
'}' + #13#10 +
'try { if (m.unbindTooltip) m.unbindTooltip(); } catch(e) {}' + #13#10 +
'try { if (m.unbindPopup) m.unbindPopup(); } catch(e) {}' + #13#10 +
'var badgeText = "";' + #13#10 +
'if (!isUnit && u) {' + #13#10 +
' try {' + #13#10 +
' var file = u.split("/").pop();' + #13#10 +
' var base = file.replace(/\.[^/.]+$/, "");' + #13#10 +
' var idx = base.lastIndexOf("_");' + #13#10 +
' if (idx >= 0 && idx < base.length - 1) {' + #13#10 +
' var suffix = base.substring(idx + 1);' + #13#10 +
' if (suffix && suffix.length > 0) {' + #13#10 +
' var ch = suffix.charAt(0);' + #13#10 +
' if (ch >= "1" && ch <= "9") badgeText = ch;' + #13#10 +
' }' + #13#10 +
' }' + #13#10 +
' } catch(e) {}' + #13#10 +
'}' + #13#10 +
'var badgeColor = "#4b5563";' + #13#10 +
'if (badgeText === "1") badgeColor = "#bc28d9";' + #13#10 +
'else if (badgeText === "2") badgeColor = "#b91c1c";' + #13#10 +
'else if (badgeText === "3") badgeColor = "#b45309";' + #13#10 +
'else if (badgeText === "4") badgeColor = "#047857";' + #13#10 +
'if (u) {' + #13#10 +
' var wrapClass = isUnit ? "emi-marker-wrap emi-marker-wrap-unit" : "emi-marker-wrap";' + #13#10 +
' var wrapClass = isUnit ? "emi-marker-wrap emi-marker-wrap-unit" : (isComplaint ? "emi-marker-wrap emi-marker-wrap-complaint" : "emi-marker-wrap");' + #13#10 +
' var html = ''<div class="'' + wrapClass + ''"><img src="'' + u + ''" class="emi-marker-img">'';' + #13#10 +
' if (isUnit && unitBadgeText) {' + #13#10 +
' html += ''<div class="emi-unit-badge">'' + unitBadgeText + ''</div>'';' + #13#10 +
' } else if (badgeText) {' + #13#10 +
' html += ''<div class="emi-marker-badge" style="background:'' + badgeColor + '';">'' + badgeText + ''</div>'';' + #13#10 +
' html += ''<div class="emi-unit-badge" style="background:'' + unitBadgeColor + '';">'' + unitBadgeText + ''</div>'';' + #13#10 +
' } else if (isComplaint && complaintBadgeText) {' + #13#10 +
' html += ''<div class="emi-complaint-badge" style="background:'' + complaintBadgeColor + '';color:'' + complaintBadgeTextColor + '';">'' + complaintBadgeText + ''</div>'';' + #13#10 +
' }' + #13#10 +
' html += ''</div>'';' + #13#10 +
' m.setIcon(L.divIcon({' + #13#10 +
......@@ -701,10 +722,12 @@ begin
'vertical-align:middle;' +
'}' + #13#10 +
// --- Marker Badge ------------------------------------------------------------
'.emi-marker-wrap{position:relative;display:inline-block;}'+#13#10+
'.emi-marker-wrap{position:relative;display:inline-block;}'+#13#10+
'.emi-marker-wrap-unit{padding-top:13px;}'+#13#10+
'.emi-marker-img{display:block;}'+#13#10+
'.emi-marker-badge{position:absolute;top:-4px;right:-4px;min-width:16px;height:16px;padding:0 4px;border-radius:999px;background:var(--bs-danger);color:#fff;font:700 11px/16px system-ui,-apple-system,"Segoe UI",Roboto,sans-serif;text-align:center;box-shadow:0 0 0 2px #fff;}'+#13#10+
'.emi-marker-wrap-complaint{padding-top:0;}'+#13#10+
'.emi-complaint-badge{position:absolute;top:-4px;right:-4px;min-width:16px;height:16px;padding:0 4px;border-radius:999px;color:#111827;font:700 11px/16px system-ui,-apple-system,"Segoe UI",Roboto,sans-serif;text-align:center;box-shadow:0 0 0 2px #fff;}'+#13#10+
'.emi-unit-badge{position:absolute;top:0;left:50%;transform:translateX(-50%);min-width:34px;max-width:58px;height:15px;padding:0 5px;border-radius:4px;background:#111827;color:#fff;font:700 10px/15px system-ui,-apple-system,"Segoe UI",Roboto,sans-serif;text-align:center;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;box-shadow:0 0 0 2px #fff;z-index:2;}'+#13#10;
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