Correctly handle different rollup value types.

This commit is contained in:
Jonathan Bernard 2022-04-18 21:02:00 -05:00
parent 7c879a0fca
commit d9cddc4371
3 changed files with 41 additions and 16 deletions

View File

@ -1,6 +1,6 @@
# Package # Package
version = "0.4.1" version = "0.4.2"
author = "Jonathan Bernard" author = "Jonathan Bernard"
description = "Utilities and bindings for HFF's Notion API." description = "Utilities and bindings for HFF's Notion API."
license = "GPL-3.0-or-later" license = "GPL-3.0-or-later"
@ -12,3 +12,4 @@ srcDir = "src"
requires "nim >= 1.4.8" requires "nim >= 1.4.8"
requires "https://git.jdb-software.com/jdb/buffoonery" requires "https://git.jdb-software.com/jdb/buffoonery"
requires "https://git.jdb-software.com/jdb/nim-time-utils.git >= 0.5.0" requires "https://git.jdb-software.com/jdb/nim-time-utils.git >= 0.5.0"
requires "https://git.jdb-software.com/jdb/nim-namespaced-logging"

View File

@ -21,7 +21,8 @@ type
name*: string name*: string
headsOfHousehold*: seq[string] headsOfHousehold*: seq[string]
headOfHouseholdIds*: seq[string] headOfHouseholdIds*: seq[string]
primaryAddressId*: seq[string] primaryAddress*: string
primaryAddressId*: string
members*: seq[string] members*: seq[string]
memberIds*: seq[string] memberIds*: seq[string]
createdAt*: Option[DateTime] createdAt*: Option[DateTime]
@ -84,8 +85,8 @@ func sameContents[T](a: seq[T], b: seq[T]): bool =
func `==`*(a, b: Family): bool = func `==`*(a, b: Family): bool =
return a.name == b.name and return a.name == b.name and
sameContents(a.headOfHouseholdIds, b.headOfHouseholdIds) and sameContents(a.headOfHouseholdIds, b.headOfHouseholdIds) and
sameContents(a.primaryAddressId, b.primaryAddressId) and sameContents(a.memberIds, b.memberIds) and
sameContents(a.memberIds, b.memberIds) a.primaryAddressId == b.primaryAddressId
func `==`*(a, b: Person): bool = func `==`*(a, b: Person): bool =
return a.preferredName == b.preferredName and return a.preferredName == b.preferredName and
@ -135,7 +136,7 @@ func toPage*(f: Family): JsonNode =
"properties": { "properties": {
"Name": makeTextProp("title", f.name), "Name": makeTextProp("title", f.name),
"Head(s) of Household": makeRelationProp(f.headOfHouseholdIds), "Head(s) of Household": makeRelationProp(f.headOfHouseholdIds),
"Primary Address": makeRelationProp(f.primaryAddressId), "Primary Address": makeRelationProp(@[f.primaryAddressId]),
"Members": makeRelationProp(f.memberIds) "Members": makeRelationProp(f.memberIds)
} }
} }
@ -186,13 +187,17 @@ proc addressFromPage*(page: JsonNode): Address =
lastUpdatedAt: some(parseIso8601(page["last_edited_time"].getStr))) lastUpdatedAt: some(parseIso8601(page["last_edited_time"].getStr)))
proc familyFromPage*(page: JsonNode): Family = proc familyFromPage*(page: JsonNode): Family =
let primaryAddressIds = page.getRelationIds("Primary Address")
result = Family( result = Family(
id: page["id"].getStr, id: page["id"].getStr,
name: page.getTitle("Name"), name: page.getTitle("Name"),
headsOfHousehold: page.getRolledupDisplayValues("Head(s) of Household (display)"), headsOfHousehold: page.getRolledupRecordTitles("Head(s) of Household (display)"),
headOfHouseholdIds: page.getRelationIds("Head(s) of Household"), headOfHouseholdIds: page.getRelationIds("Head(s) of Household"),
primaryAddressId: page.getRelationIds("Primary Address"), primaryAddress: if primaryAddressIds.len == 0: ""
members: page.getRolledupDisplayValues("Members (display)"), else: page.getRolledupRecordTitles("Primary Address (display)")[0],
primaryAddressId: if primaryAddressIds.len == 0: ""
else: primaryAddressIds[0],
members: page.getRolledupRecordTitles("Members (display)"),
memberIds: page.getRelationIds("Members"), memberIds: page.getRelationIds("Members"),
createdAt: some(parseIso8601(page["created_time"].getStr)), createdAt: some(parseIso8601(page["created_time"].getStr)),
lastUpdatedAt: some(parseIso8601(page["last_edited_time"].getStr))) lastUpdatedAt: some(parseIso8601(page["last_edited_time"].getStr)))
@ -211,16 +216,16 @@ proc personFromPage*(page: JsonNode): Person =
primaryPhoneNumber: page.getPhone("Primary Phone Number"), primaryPhoneNumber: page.getPhone("Primary Phone Number"),
primaryEmailAddress: page.getEmail("Email Address"), primaryEmailAddress: page.getEmail("Email Address"),
relationshipToHff: page.getMultiSelect("Relationship to HFF"), relationshipToHff: page.getMultiSelect("Relationship to HFF"),
addresses: page.getRolledupDisplayValues("Full Address"), addresses: page.getRollupArrayValues("Full Address").mapIt(it{"formula", "string"}.getStr),
addressIds: page.getRelationIds("Address"), addressIds: page.getRelationIds("Address"),
marriedTo: if marriedToIds.len == 0: "" marriedTo: if marriedToIds.len == 0: ""
else: page.getRolledupDisplayValues("Married To (display)")[0], else: page.getRolledupRecordTitles("Married To (display)")[0],
marriedToId: if marriedToIds.len == 0: "" marriedToId: if marriedToIds.len == 0: ""
else: marriedToIds[0], else: marriedToIds[0],
anniversary: page.getDateTime("Anniversary"), anniversary: page.getDateTime("Anniversary"),
parents: page.getRolledupDisplayValues("Parents (display)"), parents: page.getRolledupRecordTitles("Parents (display)"),
parentIds: page.getRelationIds("Parents"), parentIds: page.getRelationIds("Parents"),
children: page.getRolledupDisplayValues("Children (display)"), children: page.getRolledupRecordTitles("Children (display)"),
childIds: page.getRelationIds("Children"), childIds: page.getRelationIds("Children"),
createdAt: some(parseIso8601(page["created_time"].getStr)), createdAt: some(parseIso8601(page["created_time"].getStr)),
lastUpdatedAt: some(parseIso8601(page["last_edited_time"].getStr)), lastUpdatedAt: some(parseIso8601(page["last_edited_time"].getStr)),

