Skip to content

Commit 6f5f3b9

Browse files
authored
Town6: Adds a topics API endpoint
Also includes a small extension to the existing news/events endpoint TYPE: Feature LINK: OGC-2058
1 parent e8c813d commit 6f5f3b9

File tree

4 files changed

+108
-18
lines changed

4 files changed

+108
-18
lines changed

Diff for: docs/api/org/README.md

+11-6
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ The headless Org API offers the following views:
44

55
- [Events](#events-view)
66
- [News](#news-view)
7+
- [Topics](#topics-view)
78

89
We implement the called Collection+JSON standard established by Mike
910
Amundsen. For details please refer to [media types - collection & json](http://amundsen.com/media-types/collection/format/)
@@ -122,13 +123,17 @@ A collection+JSON of items including paging
122123

123124
## News View
124125

125-
The news view provides information about all people in relation with agencies
126-
within the organisation. Each person offers several data fields like
127-
first and last name, academic title, function within the organisation,
128-
contact information and more. Additionally, the people api provides links to
129-
a picture, website and memberships to agencies memberships if given.
126+
The news view provides information about all the news.
130127

131-
`curl https://[base_url]/people`
128+
`curl https://[base_url]/news`
129+
130+
## Topics View
131+
132+
The topics view provides information about all the topics, including
133+
their hierarchical relationship via a `parent` link. Links to children
134+
are implicit through their `parent` link.
135+
136+
`curl https://[base_url]/topics`
132137

133138

134139
## Authorization

Diff for: src/onegov/org/models/page.py

+40
Original file line numberDiff line numberDiff line change
@@ -351,6 +351,46 @@ def all_tags(self) -> list[str]:
351351
return sorted(all_hashtags)
352352

353353

354+
class TopicCollection(Pagination[Topic], AdjacencyListCollection[Topic]):
355+
"""
356+
Use it like this:
357+
358+
from onegov.page import TopicCollection
359+
topics = TopicCollection(session)
360+
"""
361+
362+
__listclass__ = Topic
363+
364+
def __init__(
365+
self,
366+
session: Session,
367+
page: int = 0,
368+
):
369+
self.session = session
370+
self.page = page
371+
372+
def subset(self) -> Query[Topic]:
373+
topics = self.session.query(Topic)
374+
topics = topics.filter(
375+
News.publication_started == True,
376+
News.publication_ended == False
377+
)
378+
topics = topics.order_by(desc(Topic.published_or_created))
379+
topics = topics.options(undefer('created'))
380+
topics = topics.options(undefer('content'))
381+
return topics
382+
383+
@property
384+
def page_index(self) -> int:
385+
return self.page
386+
387+
def page_by_index(self, index: int) -> Self:
388+
return self.__class__(
389+
self.session,
390+
page=index
391+
)
392+
393+
354394
class NewsCollection(Pagination[News], AdjacencyListCollection[News]):
355395
"""
356396
Use it like this:

Diff for: src/onegov/town6/api.py

+53-10
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,16 @@
11
from __future__ import annotations
22

33
from onegov.event.collections import OccurrenceCollection
4-
from onegov.api import ApiEndpoint
4+
from onegov.api.models import ApiEndpoint, ApiEndpointItem
55
from onegov.gis import Coordinates
66

77

88
from typing import Any
99
from typing import TYPE_CHECKING
1010

11-
from onegov.org.models.page import NewsCollection
11+
from onegov.org.models.page import News, NewsCollection, Topic, TopicCollection
1212

1313
if TYPE_CHECKING:
14-
from onegov.org.models.page import News
1514
from onegov.town6.app import TownApp
1615
from onegov.event.models import Occurrence
1716
from onegov.core.orm.mixins import ContentMixin
@@ -36,9 +35,7 @@ def get_modified_iso_format(item: TimestampMixin) -> str:
3635
return item.last_change.isoformat()
3736

3837

39-
class EventApiEndpoint(
40-
ApiEndpoint['Occurrence'],
41-
):
38+
class EventApiEndpoint(ApiEndpoint['Occurrence']):
4239
app: TownApp
4340
endpoint = 'events'
4441

@@ -73,14 +70,13 @@ def item_data(self, item: Occurrence) -> dict[str, Any]:
7370

7471
def item_links(self, item: Occurrence) -> dict[str, Any]:
7572
return {
73+
'html': item,
7674
'image': item.event.image,
7775
'pfd': item.event.pdf
7876
}
7977

8078

81-
class NewsApiEndpoint(
82-
ApiEndpoint['News'],
83-
):
79+
class NewsApiEndpoint(ApiEndpoint[News]):
8480
app: TownApp
8581
endpoint = 'news'
8682
filters = set()
@@ -109,6 +105,7 @@ def item_data(self, item: News) -> dict[str, Any]:
109105
'title': item.title,
110106
'lead': item.lead,
111107
'text': item.text,
108+
'hashtags': item.hashtags,
112109
'publication_start': publication_start,
113110
'publication_end': publication_end,
114111
'created': item.created.isoformat(),
@@ -117,5 +114,51 @@ def item_data(self, item: News) -> dict[str, Any]:
117114

118115
def item_links(self, item: News) -> dict[str, Any]:
119116
return {
120-
'image': item.page_image,
117+
'html': item,
118+
'image': item.page_image or None,
119+
}
120+
121+
122+
class TopicApiEndpoint(ApiEndpoint[Topic]):
123+
app: TownApp
124+
endpoint = 'topics'
125+
filters = set()
126+
127+
@property
128+
def collection(self) -> Any:
129+
result = TopicCollection(
130+
self.session,
131+
page=self.page or 0
132+
)
133+
result.batch_size = 25
134+
return result
135+
136+
def item_data(self, item: Topic) -> dict[str, Any]:
137+
if item.publication_start:
138+
publication_start = item.publication_start.isoformat()
139+
else:
140+
publication_start = None
141+
142+
if item.publication_end:
143+
publication_end = item.publication_end.isoformat()
144+
else:
145+
publication_end = None
146+
147+
return {
148+
'title': item.title,
149+
'lead': item.lead,
150+
'text': item.text,
151+
'publication_start': publication_start,
152+
'publication_end': publication_end,
153+
'created': item.created.isoformat(),
154+
'modified': get_modified_iso_format(item),
155+
}
156+
157+
def item_links(self, item: Topic) -> dict[str, Any]:
158+
return {
159+
'html': item,
160+
'image': item.page_image or None,
161+
'parent': ApiEndpointItem(
162+
self.app, self.endpoint, str(item.parent_id)
163+
) if item.parent_id is not None else None,
121164
}

Diff for: src/onegov/town6/app.py

+4-2
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,8 @@
1212
from onegov.foundation6.integration import FoundationApp
1313
from onegov.org.app import OrgApp
1414
from onegov.org.app import get_i18n_localedirs as get_org_i18n_localedirs
15-
from onegov.town6.api import EventApiEndpoint, NewsApiEndpoint
15+
from onegov.town6.api import (
16+
EventApiEndpoint, NewsApiEndpoint, TopicApiEndpoint)
1617
from onegov.town6.custom import get_global_tools
1718
from onegov.town6.initial_content import create_new_organisation
1819
from onegov.town6.theme import TownTheme
@@ -197,7 +198,8 @@ def get_public_ticket_messages() -> tuple[str, ...]:
197198
def get_api_endpoints() -> list[type[ApiEndpoint[Any]]]:
198199
return [
199200
EventApiEndpoint,
200-
NewsApiEndpoint
201+
NewsApiEndpoint,
202+
TopicApiEndpoint,
201203
]
202204

203205

0 commit comments

Comments
 (0)