|
POST
|
You have a few problems in your code: line 10: after this, you need to check if you found a drop table record, else line 11 could fail with "unexpected null") line 18: continue is used in for loops to jump to the next iteration and skip the rest of the for block for the current iteration. What you want to do is return null, for the same reason as in line 10. line 27: Date() constructs a date from the arguments you give it. I suppose you want Today(), which returns the current date. //returns a percentage of safe fill capacity based on drop rate
var layerID = $feature.tankID
//query the drop rate table for matching tank ID
var dropRateTable = FeatureSetByPortalItem(Portal('https://arcgis.com/'), 'drop rate table portal id');
var filterStatement = "tankID = @layerID"
// must select First record from filtered records, otherwise cannot call values
var tankDropTable = First(filter(dropRateTable, filterStatement))
// no drop rate found? -> return null
if(tankDropTable == null) {
return null
}
var tankDropRate = tankDropTable.dropRate
// get date of last fill from form
var formID = FeatureSetByPortalItem(Portal('https://arcgis.com/'), 'tank fill form portal id', 1, ['*'], false);
var tank = filter(formID, filterStatement)
if (Count(tank) == 0){
return null
}
// Order records by objectid; you can set this to some date field, too
var ordered_tanks = OrderBy(tank, "CreationDate DESC")
var tank = First(ordered_tanks)
var fillDate = tank.CreationDate
// calculate days since last fill
var daysSince = Round(DateDiff(Today(), fillDate, 'days'))
// gallons dropped to date
var gallonsDropped = tankDropRate * daysSince
// percent full of safe fill level
var pctFull = Round((($feature.safeFill - gallonsDropped) / $feature.safeFill) * 100)
return pctFull I don't know if that helps with the error you got, but it's worth a try. Using the FeatureSetBy* functions in visualization and labeling isn't supported (and there are no plans to do so) for performance reasons. Possible solutions: Join table / database view Join the two tables (only the newest record of the fill table) to the tank fc. You should be able to use those values in the visualization profile. Store the attributes in the tank fc I'm guessing the drop rate is fixed, so you can store that as attribute of the tanks. The date when the tank was last filled could be either edited manually by your field workers or with an Attribute Rule on the Survey Form. You can then use these attributes in the visualization profile: var gallonsDropped = DateDiff(Today(), $feature.LastFillDate, "days") * $feature.DropRate
return Round((($feature.safeFill - gallonsDropped) / $feature.safeFill) * 100) Store just the PctFull If you don't want / can't store drop rate and last fill date in the tank fc, you have to store the fill state. In that case, you can't calculate it dynamically with Arcade, but have to do it manually or automatically (like Josh said, schedule a python script that calculates the field to run every few minutes / hour / day).
... View more
02-22-2022
11:10 PM
|
3
|
0
|
2650
|
|
POST
|
Easiest way: if($feature.Purpose == "Stream Crossing-B") {
// bridge code except last line
return DefaultValue(popupString1, "No bridge inspection on record")
} else {
// culvert code except last line
return DefaultValue(popupString1, "No culvert inspection on record")
} Better way: The code for bridges and culverts is the same, only the actual data is different. So you have to abstract the code a little: // Access the inspection table as a FeatureSet
var portal = Portal("https://www.arcgis.com")
var portal_item = "ae306d66da414b7f83f1c7db4284a632"
var layer = IIF($feature.Purpose == "Stream Crossing-B", 2, 1)
var fields = ['Inspection_Date', 'Condition_Overall', 'Inspector_Initials']
var inspection_table = FeatureSetByPortalItem(portal, portal_item, layer, fields)
// Build the filter statement
var GlobalID = $feature.GlobalID
var filterStatement = IIF($feature.Purpose == "Stream Crossing-B", "Bridge", "Culvert") + "_GlobalID = @GlobalID"
// Related features as a variable
var relatedData = Filter(inspection_table, filterStatement)
// Sort related features by newest to oldest
var relatedDataSorted = OrderBy(relatedData, 'Inspection_Date DESC')
// Build the popup string
if(Count(relatedDataSorted) == 0) {
return 'No culvert inspections on record'
}
var f = First(relatedDataSorted);
return DefaultValue(f.Condition_Overall, 'No Condition Recorded') + " " + Text(f.Inspection_Date, 'MM/DD/YYYY') + " by " + DefaultValue(f.Inspector_Initials, 'No Inspector Recorded')
... View more
02-21-2022
12:30 AM
|
0
|
1
|
2719
|
|
POST
|
Hey! Busy week, sorry for ghosting you... Sadly, I can't really help you here. The fields seem to be fine. My only suggestion would be to rebuild the two tables in a test gdb and try it again, mabe there's some interference from other rules (or something else, idk).
... View more
02-20-2022
11:57 PM
|
0
|
12
|
4288
|
|
POST
|
Something like this (untested)? // define list of week day and opening hours
var opening_hours = [
["Sunday", $feature.sunday_open_close, $feature.sunday_open, $feature.sunday_close],
["Monday", "$feature.monday_open_close, $feature.monday_open, $feature.monday_close],
// ...
]
// build string for each week day
var opening_hours_strings = []
for(var i in opening_hours) {
var oh = opening_hours[i]
var oh_string = oh[0] + " - Closed"
if(oh[1] != "closed") {
oh_string = Concatenate([oh[0], oh[2], oh[3]], " - ")
}
Push(opening_hours, oh_string)
}
// Concatenate the week days with line breaks
return Concatenate(opening_hours_strings, TextFormatting.NewLine)
... View more
02-20-2022
11:40 PM
|
1
|
0
|
1466
|
|
POST
|
Ah. In that case: go to the layer's style settings Choose "New Expression" as symbol field edit and use this expression (it will return true or false): var start_date = Today()
var end_date = DateAdd(Today(), 5, "days")
var test_date = $feature.DateField
return test_date >= start_date && test_date <= end_date Choose "Distinct Values" as styling option Style the symbols for true and false You can also hide the false features by setting the transparency to 100%. Before: After applying the Arcade expression: After hiding the false features: Note that this approach will probably be slower than just filtering out the undesired features from the layer (see HuubZwart's answer).
... View more
02-14-2022
01:00 AM
|
0
|
1
|
4148
|
|
POST
|
var start_date = Text(Today(), "Y-MM-DD") // Today: 2022-02-11
var end_date = Text(DateAdd(Today(), 5, "days"), "Y-MM-DD") // Today +5 days: 2022-02-16
var fs = FeatureSetBy*(...)
var future_records = Filter(fs, "DateField BETWEEN @start_date and @end_date")
... View more
02-11-2022
04:18 AM
|
0
|
3
|
4184
|
|
POST
|
It's because of this line: results +=line What your code does is: go through ALL related work records and concatenate their New_MeterIDs. You need some way to check only the LATEST work record. You shouldn't need the filter, as the FeatureSetByRelationshipName function returns only the related work records. Note that, while this is absolutely a legit way of copying the new Meter_ID to the feature class, this won't happen automatically. You have to update the WaterMeter after you added a new WaterMeterWorkHistory record.
... View more
02-11-2022
03:23 AM
|
1
|
0
|
4346
|
|
POST
|
The first error comes from me not testing the rule. When no relates asset is found, the rule should just return, not return null. Second error: no idea. I built a rudimentary structure: Feature class: Table: Relationship class: Attribute rule on the work table: // Calculation Attribute Rule on WaterMeterWorkHistory
// Triggers: Insert
// Exclude from application evaluation
// Copies old values from water meter t
// get the water meter
var water_meter = First(FeatureSetByRelationshipName($feature, "WaterMeterTOWorkHistory"))
if(water_meter == null) { return }
// get attributes from water_meter
var old_attributes = {
"Old_MeterID": water_meter.Meter_ID,
"Old_Brand": water_meter.Brand,
"Old_Reading": water_meter.Latest_Reading,
}
// map the attribute names from the work table to the feature class
var update_attribute_map = [
["New_MeterID", "Meter_ID"],
["New_Brand", "Brand"],
["New_Reading", "Latest_Reading"],
]
// if the new attributes are filled in, add them to the edit request
var updated_attributes = Dictionary()
for(var i in update_attribute_map) {
var work_att = update_attribute_map[i][0]
var asset_att = update_attribute_map[i][1]
var new_att = $feature[work_att]
var old_att = water_meter[asset_att]
if(!IsEmpty(new_att)) {
updated_attributes[asset_att] = new_att
}
}
var edit = [{"className": "WaterMeter", "updates": [{"globalID": water_meter.GlobalID, "attributes": updated_attributes}]}]
// return
return {
"result": {"attributes": old_attributes}, // copy old attributes from water meter to work table
"edit": edit // copy new attributes from work table to water meter
} WaterMeter: WaterMeterWorkHistory: WaterMeter after these changes:
... View more
02-11-2022
03:18 AM
|
1
|
14
|
4345
|
|
POST
|
You're not returning anything from the expression. Try adding this as the last line: return result
... View more
02-10-2022
02:25 AM
|
3
|
0
|
1476
|
|
POST
|
The tool you're looking for is Select Layer By Location. You can open it from the Geoprocessing Pane (Data Management -> Layers and Table Views) or from the Map Ribbon: Parameters: Input features: polygons Selecting features: points Relationship: Intersect If nothing is found, try using a small Search Distance.
... View more
02-10-2022
02:20 AM
|
2
|
1
|
5643
|
|
POST
|
Oh yeah, "Exclude from application evaluation" has to be checked for rules that affect other tables. Try inserting a record in Pro before publishing, that will give better error messages.
... View more
02-08-2022
10:40 PM
|
2
|
1
|
6401
|
|
POST
|
OK, then the rule should trigger on Insert. // Attribute Rule on the work history table
// Triggers: Insert
// Field: empty
// get the water meter
var water_meter = First(FeatureSetByRelationshipName($feature, "test.DBO.WaterMeterTOWorkHistory_TEST"))
if(water_meter == null) { return null }
// construct the edit parameter, only fill it if meter got replaced
var edit = []
if($feature.New_MeterID != water_meter.MeterID) {
Push(edit, {
"className": "test.DBO.WaterMeterTEST"
"updates": [{"globalID": water_meter.GlobalID, "attributes": {"MeterID": $feature.MeterID}}]
})
}
// return
return {
"result": {
"attributes": {
"Old_MeterID": water_meter.MeterID,
// you can also copy the other fields here:
// "Brand": water_meter.Brand,
// "LatestReading": water_meter.LatestReading,
}
},
"edit": edit
}
... View more
02-08-2022
06:29 AM
|
1
|
4
|
6439
|
|
POST
|
What's your workflow here? Do you insert the work history record with Old_MeterID and New_MeterID or do you change New_MeterID after the record is already inserted?
... View more
02-08-2022
06:02 AM
|
0
|
6
|
6449
|
|
IDEA
|
Just had a look at the Arcade profiles again. The calculation profile doesn't allow $map either, so my approach wouldn't work, anyway...
... View more
02-08-2022
05:58 AM
|
0
|
0
|
3394
|
|
IDEA
|
@KoryKramer Yes, absolutely. I do this in my database. But that only works when data inside your database changes. In Anna's use case, you would define an Update Attribute Rule on the LIHTC feature class that runs her code and updates the intersecting features. If the data is outside of your database, this isn't possible (?). Imagine you are using census or parcel data. You don't author this data, you just use it in your map. It's not part of your database. You can only read it. You could copy this data into your database and define the appropriate Attribute Rules. When the authority changes the data, you update your tables accordingly. That seems cumbersome and error prone, and you lose the advantage of directly using the authorative data. In a case like this, I'd argue it's much simpler to just create a field in your table and recalculate it regularily or when you know the determining data changed. Or, and this is the core of this idea, make the whole process dynamic by allowing the $map (and $datastore) global in the visulisation (and labeling) profile.
... View more
02-08-2022
05:55 AM
|
0
|
0
|
3396
|
| Title | Kudos | Posted |
|---|---|---|
| 1 | 01-30-2023 09:57 AM | |
| 1 | 05-18-2023 12:51 AM | |
| 1 | 03-05-2023 12:46 PM | |
| 1 | 12-07-2022 07:01 AM | |
| 1 | 06-21-2022 08:27 AM |
| Online Status |
Offline
|
| Date Last Visited |
02-03-2024
06:14 PM
|