View File

@ -1,9 +1,16 @@
import std/json, std/options, std/sequtils, std/times import std/json, std/logging, std/options, std/sequtils, std/times
import namespaced_logging
import timeutils import timeutils
const NOTION_MAX_PAGE_SIZE* = 100 const NOTION_MAX_PAGE_SIZE* = 100
const NOTION_DATE_FORMAT = "YYYY-MM-dd" const NOTION_DATE_FORMAT = "YYYY-MM-dd"
var logNs {.threadvar.}: LoggingNamespace
template log(): untyped =
if logNs.isNil: logNs = initLoggingNamespace("hff_notion_api_client/utils", lvlInfo)
logNs
proc parseDate(str: string): DateTime = proc parseDate(str: string): DateTime =
try: result = parseIso8601(str) try: result = parseIso8601(str)
except: result = times.parse(str, NOTION_DATE_FORMAT) except: result = times.parse(str, NOTION_DATE_FORMAT)
@ -74,9 +81,21 @@ proc getRelationIds*(page: JsonNode, propName: string): seq[string] =
let propNode = page.getPropNode("relation", propName) let propNode = page.getPropNode("relation", propName)
return propNode.getElems.mapIt(it["id"].getStr) return propNode.getElems.mapIt(it["id"].getStr)
proc getRolledupDisplayValues*(page: JsonNode, propName: string): seq[string] = proc getRollupArrayValues*(page: JsonNode, propName: string): seq[JsonNode] =
let propNode = page.getPropNode("rollup", propName) return page.getPropNode("rollup", propName){"array"}.getElems(@[])
return propNode.getElems.mapIt(it{"formula", "string"}.getStr)
proc getRolledupRecordTitles*(page: JsonNode, propName: string): seq[string] =
let rollups = page.getPropNode("rollup", propName)["array"]
if rollups.getElems.len == 0: return @[]
elif rollups.getElems.len != 1 or not rollups.getElems[0].hasKey("title"):
log().debug "Expected exactly one item of type 'title'. Received: \n" & rollups.pretty
raise newException(
ValueError,
"unexpected format of rollup value for '" & propName & "' property")
let titleElems = rollups.getElems[0]["title"]
return titleElems.getElems.mapIt(it["plain_text"].getStr)
proc getText*(page: JsonNode, propName: string): string = proc getText*(page: JsonNode, propName: string): string =
let propNode = page.getPropNode("rich_text", propName) let propNode = page.getPropNode("rich_text", propName)