-
-
Notifications
You must be signed in to change notification settings - Fork 34
feat: Route to return product info as Knowledge Panels #267
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
feat: Route to return product info as Knowledge Panels #267
Conversation
All the whitespaces modifications and similar things were automatic
|
Bonjour @stephanegigandet et @teolemon! The pytest check failed. After some digging, it seems this could be due to a connection leak in the test code. I think that the database connections aren't being closed correctly: Personally, I think that fixing it would step outside the scope of this issue. I think I should create a new issue to fix the problem (which I'd love to try and fix myself). Then, I'm not sure which way would be preferable here:
Let me know what works best. I’m open to whichever path you think is better, or something else entirely if there's a better solution obviously 😄! |
|
Will reopen when #270 is merged. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's the right direction @pascalypperciel but I don't think we want this rendering ! (it's far too verbose and not user oriented, there should be only one panel per property, and inside it, put a sensible html)
@teolemon might be able to provide what we would like to display.
I think there is a "table"
folksonomy/api.py
Outdated
| query = f""" | ||
| SELECT product, k, v, owner, version, editor, last_edit, comment | ||
| FROM folksonomy | ||
| WHERE product = %s | ||
| """ | ||
| params = [product] | ||
| if k: | ||
| query+= " AND k = %s" | ||
| params.append(k) | ||
| query += " ORDER BY k;" | ||
|
|
||
| cur, timing = await db.db_exec(query, tuple(params)) | ||
| rows = await cur.fetchall() | ||
|
|
||
| if not rows: | ||
| raise HTTPException( | ||
| status_code=404, | ||
| detail="Could not find product or key", | ||
| ) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would prefer that we reuse existing API functions here (or refactor them to use a common method).
|
Here's what we currently have in the mobile app:
|
|
Thank you for all the feedback to both of you! I will be bringing changes soon. 😄 |
Codecov ReportAttention: Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #267 +/- ##
==========================================
- Coverage 95.06% 90.21% -4.85%
==========================================
Files 5 6 +1
Lines 324 460 +136
==========================================
+ Hits 308 415 +107
- Misses 16 45 +29 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
|
Hello again @alexgarel ! So I switch from using a text element to a table element because that's how I interpreted this comment:
I added every requirement from teolemon, hopefully in a more user-friendly format. Here is an example of a return in JSON: And here's the same body but in HTML: And for the following comment:
I looked for existing helpers to reuse but couldn’t find one that fit. I considered creating a new one, but it ended up requiring changes across multiple routes to make it work cleanly. I held back on that refactor to avoid stepping beyond the scope of this issue or introducing potential merge conflicts. Happy to go through with it if you think I should, or revisit this in a follow-up PR! |
alexgarel
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@pascalypperciel first thank you so much for your work, and really sorry for the latency to review.
Overall it's good (although I'm not really convinced that we need a table, but it can be changed later).
I propose some (minor) changes.
tests/test_main.py
Outdated
| panels = data["knowledge_panels"] | ||
| assert "color" in panels | ||
| assert "size" in panels | ||
| assert "x-pg-timing" in response.headers |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No need to assert that here !
folksonomy/api.py
Outdated
| panels_by_key = {} | ||
| for row in rows: | ||
|
|
||
| product_value, k, v, _, _, _, _, _ = row | ||
|
|
||
| if k not in panels_by_key: | ||
| panels_by_key[k] = { | ||
| "Barcode": product_value, | ||
| "Key": k, | ||
| "Value": v | ||
| } | ||
| else: | ||
| data = panels_by_key[k] | ||
| if not data.get("Barcode") and product_value: | ||
| data["Barcode"] = product_value | ||
| if not data.get("Value") and v: | ||
| data["Value"] = v | ||
|
|
||
| panels = {} | ||
| for k, data in panels_by_key.items(): | ||
| rows_html = "" | ||
| for property, value in data.items(): | ||
| if value is None: | ||
| continue | ||
|
|
||
| # Links for Key and Value property | ||
| if property == "Key": | ||
| value_cell = ( | ||
| f'<a href="world.openfoodfacts.org/property/{value}">{value}</a> ' | ||
| f'<a href="wiki.openfoodfacts.org/Folksonomy/Property/{value}">ℹ</a>' | ||
| ) | ||
| elif property == "Value": | ||
| value_cell = f'<a href="world.openfoodfacts.org/property/{data["Key"]}/value/{value}">{value}</a>' | ||
| else: | ||
| value_cell = value | ||
|
|
||
| row_html = f"<tr><td>{property}</td><td>{value_cell}</td></tr>" | ||
| rows_html += row_html | ||
|
|
||
|
|
||
|
|
||
| table_html = f"<table>{rows_html}</table>" | ||
|
|
||
| table_element = TableElement( | ||
| id=k, | ||
| title=f"Folksonomy Data for '{k}'", | ||
| rows=table_html, | ||
| columns=[ | ||
| TableColumn(type="text", text="Property"), | ||
| TableColumn(type="text", text="Value") | ||
| ] | ||
| ) | ||
|
|
||
| element = Element( | ||
| type="table", | ||
| table_element=table_element | ||
| ) | ||
|
|
||
| panel = Panel( | ||
| title_element=TitleElement( | ||
| title=f"Folksonomy Data for '{k}'", | ||
| name=k | ||
| ), | ||
| elements=[element] | ||
| ) | ||
| panels[k] = panel |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would like this to be in a separate file. To avoid having a long method. Maybe knowelge_panels.py
| class TitleElement(BaseModel): | ||
| name: str | ||
| title: str | ||
|
|
||
| class TableColumn(BaseModel): | ||
| type: str | ||
| text: str | ||
|
|
||
| class TableElement(BaseModel): | ||
| id: str | ||
| title: str | ||
| rows: str | ||
| columns: List[TableColumn] | ||
|
|
||
| class Element(BaseModel): | ||
| type: str | ||
| table_element: TableElement | ||
|
|
||
| class Panel(BaseModel): | ||
| title_element: TitleElement | ||
| elements: List[Element] | ||
|
|
||
| class ProductKnowledgePanels(BaseModel): | ||
| knowledge_panels: Dict[str, Panel] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you add simple docstring to every object you introduce and eventually document fields ? (it will be in the generated documentation).
You might copy information from openfoodfacts-server OpenAPI documentation.
…ircular dependency tests passed with pytest command
Pytest now successfully complete again
|
Hello @alexgarel Thank you for the kind words and for your guidance on this PR! Apologies for the delay on my side as well! My busy winter semester has just wrapped up, so I finally have more time to contribute. 😄 Please let me know if I can bring any improvements! |
|
Hi @pascalypperciel, really sorry that I missed this PR. You did a great job. |




What
.editorconfigfile.Screenshot
With an input
kWithout an input
k, so all the keys in the productFixes bug(s)
Part of