From d9cddc43715da4106a66072f3afd3f8e3b4d8670 Mon Sep 17 00:00:00 2001 From: Jonathan Bernard Date: Mon, 18 Apr 2022 21:02:00 -0500 Subject: [PATCH] Correctly handle different rollup value types. --- hff_notion_api_client.nimble | 3 ++- src/hff_notion_api_client/models.nim | 27 ++++++++++++++++----------- src/hff_notion_api_client/utils.nim | 27 +++++++++++++++++++++++---- 3 files changed, 41 insertions(+), 16 deletions(-) diff --git a/hff_notion_api_client.nimble b/hff_notion_api_client.nimble index 8698d58..b02658f 100644 --- a/hff_notion_api_client.nimble +++ b/hff_notion_api_client.nimble @@ -1,6 +1,6 @@ # Package -version = "0.4.1" +version = "0.4.2" author = "Jonathan Bernard" description = "Utilities and bindings for HFF's Notion API." license = "GPL-3.0-or-later" @@ -12,3 +12,4 @@ srcDir = "src" requires "nim >= 1.4.8" 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-namespaced-logging" diff --git a/src/hff_notion_api_client/models.nim b/src/hff_notion_api_client/models.nim index 7437f5a..1c5e8f7 100644 --- a/src/hff_notion_api_client/models.nim +++ b/src/hff_notion_api_client/models.nim @@ -21,7 +21,8 @@ type name*: string headsOfHousehold*: seq[string] headOfHouseholdIds*: seq[string] - primaryAddressId*: seq[string] + primaryAddress*: string + primaryAddressId*: string members*: seq[string] memberIds*: seq[string] createdAt*: Option[DateTime] @@ -84,8 +85,8 @@ func sameContents[T](a: seq[T], b: seq[T]): bool = func `==`*(a, b: Family): bool = return a.name == b.name and sameContents(a.headOfHouseholdIds, b.headOfHouseholdIds) and - sameContents(a.primaryAddressId, b.primaryAddressId) and - sameContents(a.memberIds, b.memberIds) + sameContents(a.memberIds, b.memberIds) and + a.primaryAddressId == b.primaryAddressId func `==`*(a, b: Person): bool = return a.preferredName == b.preferredName and @@ -135,7 +136,7 @@ func toPage*(f: Family): JsonNode = "properties": { "Name": makeTextProp("title", f.name), "Head(s) of Household": makeRelationProp(f.headOfHouseholdIds), - "Primary Address": makeRelationProp(f.primaryAddressId), + "Primary Address": makeRelationProp(@[f.primaryAddressId]), "Members": makeRelationProp(f.memberIds) } } @@ -186,13 +187,17 @@ proc addressFromPage*(page: JsonNode): Address = lastUpdatedAt: some(parseIso8601(page["last_edited_time"].getStr))) proc familyFromPage*(page: JsonNode): Family = + let primaryAddressIds = page.getRelationIds("Primary Address") result = Family( id: page["id"].getStr, 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"), - primaryAddressId: page.getRelationIds("Primary Address"), - members: page.getRolledupDisplayValues("Members (display)"), + primaryAddress: if primaryAddressIds.len == 0: "" + else: page.getRolledupRecordTitles("Primary Address (display)")[0], + primaryAddressId: if primaryAddressIds.len == 0: "" + else: primaryAddressIds[0], + members: page.getRolledupRecordTitles("Members (display)"), memberIds: page.getRelationIds("Members"), createdAt: some(parseIso8601(page["created_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"), primaryEmailAddress: page.getEmail("Email Address"), 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"), marriedTo: if marriedToIds.len == 0: "" - else: page.getRolledupDisplayValues("Married To (display)")[0], + else: page.getRolledupRecordTitles("Married To (display)")[0], marriedToId: if marriedToIds.len == 0: "" else: marriedToIds[0], anniversary: page.getDateTime("Anniversary"), - parents: page.getRolledupDisplayValues("Parents (display)"), + parents: page.getRolledupRecordTitles("Parents (display)"), parentIds: page.getRelationIds("Parents"), - children: page.getRolledupDisplayValues("Children (display)"), + children: page.getRolledupRecordTitles("Children (display)"), childIds: page.getRelationIds("Children"), createdAt: some(parseIso8601(page["created_time"].getStr)), lastUpdatedAt: some(parseIso8601(page["last_edited_time"].getStr)), diff --git a/src/hff_notion_api_client/utils.nim b/src/hff_notion_api_client/utils.nim index dfdfaf0..36982d4 100644 --- a/src/hff_notion_api_client/utils.nim +++ b/src/hff_notion_api_client/utils.nim @@ -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 const NOTION_MAX_PAGE_SIZE* = 100 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 = try: result = parseIso8601(str) 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) return propNode.getElems.mapIt(it["id"].getStr) -proc getRolledupDisplayValues*(page: JsonNode, propName: string): seq[string] = - let propNode = page.getPropNode("rollup", propName) - return propNode.getElems.mapIt(it{"formula", "string"}.getStr) +proc getRollupArrayValues*(page: JsonNode, propName: string): seq[JsonNode] = + return page.getPropNode("rollup", propName){"array"}.getElems(@[]) + +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 = let propNode = page.getPropNode("rich_text", propName)