mirror of
https://github.com/YunoHost/apps.git
synced 2024-09-03 20:06:07 +02:00
store/dash: add RSS for catalog news + port badge mechanism (#2324)
* store: fix hardcoded url * store: add rss for news Co-authored-by: oleole39 * store: port badge mechanism from the old tartiflette
This commit is contained in:
parent
a93f16c892
commit
320df5b086
5 changed files with 128 additions and 3 deletions
69
store/app.py
69
store/app.py
|
@ -11,6 +11,7 @@ import hmac
|
|||
import string
|
||||
import random
|
||||
import urllib
|
||||
from datetime import datetime
|
||||
from slugify import slugify
|
||||
from flask import (
|
||||
Flask,
|
||||
|
@ -19,6 +20,7 @@ from flask import (
|
|||
session,
|
||||
redirect,
|
||||
request,
|
||||
make_response,
|
||||
)
|
||||
from flask_babel import Babel
|
||||
from flask_babel import gettext as _
|
||||
|
@ -89,6 +91,13 @@ def days_ago(timestamp):
|
|||
return int((time.time() - timestamp) / (60 * 60 * 24))
|
||||
|
||||
|
||||
@app.template_filter("format_datetime")
|
||||
def format_datetime(value, format="%d %b %Y %I:%M %p"):
|
||||
if value is None:
|
||||
return ""
|
||||
return datetime.strptime(value, "%b %d %Y").strftime(format)
|
||||
|
||||
|
||||
@app.context_processor
|
||||
def utils():
|
||||
d = {
|
||||
|
@ -487,6 +496,66 @@ def charts():
|
|||
)
|
||||
|
||||
|
||||
@app.route("/news.rss")
|
||||
def news_rss():
|
||||
|
||||
news_per_date = json.loads(open(".cache/news.json").read())
|
||||
|
||||
# Keepy only the last N entries
|
||||
news_per_date = {d: infos for d, infos in reversed(list(news_per_date.items())[-2:])}
|
||||
|
||||
rss_xml = render_template('news_rss.xml', news_per_date=news_per_date, catalog=get_catalog())
|
||||
response = make_response(rss_xml)
|
||||
response.headers['Content-Type'] = 'application/rss+xml'
|
||||
response.headers['Content-Disposition'] = "inline; filename=news_rss.xml"
|
||||
return response
|
||||
|
||||
|
||||
# Badges
|
||||
@app.route('/integration/<app>')
|
||||
@app.route('/integration/<app>.svg')
|
||||
@app.route('/badge/<type>/<app>')
|
||||
@app.route('/badge/<type>/<app>.svg')
|
||||
def badge(app, type="integration"):
|
||||
|
||||
data = get_dashboard_data()
|
||||
catalog = get_catalog()["apps"]
|
||||
|
||||
catalog_level = catalog.get(app, {}).get("level")
|
||||
main_ci_level = data.get(app, {}).get("ci_results", {}).get("main", {}).get("level", '?')
|
||||
|
||||
if type == "integration":
|
||||
if app in catalog and main_ci_level:
|
||||
badge = f"level{main_ci_level}"
|
||||
else:
|
||||
badge = "unknown"
|
||||
elif type == "state":
|
||||
if app not in catalog:
|
||||
badge = "state-unknown"
|
||||
else:
|
||||
if catalog_level in [None, '?']:
|
||||
badge = "state-just-got-added-to-catalog"
|
||||
elif catalog_level in [0, -1]:
|
||||
badge = "state-broken"
|
||||
else:
|
||||
badge = "state-working"
|
||||
elif type == "maintained":
|
||||
if app in catalog and catalog.get(app, {}).get("maintained") is False:
|
||||
badge = "unmaintained"
|
||||
else:
|
||||
badge = "empty"
|
||||
else:
|
||||
badge = "empty"
|
||||
|
||||
svg = open(f"assets/badges/{badge}.svg").read()
|
||||
response = make_response(svg)
|
||||
response.content_type = 'image/svg+xml'
|
||||
response.headers['Cache-Control'] = 'no-cache, no-store, must-revalidate'
|
||||
response.headers['Pragma'] = 'no-cache'
|
||||
|
||||
return response
|
||||
|
||||
|
||||
###############################################################################
|
||||
# Session / SSO using Discourse #
|
||||
###############################################################################
|
||||
|
|
20
store/assets/badges/fetch_badges
Normal file
20
store/assets/badges/fetch_badges
Normal file
|
@ -0,0 +1,20 @@
|
|||
wget -O - https://img.shields.io/badge/Integration-Level_9-blue.svg > level9.svg
|
||||
wget -O - https://img.shields.io/badge/Integration-Level_8-brightgreen.svg > level8.svg
|
||||
wget -O - https://img.shields.io/badge/Integration-Level_7-green.svg > level7.svg
|
||||
wget -O - https://img.shields.io/badge/Integration-Level_6-yellowgreen.svg > level6.svg
|
||||
wget -O - https://img.shields.io/badge/Integration-Level_5-yellowgreen.svg > level5.svg
|
||||
wget -O - https://img.shields.io/badge/Integration-Level_4-yellow.svg > level4.svg
|
||||
wget -O - https://img.shields.io/badge/Integration-Level_3-yellow.svg > level3.svg
|
||||
wget -O - https://img.shields.io/badge/Integration-Level_2-orange.svg > level2.svg
|
||||
wget -O - https://img.shields.io/badge/Integration-Level_1-orange.svg > level1.svg
|
||||
wget -O - https://img.shields.io/badge/Integration-Level_0-red.svg > level0.svg
|
||||
wget -O - https://img.shields.io/badge/Integration-Unknown-lightgrey.svg > unknown.svg
|
||||
|
||||
wget -O - https://upload.wikimedia.org/wikipedia/commons/1/1d/No_image.svg > empty.svg
|
||||
wget -O - https://img.shields.io/badge/Status-Package%20not%20maintained-red.svg > unmaintained.svg
|
||||
|
||||
wget -O - https://img.shields.io/badge/Status-working-brightgreen.svg > state-working.svg
|
||||
wget -O - https://img.shields.io/badge/Status-Just%20got%20added%20to%20catalog-yellowgreen.svg > state-just-got-added-to-catalog.svg
|
||||
wget -O - https://img.shields.io/badge/Status-In%20progress-orange.svg > state-inprogress.svg
|
||||
wget -O - https://img.shields.io/badge/Status-Not%20working-red.svg > state-notworking.svg
|
||||
wget -O - https://img.shields.io/badge/Status-Broken-red.svg > state-broken.svg
|
|
@ -10,8 +10,13 @@
|
|||
<div id="levelHistory" class="h-80"></div>
|
||||
</div>
|
||||
|
||||
<div class="mx-auto w-80">
|
||||
<h1 class="text-center font-medium text-2xl py-2">{{ _("History") }}</h1>
|
||||
<div class="mx-auto w-80 py-2">
|
||||
<h1 class="text-center font-medium text-2xl pt-4">
|
||||
{{ _("History") }}
|
||||
<link rel="alternate" type="application/rss+xml" title="YunoHost apps catalog news" href="{{ url_for('news_rss')}}" />
|
||||
<a href="{{ url_for('news_rss')}}" class="btn btn-sm h-6 bg-orange-500 text-white !font-bold align-middle !px-2 !py-1"><i class="fa fa-rss-square" aria-hidden="true"></i> Suscribe via RSS</a>
|
||||
</h1>
|
||||
|
||||
<div>
|
||||
{% for date, news in news_per_date.items()|reverse %}
|
||||
<h2 class="text-center font-medium text-xl py-4">{{ date }}</h2>
|
||||
|
|
|
@ -95,7 +95,7 @@
|
|||
>
|
||||
<td class="text-center text-blue-600 font-medium"><a href="{{ infos["url"] }}">{{ app }}</a></td>
|
||||
<td class="font-bold">
|
||||
<a href="https://apps.yunohost.org/app/{{ app }}">
|
||||
<a href="{{ url_for('app_info', app_id=app) }}">
|
||||
{{ infos["public_level"] }}
|
||||
{% if infos["public_level"] == "?" %}
|
||||
{% elif infos["public_level"] == 0 %}
|
||||
|
|
31
store/templates/news_rss.xml
Normal file
31
store/templates/news_rss.xml
Normal file
|
@ -0,0 +1,31 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<rss version="2.0"
|
||||
xmlns:content="http://purl.org/rss/1.0/modules/content/"
|
||||
xmlns:wfw="http://wellformedweb.org/CommentAPI/"
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:atom="http://www.w3.org/2005/Atom"
|
||||
xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
|
||||
xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
|
||||
>
|
||||
<channel>
|
||||
<title>YunoHost apps catalog News</title>
|
||||
<link>{{ url_for('news_rss')}}</link>
|
||||
<atom:link href="{{ url_for('news_rss')}}" rel="self" type="application/rss+xml" />
|
||||
<description>YunoHost apps catalog news</description>
|
||||
{%- for date, news in news_per_date.items() %}
|
||||
{%- for status in ("added", "repaired", "broke", "removed") %}i
|
||||
{%- for app, url in news[status] %}
|
||||
{% set manifest = catalog["apps"][app]["manifest"] %}
|
||||
<item>
|
||||
<title>[{{ status|capitalize }}] {{ manifest['name'] }}</title>
|
||||
<link>{{ url_for('app_info', app_id=app) }}</link>
|
||||
<guid>{{ app }}#{{ date|format_datetime("%Y%m%d") }}</guid>
|
||||
<pubDate>{{ date|format_datetime("%a, %d %b %Y %H:%M:%S +0000") }}</pubDate>
|
||||
<description>{{ manifest["description"].get("en") }}</description>
|
||||
<content:encoded>{{ manifest["description"].get("en") }}</content:encoded>
|
||||
</item>
|
||||
{% endfor -%}
|
||||
{% endfor -%}
|
||||
{% endfor %}
|
||||
</channel>
|
||||
</rss>
|
Loading…
Add table
Reference in a new issue