[client]: Pagination and additional card info
This commit is contained in:
parent
7cd847ce64
commit
c98946cacb
|
@ -102,32 +102,47 @@ class FavroClient:
|
||||||
seq_id: SeqId | None = None,
|
seq_id: SeqId | None = None,
|
||||||
todo_list=False,
|
todo_list=False,
|
||||||
) -> Iterator[Card]:
|
) -> Iterator[Card]:
|
||||||
# Determine params for get_cards
|
page = 0
|
||||||
request = self._get_cards_request(seq_id, todo_list)
|
request_id = None
|
||||||
|
num_pages = 1
|
||||||
|
|
||||||
# Run query
|
while page < num_pages:
|
||||||
logger.warning('Sending request: %s', request.url)
|
# Determine params for get_cards
|
||||||
response = self.session.send(request)
|
request = self._get_cards_request(seq_id, todo_list, page=page, request_id=request_id)
|
||||||
response.raise_for_status()
|
|
||||||
json = response.json()
|
|
||||||
|
|
||||||
# TODO: Add support for pageination
|
# Run query
|
||||||
for entity_json in json['entities']:
|
logger.warning('Sending request: %s', request.url)
|
||||||
card = Card.from_json(entity_json)
|
response = self.session.send(request)
|
||||||
self.cache.add_card(card)
|
response.raise_for_status()
|
||||||
yield card
|
json = response.json()
|
||||||
del entity_json
|
|
||||||
|
for entity_json in json['entities']:
|
||||||
|
card = Card.from_json(entity_json)
|
||||||
|
self.cache.add_card(card)
|
||||||
|
yield card
|
||||||
|
del entity_json
|
||||||
|
|
||||||
|
# Pagination bookkeeping
|
||||||
|
page = json['page'] + 1
|
||||||
|
request_id = json['requestId']
|
||||||
|
num_pages = json['pages']
|
||||||
|
|
||||||
def _get_cards_request(
|
def _get_cards_request(
|
||||||
self,
|
self,
|
||||||
seq_id: SeqId | None = None,
|
seq_id: SeqId | None = None,
|
||||||
todo_list=False,
|
todo_list: bool=False,
|
||||||
|
request_id: None | str = None,
|
||||||
|
page: None | int = None,
|
||||||
) -> requests.PreparedRequest:
|
) -> requests.PreparedRequest:
|
||||||
params = {'descriptionFormat': 'markdown'}
|
params = {'descriptionFormat': 'markdown'}
|
||||||
if seq_id is not None:
|
if seq_id is not None:
|
||||||
params['cardSequentialId'] = str(seq_id.raw_id)
|
params['cardSequentialId'] = str(seq_id.raw_id)
|
||||||
if todo_list is True:
|
if todo_list is True:
|
||||||
params['todoList'] = 'true'
|
params['todoList'] = 'true'
|
||||||
|
if request_id:
|
||||||
|
params['requestId'] = request_id
|
||||||
|
if page:
|
||||||
|
params['page'] = page
|
||||||
|
|
||||||
request = requests.Request('GET', URL_GET_ALL_CARDS, params=params)
|
request = requests.Request('GET', URL_GET_ALL_CARDS, params=params)
|
||||||
return self.session.prepare_request(request)
|
return self.session.prepare_request(request)
|
||||||
|
@ -192,6 +207,7 @@ class FavroClient:
|
||||||
'name': card_contents.name,
|
'name': card_contents.name,
|
||||||
'detailedDescription': card_contents.description,
|
'detailedDescription': card_contents.description,
|
||||||
'descriptionFormat': 'markdown',
|
'descriptionFormat': 'markdown',
|
||||||
|
'archived': card_contents.archived,
|
||||||
}
|
}
|
||||||
|
|
||||||
url = URL_UPDATE_CARD.format(card_id=card_id.raw_id)
|
url = URL_UPDATE_CARD.format(card_id=card_id.raw_id)
|
||||||
|
|
|
@ -94,13 +94,13 @@ class TagInfo:
|
||||||
@dataclasses.dataclass(frozen=True)
|
@dataclasses.dataclass(frozen=True)
|
||||||
class CustomField:
|
class CustomField:
|
||||||
custom_field_id: CustomFieldId
|
custom_field_id: CustomFieldId
|
||||||
value: list[str] # TODO
|
value: list[str] | str
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def from_json(json: dict[str, Any]) -> 'CustomField':
|
def from_json(json: dict[str, Any]) -> 'CustomField':
|
||||||
return CustomField(
|
return CustomField(
|
||||||
CustomFieldId(json['customFieldId']),
|
CustomFieldId(json['customFieldId']),
|
||||||
json['value'], # TODO
|
json.get('value'),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@ -137,14 +137,14 @@ class Card:
|
||||||
todo_list_completed: bool | None
|
todo_list_completed: bool | None
|
||||||
creator_user_id: UserId
|
creator_user_id: UserId
|
||||||
creation_date: datetime.datetime
|
creation_date: datetime.datetime
|
||||||
|
start_date: datetime.date | None
|
||||||
|
due_date: datetime.date | None
|
||||||
attachments: list[dict]
|
attachments: list[dict]
|
||||||
detailed_description: str | None
|
detailed_description: str | None
|
||||||
|
archived: bool
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def from_json(json: dict[str, Any]) -> 'Card':
|
def from_json(json: dict[str, Any]) -> 'Card':
|
||||||
todo_list_user_id = (
|
|
||||||
UserId(json['todoListUserId']) if 'todoListUserId' in json else None
|
|
||||||
)
|
|
||||||
return Card(
|
return Card(
|
||||||
card_id=CardId(json['cardId']),
|
card_id=CardId(json['cardId']),
|
||||||
seq_id=SeqId(json['sequentialId']),
|
seq_id=SeqId(json['sequentialId']),
|
||||||
|
@ -153,17 +153,25 @@ class Card:
|
||||||
is_archived=json['archived'],
|
is_archived=json['archived'],
|
||||||
organization_id=OrganizationId(json['organizationId']),
|
organization_id=OrganizationId(json['organizationId']),
|
||||||
name=json['name'],
|
name=json['name'],
|
||||||
todo_list_user_id=todo_list_user_id,
|
todo_list_user_id=map_opt(UserId, json.get('todoListUserId')),
|
||||||
todo_list_completed=json.get('todoListCompleted'),
|
todo_list_completed=json.get('todoListCompleted'),
|
||||||
dependencies=[
|
dependencies=[
|
||||||
CardDependency.from_json(dep) for dep in json['dependencies']
|
CardDependency.from_json(dep) for dep in json['dependencies']
|
||||||
],
|
],
|
||||||
tags=[TagId(tag) for tag in json['tags']],
|
tags=[TagId(tag) for tag in json['tags']],
|
||||||
creator_user_id=UserId(json['createdByUserId']),
|
creator_user_id=UserId(json['createdByUserId']),
|
||||||
creation_date=datetime.datetime.fromisoformat(json['createdAt']),
|
creation_date=map_opt(datetime.datetime.fromisoformat,json.get('createdAt')),
|
||||||
|
start_date=map_opt(datetime.datetime.fromisoformat,json.get('startDate')),
|
||||||
|
due_date=map_opt(datetime.datetime.fromisoformat,json.get('dueDate')),
|
||||||
assignments=[CardAssignment.from_json(ass) for ass in json['assignments']],
|
assignments=[CardAssignment.from_json(ass) for ass in json['assignments']],
|
||||||
custom_fields=[
|
custom_fields=[
|
||||||
CustomField.from_json(field) for field in json['customFields']
|
CustomField.from_json(field) for field in json['customFields']
|
||||||
],
|
],
|
||||||
|
archived=json['archived'],
|
||||||
attachments=json['attachments'], # TODO
|
attachments=json['attachments'], # TODO
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def map_opt(mapper, value):
|
||||||
|
if value is not None:
|
||||||
|
return mapper(value)
|
||||||
|
return None
|
||||||
|
|
|
@ -201,6 +201,8 @@ class FavroFuse(fuse.Fuse):
|
||||||
seq_id=card.seq_id.raw_id,
|
seq_id=card.seq_id.raw_id,
|
||||||
),
|
),
|
||||||
todo_list_completed = card.todo_list_completed,
|
todo_list_completed = card.todo_list_completed,
|
||||||
|
start_date= card.start_date,
|
||||||
|
due_date= card.due_date,
|
||||||
)
|
)
|
||||||
return self.formatter.format_card_contents(card_contents)
|
return self.formatter.format_card_contents(card_contents)
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
import dataclasses
|
import dataclasses
|
||||||
import re
|
import re
|
||||||
|
import datetime
|
||||||
|
|
||||||
import frontmatter
|
import frontmatter
|
||||||
import marko
|
import marko
|
||||||
|
@ -14,6 +15,9 @@ FM_KEY_ASSIGNMENTS = 'assignments'
|
||||||
FM_KEY_DEPENDENCIES = 'dependencies'
|
FM_KEY_DEPENDENCIES = 'dependencies'
|
||||||
FM_KEY_URL = 'url'
|
FM_KEY_URL = 'url'
|
||||||
FM_KEY_ALIASES = 'aliases'
|
FM_KEY_ALIASES = 'aliases'
|
||||||
|
FM_KEY_ARCHIVED = 'archived'
|
||||||
|
FM_KEY_DUE_DATE = 'due'
|
||||||
|
FM_KEY_START_DATE = 'start-date'
|
||||||
|
|
||||||
################################################################################
|
################################################################################
|
||||||
|
|
||||||
|
@ -27,6 +31,9 @@ class CardContents:
|
||||||
card_dependencies: list[str]
|
card_dependencies: list[str]
|
||||||
url: str
|
url: str
|
||||||
todo_list_completed: bool | None
|
todo_list_completed: bool | None
|
||||||
|
archived: bool
|
||||||
|
start_date: datetime.date | None
|
||||||
|
due_date: datetime.date | None
|
||||||
|
|
||||||
|
|
||||||
def format_obsidian_link(text: str) -> str:
|
def format_obsidian_link(text: str) -> str:
|
||||||
|
@ -87,6 +94,12 @@ class CardFileFormatter:
|
||||||
]
|
]
|
||||||
if card.todo_list_completed:
|
if card.todo_list_completed:
|
||||||
frontmatter_data[FM_KEY_TODO_LIST_COMPLETED] = card.todo_list_completed
|
frontmatter_data[FM_KEY_TODO_LIST_COMPLETED] = card.todo_list_completed
|
||||||
|
if card.archived:
|
||||||
|
frontmatter_data[FM_KEY_ARCHIVED] = card.archived
|
||||||
|
if card.due_date:
|
||||||
|
frontmatter_data[FM_KEY_DUE_DATE] = card.due_date
|
||||||
|
if card.start_date:
|
||||||
|
frontmatter_data[FM_KEY_DUE_DATE] = card.start_date
|
||||||
|
|
||||||
# Card name
|
# Card name
|
||||||
ls = []
|
ls = []
|
||||||
|
@ -134,6 +147,10 @@ class CardFileFormatter:
|
||||||
|
|
||||||
url: list[str] = fm.metadata.get(FM_KEY_URL)
|
url: list[str] = fm.metadata.get(FM_KEY_URL)
|
||||||
todo_list_completed: bool | None = fm.metadata.get(FM_KEY_TODO_LIST_COMPLETED)
|
todo_list_completed: bool | None = fm.metadata.get(FM_KEY_TODO_LIST_COMPLETED)
|
||||||
|
archived: bool = fm.metadata.get(FM_KEY_ARCHIVED)
|
||||||
|
|
||||||
|
start_date: datetime.date = fm.metadata.get(FM_KEY_START_DATE)
|
||||||
|
due_date: datetime.date = fm.metadata.get(FM_KEY_DUE_DATE)
|
||||||
|
|
||||||
description = self.renderer.render_children(document).strip()
|
description = self.renderer.render_children(document).strip()
|
||||||
return CardContents(
|
return CardContents(
|
||||||
|
@ -145,4 +162,7 @@ class CardFileFormatter:
|
||||||
card_dependencies=card_dependencies,
|
card_dependencies=card_dependencies,
|
||||||
url=url,
|
url=url,
|
||||||
todo_list_completed=todo_list_completed,
|
todo_list_completed=todo_list_completed,
|
||||||
|
archived=archived,
|
||||||
|
start_date=start_date,
|
||||||
|
due_date=due_date,
|
||||||
)
|
)
|
||||||
|
|
|
@ -20,15 +20,19 @@ def test_create_client():
|
||||||
def test_get_card():
|
def test_get_card():
|
||||||
client = create_client()
|
client = create_client()
|
||||||
card = client.get_card(SeqId(11368))
|
card = client.get_card(SeqId(11368))
|
||||||
print(card)
|
|
||||||
|
|
||||||
assert card is not None
|
assert_valid_card(card)
|
||||||
assert card.name is not None
|
|
||||||
assert card.detailed_description is not None
|
assert card.detailed_description is not None
|
||||||
assert len(card.dependencies) == 1
|
assert len(card.dependencies) == 1
|
||||||
assert len(card.attachments) == 0
|
assert len(card.attachments) == 0
|
||||||
assert len(card.custom_fields) == 2
|
assert len(card.custom_fields) == 2
|
||||||
|
|
||||||
|
@needs_secrets
|
||||||
|
def test_get_cards():
|
||||||
|
client = create_client()
|
||||||
|
for card in client.get_cards(todo_list=True):
|
||||||
|
assert_valid_card(card)
|
||||||
|
|
||||||
def create_client():
|
def create_client():
|
||||||
return FavroClient(
|
return FavroClient(
|
||||||
|
@ -37,3 +41,7 @@ def create_client():
|
||||||
favro_password=secrets.favro_password(),
|
favro_password=secrets.favro_password(),
|
||||||
read_only=True,
|
read_only=True,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def assert_valid_card(card):
|
||||||
|
assert card is not None
|
||||||
|
assert card.name is not None
|
||||||
|
|
Loading…
Reference in New Issue
Block a user