Merge branch 'update_app_levels' of https://github.com/YunoHost/apps into update_app_levels
46
apps.toml
|
@ -150,7 +150,7 @@ url = "https://github.com/YunoHost-Apps/archivebox_ynh"
|
|||
[archivist]
|
||||
added_date = 1674232499 # 2023/01/20
|
||||
category = "system_tools"
|
||||
level = 6
|
||||
level = 7
|
||||
state = "working"
|
||||
subtags = [ "backup" ]
|
||||
url = "https://github.com/YunoHost-Apps/archivist_ynh"
|
||||
|
@ -205,7 +205,7 @@ url = "https://github.com/YunoHost-Apps/baikal_ynh"
|
|||
[bazarr]
|
||||
added_date = 1674232499 # 2023/01/20
|
||||
category = "multimedia"
|
||||
level = 6
|
||||
level = 8
|
||||
state = "working"
|
||||
url = "https://github.com/YunoHost-Apps/bazarr_ynh"
|
||||
|
||||
|
@ -440,7 +440,7 @@ url = "https://github.com/YunoHost-Apps/civicrm_drupal7_ynh"
|
|||
[cjdns]
|
||||
added_date = 1703094732 # 2023/12/20
|
||||
category = "system_tools"
|
||||
level = 0
|
||||
level = 6
|
||||
state = "working"
|
||||
subtags = [ "network" ]
|
||||
url = "https://github.com/YunoHost-Apps/cjdns_ynh"
|
||||
|
@ -778,7 +778,7 @@ url = "https://github.com/YunoHost-Apps/django-fmd_ynh"
|
|||
[django-for-runners]
|
||||
added_date = 1674232499 # 2023/01/20
|
||||
category = "small_utilities"
|
||||
level = 6
|
||||
level = 3
|
||||
state = "working"
|
||||
url = "https://github.com/YunoHost-Apps/django-for-runners_ynh"
|
||||
|
||||
|
@ -793,7 +793,7 @@ url = "https://github.com/YunoHost-Apps/django-fritzconnection_ynh"
|
|||
[django_example]
|
||||
added_date = 1674232499 # 2023/01/20
|
||||
category = "dev"
|
||||
level = 3
|
||||
level = 8
|
||||
state = "working"
|
||||
subtags = [ "programming" ]
|
||||
url = "https://github.com/YunoHost-Apps/django_example_ynh"
|
||||
|
@ -900,7 +900,7 @@ url = "https://github.com/YunoHost-Apps/elabftw_ynh"
|
|||
added_date = 1674232499 # 2023/01/20
|
||||
antifeatures = [ "not-totally-free-upstream" ]
|
||||
category = "dev"
|
||||
level = 6
|
||||
level = 8
|
||||
state = "working"
|
||||
subtags = [ "programming" ]
|
||||
url = "https://github.com/YunoHost-Apps/elasticsearch7_ynh"
|
||||
|
@ -1142,7 +1142,7 @@ url = "https://github.com/YunoHost-Apps/flarum_ynh"
|
|||
added_date = 1714137502 # 2024/04/26
|
||||
antifeatures = [ "alpha-software", "arbitrary-limitations" ]
|
||||
category = "publishing"
|
||||
level = 6
|
||||
level = 7
|
||||
potential_alternative_to = [ "ClassifiedAds.com", "kleinanzeigen.de" ]
|
||||
state = "working"
|
||||
subtags = [ "ecommerce" ]
|
||||
|
@ -1471,7 +1471,7 @@ url = "https://github.com/YunoHost-Apps/guacamole_ynh"
|
|||
[h5ai]
|
||||
added_date = 1674232499 # 2023/01/20
|
||||
category = "small_utilities"
|
||||
level = 0
|
||||
level = 6
|
||||
state = "working"
|
||||
url = "https://github.com/YunoHost-Apps/h5ai_ynh"
|
||||
|
||||
|
@ -2268,7 +2268,7 @@ url = "https://github.com/YunoHost-Apps/mautrix_facebook_ynh"
|
|||
[mautrix_signal]
|
||||
added_date = 1674232499 # 2023/01/20
|
||||
category = "communication"
|
||||
level = 0
|
||||
level = 3
|
||||
potential_alternative_to = [ "Signal" ]
|
||||
state = "working"
|
||||
subtags = [ "chat" ]
|
||||
|
@ -2277,7 +2277,7 @@ url = "https://github.com/YunoHost-Apps/mautrix_signal_ynh"
|
|||
[mautrix_telegram]
|
||||
added_date = 1674232499 # 2023/01/20
|
||||
category = "communication"
|
||||
level = 0
|
||||
level = 8
|
||||
potential_alternative_to = [ "Telegram" ]
|
||||
state = "working"
|
||||
subtags = [ "chat" ]
|
||||
|
@ -2609,7 +2609,7 @@ url = "https://github.com/YunoHost-Apps/nocodb_ynh"
|
|||
[nodebb]
|
||||
added_date = 1674232499 # 2023/01/20
|
||||
category = "communication"
|
||||
level = 8
|
||||
level = 6
|
||||
state = "working"
|
||||
subtags = [ "forum" ]
|
||||
url = "https://github.com/YunoHost-Apps/nodebb_ynh"
|
||||
|
@ -2856,7 +2856,7 @@ url = "https://github.com/YunoHost-Apps/peertube_ynh"
|
|||
added_date = 1674232499 # 2023/01/20
|
||||
antifeatures = [ "not-totally-free-upstream" ]
|
||||
category = "social_media"
|
||||
level = 7
|
||||
level = 1
|
||||
state = "working"
|
||||
subtags = [ "videos" ]
|
||||
url = "https://github.com/YunoHost-Apps/peertube-search-index_ynh"
|
||||
|
@ -3090,7 +3090,7 @@ url = "https://github.com/YunoHost-Apps/plateau_ynh"
|
|||
[pleroma]
|
||||
added_date = 1674232499 # 2023/01/20
|
||||
category = "social_media"
|
||||
level = 6
|
||||
level = 8
|
||||
potential_alternative_to = [ "X" ]
|
||||
state = "working"
|
||||
subtags = [ "microblogging" ]
|
||||
|
@ -3132,7 +3132,7 @@ url = "https://github.com/YunoHost-Apps/prestashop_ynh"
|
|||
[prettynoemiecms]
|
||||
added_date = 1674232499 # 2023/01/20
|
||||
category = "publishing"
|
||||
level = 8
|
||||
level = 2
|
||||
potential_alternative_to = [ "Wix" ]
|
||||
state = "working"
|
||||
subtags = [ "website" ]
|
||||
|
@ -3368,7 +3368,7 @@ url = "https://github.com/YunoHost-Apps/rocketchat_ynh"
|
|||
[roundcube]
|
||||
added_date = 1674232499 # 2023/01/20
|
||||
category = "communication"
|
||||
level = 8
|
||||
level = 2
|
||||
potential_alternative_to = [ "GMail", "Hotmail", "Microsoft Outlook", "Yahoo! Mail" ]
|
||||
state = "working"
|
||||
subtags = [ "email" ]
|
||||
|
@ -3430,7 +3430,7 @@ url = "https://github.com/YunoHost-Apps/satdress_ynh"
|
|||
[scovie]
|
||||
added_date = 1685183203 # 2023/05/27
|
||||
category = "publishing"
|
||||
level = 8
|
||||
level = 3
|
||||
state = "working"
|
||||
subtags = [ "website" ]
|
||||
url = "https://github.com/YunoHost-Apps/scovie_ynh"
|
||||
|
@ -3479,7 +3479,7 @@ url = "https://github.com/YunoHost-Apps/searx_ynh"
|
|||
[searxng]
|
||||
added_date = 1678310393 # 2023/03/08
|
||||
category = "small_utilities"
|
||||
level = 8
|
||||
level = 6
|
||||
potential_alternative_to = [ "Bing", "DuckDuckGo", "Google", "SearX", "Yahoo" ]
|
||||
state = "working"
|
||||
url = "https://github.com/YunoHost-Apps/searxng_ynh"
|
||||
|
@ -4283,6 +4283,14 @@ level = 8
|
|||
state = "working"
|
||||
url = "https://github.com/YunoHost-Apps/yacy_ynh"
|
||||
|
||||
[yarr]
|
||||
added_date = 1715771420 # 2024/05/15
|
||||
category = "reading"
|
||||
level = 7
|
||||
state = "working"
|
||||
subtags = [ "rssreader" ]
|
||||
url = "https://github.com/YunoHost-Apps/yarr_ynh"
|
||||
|
||||
[yellow]
|
||||
added_date = 1674232499 # 2023/01/20
|
||||
category = "publishing"
|
||||
|
@ -4375,7 +4383,7 @@ url = "https://github.com/YunoHost-Apps/zeronet_ynh"
|
|||
added_date = 1674232499 # 2023/01/20
|
||||
antifeatures = [ "non-free-network", "not-totally-free-upstream" ]
|
||||
category = "system_tools"
|
||||
level = 8
|
||||
level = 0
|
||||
state = "working"
|
||||
subtags = [ "network" ]
|
||||
url = "https://github.com/YunoHost-Apps/zerotier_ynh"
|
||||
|
@ -4402,7 +4410,7 @@ url = "https://github.com/YunoHost-Apps/zipline_ynh"
|
|||
added_date = 1674232499 # 2023/01/20
|
||||
antifeatures = [ "non-free-dependencies" ]
|
||||
category = "system_tools"
|
||||
level = 6
|
||||
level = 8
|
||||
state = "working"
|
||||
subtags = [ "network" ]
|
||||
url = "https://github.com/YunoHost-Apps/ztncui_ynh"
|
||||
|
|
12
cron
|
@ -1,8 +1,14 @@
|
|||
# Every 4 hours
|
||||
0 */4 * * * root /bin/bash __BASEDIR__/rebuild.sh
|
||||
0 */4 * * * root /bin/bash __BASEDIR__/maintenance.sh rebuild_catalog
|
||||
|
||||
# Everyday at 01:30 UTC
|
||||
30 1 * * * root /bin/bash __BASEDIR__/sourcesautoupdate.sh
|
||||
30 1 * * * root /bin/bash __BASEDIR__/maintenance.sh autoupdate_app_sources
|
||||
|
||||
# Every friday at 6 PM UTC
|
||||
0 17 * * 5 root /usr/bin/python3 __BASEDIR__/tools/update_app_levels/update_app_levels.py
|
||||
0 17 * * 5 root /bin/bash __BASEDIR__/maintenance.sh update_app_levels
|
||||
|
||||
# Every 6 hours
|
||||
0 */6 * * * root /bin/bash __BASEDIR__/maintenance.sh fetch_main_dashboard
|
||||
|
||||
# Every day at 2AM
|
||||
0 2 * * * root /bin/bash __BASEDIR__/maintenance.sh fetch_level_history
|
||||
|
|
Before Width: | Height: | Size: 23 KiB After Width: | Height: | Size: 40 KiB |
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 27 KiB |
Before Width: | Height: | Size: 1.3 KiB After Width: | Height: | Size: 4.4 KiB |
BIN
logos/cheky.png
Before Width: | Height: | Size: 5.6 KiB After Width: | Height: | Size: 13 KiB |
Before Width: | Height: | Size: 6.2 KiB After Width: | Height: | Size: 10 KiB |
BIN
logos/coin.png
Before Width: | Height: | Size: 3.5 KiB After Width: | Height: | Size: 8.2 KiB |
Before Width: | Height: | Size: 7.3 KiB After Width: | Height: | Size: 11 KiB |
Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 28 KiB |
Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 28 KiB |
Before Width: | Height: | Size: 2.2 KiB After Width: | Height: | Size: 4.9 KiB |
Before Width: | Height: | Size: 4.7 KiB After Width: | Height: | Size: 8.7 KiB |
Before Width: | Height: | Size: 5.1 KiB After Width: | Height: | Size: 11 KiB |
BIN
logos/endi.png
Before Width: | Height: | Size: 2.1 KiB After Width: | Height: | Size: 5.1 KiB |
Before Width: | Height: | Size: 3.7 KiB After Width: | Height: | Size: 6.4 KiB |
BIN
logos/jappix.png
Before Width: | Height: | Size: 7.2 KiB After Width: | Height: | Size: 20 KiB |
BIN
logos/kiwix.png
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 14 KiB |
BIN
logos/leed.png
Before Width: | Height: | Size: 1.8 KiB After Width: | Height: | Size: 3.8 KiB |
Before Width: | Height: | Size: 24 KiB After Width: | Height: | Size: 32 KiB |
BIN
logos/lstu.png
Before Width: | Height: | Size: 7.8 KiB After Width: | Height: | Size: 10 KiB |
Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 25 KiB |
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 15 KiB |
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 15 KiB |
Before Width: | Height: | Size: 2.4 KiB After Width: | Height: | Size: 6.2 KiB |
BIN
logos/paheko.png
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 17 KiB |
Before Width: | Height: | Size: 6.7 KiB After Width: | Height: | Size: 8.7 KiB |
Before Width: | Height: | Size: 2.6 KiB After Width: | Height: | Size: 6.8 KiB |
Before Width: | Height: | Size: 8 KiB After Width: | Height: | Size: 20 KiB |
Before Width: | Height: | Size: 6.3 KiB After Width: | Height: | Size: 8.4 KiB |
Before Width: | Height: | Size: 13 KiB After Width: | Height: | Size: 13 KiB |
BIN
logos/yarr.png
Normal file
After Width: | Height: | Size: 6.8 KiB |
98
maintenance.sh
Normal file
|
@ -0,0 +1,98 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
workdir=$(realpath $(dirname "$0"))
|
||||
cd $workdir
|
||||
|
||||
function git_pull_and_update_cron_and_restart_services_if_needed()
|
||||
{
|
||||
git pull &>/dev/null
|
||||
|
||||
# Cron
|
||||
cat cron | sed "s@__BASEDIR__@$workdir@g" > /etc/cron.d/app_list
|
||||
|
||||
# App store
|
||||
chown -R appstore store
|
||||
pushd store >/dev/null
|
||||
modified_after_service_start="$(find *.py translations/ templates/ assets/ -newermt "$(systemctl show --property=ActiveEnterTimestamp appstore | cut -d= -f2 | cut -d' ' -f2-3)")"
|
||||
if [ -n "$modified_after_service_start" ]
|
||||
then
|
||||
pushd assets >/dev/null
|
||||
./tailwindcss-linux-x64 --input tailwind-local.css --output tailwind.css --minify
|
||||
popd >/dev/null
|
||||
systemctl restart appstore
|
||||
sleep 3
|
||||
fi
|
||||
popd >/dev/null
|
||||
|
||||
systemctl --quiet is-active appstore || sendxmpppy "[appstore] Uhoh, failed to (re)start the appstore service?"
|
||||
|
||||
# App generator
|
||||
chown -R appgenerator tools/app_generator
|
||||
pushd tools/app_generator >/dev/null
|
||||
modified_after_service_start="$(find *.py translations/ templates/ static/ -newermt "$(systemctl show --property=ActiveEnterTimestamp appgenerator | cut -d= -f2 | cut -d' ' -f2-3)")"
|
||||
if [ -n "$modified_after_service_start" ]
|
||||
then
|
||||
pushd assets >/dev/null
|
||||
./tailwindcss-linux-x64 --input tailwind-local.css --output tailwind.css --minify
|
||||
popd >/dev/null
|
||||
systemctl restart appgenerator
|
||||
sleep 3
|
||||
fi
|
||||
popd >/dev/null
|
||||
|
||||
systemctl --quiet is-active appgenerator || sendxmpppy "[appgenerator] Uhoh, failed to (re)start the appgenerator service?"
|
||||
|
||||
# Autoreadme
|
||||
pushd tools/readme_generator >/dev/null
|
||||
modified_after_service_start="$(find *.py translations/ templates/ -newermt "$(systemctl show --property=ActiveEnterTimestamp autoreadme | cut -d= -f2 | cut -d' ' -f2-3)")"
|
||||
if [ -n "$modified_after_service_start" ]
|
||||
then
|
||||
systemctl restart autoreadme
|
||||
sleep 3
|
||||
fi
|
||||
popd >/dev/null
|
||||
|
||||
systemctl --quiet is-active autoreadme || sendxmpppy "[autoreadme] Uhoh, failed to (re)start the autoreadme service?"
|
||||
}
|
||||
|
||||
function rebuild_catalog()
|
||||
{
|
||||
log=$workdir/app_list_auto_update.log
|
||||
date >> $log
|
||||
git_pull_and_update_cron_and_restart_services_if_needed
|
||||
./tools/list_builder.py &>> $log || sendxmpppy "[listbuilder] Rebuilding the application list failed miserably"
|
||||
}
|
||||
|
||||
function autoupdate_app_sources()
|
||||
{
|
||||
log=$workdir/app_sources_auto_update.log
|
||||
date >> $log
|
||||
git_pull_and_update_cron_and_restart_services_if_needed
|
||||
tools/autoupdate_app_sources/venv/bin/python3 tools/autoupdate_app_sources/autoupdate_app_sources.py \
|
||||
--edit --commit --pr --paste -j1 \
|
||||
&> $log || sendxmpppy "[appsourcesautoupdate] App sources auto-update failed miserably"
|
||||
}
|
||||
|
||||
function update_app_levels()
|
||||
{
|
||||
pushd tools/update_app_levels >/dev/null
|
||||
python3 update_app_levels.py
|
||||
popd >/dev/null
|
||||
}
|
||||
|
||||
function fetch_main_dashboard()
|
||||
{
|
||||
pushd store >/dev/null
|
||||
venv/bin/python3 fetch_main_dashboard.py 2>&1 | grep -v 'Following Github server redirection'
|
||||
popd >/dev/null
|
||||
}
|
||||
|
||||
|
||||
function fetch_level_history()
|
||||
{
|
||||
pushd store >/dev/null
|
||||
venv/bin/python3 fetch_level_history.py
|
||||
popd >/dev/null
|
||||
}
|
||||
|
||||
$1
|
11
rebuild.sh
|
@ -1,11 +0,0 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
workdir=$(realpath $(dirname "$0"))
|
||||
log=$workdir/app_list_auto_update.log
|
||||
|
||||
cd $workdir
|
||||
date >> $log
|
||||
git pull &>/dev/null
|
||||
cat cron | sed "s@__BASEDIR__@$workdir@g" > /etc/cron.d/app_list
|
||||
|
||||
./tools/list_builder.py &>> $log || sendxmpppy "[listbuilder] Rebuilding the application list failed miserably"
|
|
@ -1,13 +0,0 @@
|
|||
#!/bin/bash
|
||||
|
||||
workdir=$(realpath $(dirname "$0"))
|
||||
log=$workdir/app_sources_auto_update.log
|
||||
|
||||
cd $workdir
|
||||
date >> $log
|
||||
git pull &>/dev/null
|
||||
cat cron | sed "s@__BASEDIR__@$workdir@g" > /etc/cron.d/app_list
|
||||
|
||||
python3 tools/autoupdate_app_sources/autoupdate_app_sources.py \
|
||||
--edit --commit --pr --paste -j1 \
|
||||
&> $log || sendxmpppy "[appsourcesautoupdate] App sources auto-update failed miserably"
|
|
@ -32,6 +32,9 @@ And then start the dev server:
|
|||
```bash
|
||||
source venv/bin/activate
|
||||
FLASK_APP=app.py FLASK_ENV=development flask --debug run
|
||||
|
||||
# In another term, launch the tailwindcss process to autorebuild css:
|
||||
cd assets; ./tailwindcss-linux-x64 --input tailwind-local.css --output tailwind.css --watch
|
||||
```
|
||||
|
||||
## Translation
|
||||
|
|
75
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,72 @@ 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
|
@ -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
|
|
@ -1,11 +1,14 @@
|
|||
|
||||
# Production -> download standalone tailwind to compile only what we need
|
||||
wget https://github.com/tailwindlabs/tailwindcss/releases/download/v3.3.3/tailwindcss-linux-x64
|
||||
wget https://github.com/tailwindlabs/tailwindcss/releases/download/v3.4.3/tailwindcss-linux-x64
|
||||
chmod +x tailwindcss-linux-x64
|
||||
./tailwindcss-linux-x64 --input tailwind-local.css --output tailwind.css --minify
|
||||
|
||||
# Development -> we use the JS magic thingy
|
||||
curl -L https://cdn.tailwindcss.com?plugins=forms > tailwind-css.js
|
||||
#curl -L https://cdn.tailwindcss.com?plugins=forms > tailwind-css.js
|
||||
|
||||
# Dark theme stuff
|
||||
git clone https://github.com/jjranalli/nightwind
|
||||
|
||||
# Canvasjs (for the chart page only)
|
||||
curl -L https://cdn.canvasjs.com/ga/canvasjs.min.js > canvasjs.min.js
|
||||
|
|
|
@ -3,8 +3,8 @@
|
|||
@tailwind utilities;
|
||||
|
||||
@layer utilities {
|
||||
body {
|
||||
@apply text-gray-800;
|
||||
input, textarea, select {
|
||||
@apply !rounded-md shadow-sm !border-gray-200 !bg-neutral-50;
|
||||
}
|
||||
.btn {
|
||||
@apply text-sm font-medium rounded-md px-4 py-2 transition;
|
||||
|
|
|
@ -1,11 +1,10 @@
|
|||
/** @type {import('tailwindcss').Config} */
|
||||
module.exports = {
|
||||
content: ['../templates/*.html'],
|
||||
theme: {
|
||||
extend: {},
|
||||
},
|
||||
darkMode: 'selector',
|
||||
plugins: [
|
||||
require('@tailwindcss/forms'),
|
||||
require('./nightwind/src/index.js'),
|
||||
],
|
||||
safelist: [
|
||||
'safelisted',
|
||||
|
|
|
@ -87,8 +87,6 @@ for app, infos in catalog["apps"].items():
|
|||
if infos["state"] != "working":
|
||||
continue
|
||||
|
||||
print(app)
|
||||
|
||||
consolidated_infos[app] = {
|
||||
"public_level": infos["level"],
|
||||
"url": infos["git"]["url"],
|
||||
|
|
|
@ -82,7 +82,7 @@
|
|||
<span class="inline sm:hidden">{{ _("Demo") }}</span>
|
||||
</a>
|
||||
{% endif %}
|
||||
<a aria-label="{{ _('Install with YunoHost') }}" title="{{ _('Install with YunoHost') }}" class="h-9.5 inline-block rounded-md border p-0 bg-gray-900 text-white " href="https://install-app.yunohost.org/?app={{ app_id }}">
|
||||
<a aria-label="{{ _('Install with YunoHost') }}" title="{{ _('Install with YunoHost') }}" class="h-9.5 inline-block rounded-md border border-gray-300 p-0 bg-gray-900 dark:bg-gray-50 text-white dark:text-black" href="https://install-app.yunohost.org/?app={{ app_id }}">
|
||||
<span class="inline-block text-[11px] leading-3 text-center py-1.5 pl-2">Install<br/>with</span>
|
||||
<span class="inline-block pr-2 pt-1"><img alt="YunoHost" src="{{ url_for('static', filename='horizontal-yunohost.svg') }}"></span>
|
||||
</a>
|
||||
|
|
|
@ -12,17 +12,17 @@
|
|||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<link rel="stylesheet" href="{{ url_for('static', filename='fork-awesome.min.css') }}">
|
||||
{% if config.DEBUG %}
|
||||
<script src="{{ url_for('static', filename='tailwind-css.js') }}"></script>
|
||||
<style type="text/tailwindcss">
|
||||
{{ tailwind_local }}
|
||||
</style>
|
||||
{% else %}
|
||||
<link rel="stylesheet" href="{{ url_for('static', filename='tailwind.css') }}">
|
||||
{% endif %}
|
||||
<script>
|
||||
if (localStorage.theme === 'dark' || (!('theme' in localStorage) && window.matchMedia('(prefers-color-scheme: dark)').matches)) {
|
||||
document.documentElement.classList.add('dark')
|
||||
} else {
|
||||
document.documentElement.classList.remove('dark')
|
||||
}
|
||||
</script>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<body class="bg-neutral-50 text-gray-800">
|
||||
<header class="pb-2 shadow-sm">
|
||||
<div
|
||||
class="flex h-12 items-center gap-8 pt-2 px-4 sm:px-6 lg:px-8"
|
||||
|
@ -36,24 +36,24 @@
|
|||
<nav class="hidden md:block">
|
||||
<ul class="flex items-center gap-6 text-sm">
|
||||
<li>
|
||||
<a class="font-bold transition hover:text-gray-500/75" href="{{ url_for('browse_catalog') }}">
|
||||
<a class="font-bold transition hover:opacity-75" href="{{ url_for('browse_catalog') }}">
|
||||
{{ _("Catalog") }}
|
||||
</a>
|
||||
</li>
|
||||
|
||||
<li>
|
||||
<a class="font-bold transition hover:text-gray-500/75" href="{{ url_for('browse_wishlist') }}">
|
||||
<a class="font-bold transition hover:opacity-75" href="{{ url_for('browse_wishlist') }}">
|
||||
{{ _("Wishlist") }}
|
||||
</a>
|
||||
</li>
|
||||
{% if packaging_enabled %}
|
||||
<li>
|
||||
<a class="font-bold transition hover:text-gray-500/75" href="{{ url_for('dash') }}">
|
||||
<a class="font-bold transition hover:opacity-75" href="{{ url_for('dash') }}">
|
||||
{{ _("Packaging dashboard") }}
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a class="font-bold transition hover:text-gray-500/75" href="{{ url_for('charts') }}">
|
||||
<a class="font-bold transition hover:opacity-75" href="{{ url_for('charts') }}">
|
||||
{{ _("Charts & history") }}
|
||||
</a>
|
||||
</li>
|
||||
|
@ -70,6 +70,15 @@
|
|||
<i class="fa fa-external-link fa-fw" aria-hidden="true"></i>
|
||||
{{ _("YunoHost documentation") }}
|
||||
</a>
|
||||
<a
|
||||
class="inline-block"
|
||||
role="button"
|
||||
target="_blank"
|
||||
id="toggleDarkMode"
|
||||
>
|
||||
<i class="fa fa-sun-o inline-block dark:hidden rounded-md border border-gray-300 px-3 py-2.5 hover:bg-gray-100" aria-hidden="true" title="{{ _('Toggle light/dark mode') }}"></i>
|
||||
<i class="fa fa-moon-o hidden dark:inline-block rounded-md border border-gray-300 px-3 py-2.5 hover:bg-gray-100" aria-hidden="true" title="{{ _('Toggle light/dark mode') }}"></i>
|
||||
</a>
|
||||
{% if not user %}
|
||||
<a
|
||||
class="btn btn-primary inline-block"
|
||||
|
@ -252,14 +261,25 @@
|
|||
|
||||
<footer class="h-5 my-5 text-center">
|
||||
<p>
|
||||
{{ _("Made with <i class='text-red-500 fa fa-heart-o' aria-label='love'></i> using <a class='text-blue-800' href='https://flask.palletsprojects.com'>Flask</a> and <a class='text-blue-800' href='https://tailwindcss.com/'>TailwindCSS</a>") }}
|
||||
• <a class='text-blue-800' href='https://github.com/YunoHost/apps/tree/master/store'><i class='fa fa-code fa-fw' aria-hidden='true'></i> {{ _("Source") }}</a>
|
||||
• <a class='text-blue-800' href='https://yunohost.org/tos'>{{ _("Terms of Services") }}</a>
|
||||
{{ _("Made with <i class='text-red-500 fa fa-heart-o' aria-label='love'></i> using <a class='text-blue-800 dark:text-blue-400' href='https://flask.palletsprojects.com'>Flask</a> and <a class='text-blue-800 dark:text-blue-400' href='https://tailwindcss.com/'>TailwindCSS</a>") }}
|
||||
• <a class='text-blue-800 dark:text-blue-400' href='https://github.com/YunoHost/apps/tree/master/store'><i class='fa fa-code fa-fw' aria-hidden='true'></i> {{ _("Source") }}</a>
|
||||
• <a class='text-blue-800 dark:text-blue-400' href='https://yunohost.org/tos'>{{ _("Terms of Services") }}</a>
|
||||
</p>
|
||||
</footer>
|
||||
</body>
|
||||
|
||||
<script type="text/javascript">
|
||||
document.getElementById('toggleDarkMode').addEventListener('click', () => {
|
||||
document.documentElement.classList.toggle('dark')
|
||||
if (document.documentElement.classList.contains("dark") == true)
|
||||
{
|
||||
localStorage.theme = 'dark';
|
||||
}
|
||||
else
|
||||
{
|
||||
localStorage.theme = 'light';
|
||||
}
|
||||
});
|
||||
{% if user %}
|
||||
document.getElementById('toggleUserMenu').addEventListener('click', () => {
|
||||
document.getElementById('userMenu').classList.toggle("hidden");
|
||||
|
@ -269,5 +289,4 @@
|
|||
document.getElementById('menu').classList.toggle("hidden");
|
||||
});
|
||||
</script>
|
||||
|
||||
</html>
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
>
|
||||
<a
|
||||
href="{{ url_for('app_info', app_id=app) }}"
|
||||
class="relative block overflow-hidden rounded-lg py-2 px-4 hover:bg-gray-100 mx-2 md:mx-0"
|
||||
class="relative block overflow-hidden rounded-lg py-2 px-4 hover:bg-neutral-100 mx-2 md:mx-0"
|
||||
>
|
||||
<div class="flex justify-between gap-4">
|
||||
<div class="shrink-0">
|
||||
|
@ -27,7 +27,7 @@
|
|||
src="{{ url_for('static', filename='app_logo_placeholder.png') }}"
|
||||
{% endif %}
|
||||
loading="lazy"
|
||||
class="h-12 w-12 rounded-lg object-cover shadow-sm mt-1"
|
||||
class="h-12 w-12 rounded-lg object-cover shadow mt-1"
|
||||
>
|
||||
</div>
|
||||
<div class="w-full">
|
||||
|
@ -53,14 +53,16 @@
|
|||
</span>
|
||||
</span>
|
||||
</span>
|
||||
<p class="max-w-[40ch] text-xs text-gray-700">
|
||||
<p class="max-w-[40ch] text-xs opacity-75">
|
||||
{{ infos['manifest']['description']|localize }}
|
||||
</p>
|
||||
<div class="hidden">
|
||||
{{ infos["potential_alternative_to"]|join(', ') }}
|
||||
</div>
|
||||
{% if infos['category'] %}
|
||||
<span class="rounded-full px-2.5 py-0.5 text-[10px] border text-{{ catalog['categories'][infos['category']]['color'] }}-600 border-{{ catalog['categories'][infos['category']]['color'] }}-400 ">
|
||||
<span class="rounded-full px-2.5 py-0.5 text-[10px] border
|
||||
text-{{ catalog['categories'][infos['category']]['color'] }}-600
|
||||
border-{{ catalog['categories'][infos['category']]['color'] }}-400 ">
|
||||
{{ catalog['categories'][infos['category']]['title']|localize|lower }}
|
||||
</span>
|
||||
{% endif %}
|
||||
|
@ -90,7 +92,7 @@
|
|||
id="search"
|
||||
placeholder="{{ _('Search for…') }}"
|
||||
{% if request.args.get("search") %}value="{{ request.args.get("search") }}"{% endif %}
|
||||
class="w-full rounded-md border-gray-200 shadow-sm sm:text-sm py-2 pe-10"
|
||||
class="w-full sm:text-sm py-2 pe-10"
|
||||
>
|
||||
|
||||
<span class="absolute inset-y-0 end-0 grid w-10 place-content-center pr-4">
|
||||
|
@ -102,7 +104,7 @@
|
|||
<select
|
||||
name="selectcategory"
|
||||
id="selectcategory"
|
||||
class="w-full rounded-md border-gray-200 shadow-sm sm:test-sm px-2 py-1.5"
|
||||
class="w-full sm:text-sm px-2 py-1.5"
|
||||
>
|
||||
<option value="">{{ _("All apps") }}</option>
|
||||
{% for id, category in catalog['categories'].items() %}
|
||||
|
@ -118,14 +120,14 @@
|
|||
<select
|
||||
name="selectsort"
|
||||
id="selectsort"
|
||||
class="inline-block rounded-md border-gray-200 text-sm ml-1 pl-1 pr-7 h-8 py-0"
|
||||
class="inline-block text-sm ml-1 pl-1 pr-7 h-8 py-0"
|
||||
>
|
||||
<option {% if request.args.get("sort") in [None, "popularity"] %}selected{% endif %} value="popularity">{{ _("Popularity") }}</option>
|
||||
<option {% if request.args.get("sort") == "newest" %}selected{% endif %} value="newest">{{ _("Newest") }}</option>
|
||||
<option {% if request.args.get("sort") == "alpha" %}selected{% endif %} value="alpha">{{ _("Alphabetical") }}</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="inline-block flex items-center px-2 pt-2 md:pt-0 {% if not user %}text-gray-500{% endif %}" {% if not user %}title="{{ _('Requires to be logged-in') }}" aria-label="{{ _('Requires to be logged-in') }}"{% endif %}>
|
||||
<div class="inline-block flex items-center px-2 pt-2 md:pt-0 {% if not user %}opacity-75{% endif %}" {% if not user %}title="{{ _('Requires to be logged-in') }}" aria-label="{{ _('Requires to be logged-in') }}"{% endif %}>
|
||||
<label for="starsonly" class="inline-block relative mr-2 h-4 w-7 cursor-pointer">
|
||||
<span class="sr-only">{{ _("Show only apps you starred") }}</span>
|
||||
<input type="checkbox" id="starsonly" class="peer sr-only" {% if user and request.args.get("starsonly") %}checked{% endif %} {% if not user%}disabled{% endif %} >
|
||||
|
|
|
@ -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>
|
||||
|
@ -54,6 +59,12 @@
|
|||
<script>
|
||||
window.onload = function () {
|
||||
|
||||
var theme = "light1";
|
||||
if (document.documentElement.classList.contains("dark") == true)
|
||||
{
|
||||
theme = "dark1";
|
||||
}
|
||||
|
||||
var colors_per_level = [
|
||||
"#d9534f",
|
||||
"#E26D4F",
|
||||
|
@ -68,6 +79,8 @@ window.onload = function () {
|
|||
];
|
||||
|
||||
new CanvasJS.Chart("levelRing", {
|
||||
backgroundColor: 'transparent',
|
||||
theme: theme,
|
||||
animationEnabled: false,
|
||||
data: [{
|
||||
type: "doughnut",
|
||||
|
@ -93,6 +106,8 @@ window.onload = function () {
|
|||
|
||||
|
||||
new CanvasJS.Chart("levelHistory", {
|
||||
backgroundColor: 'transparent',
|
||||
theme: theme,
|
||||
animationEnabled: false,
|
||||
toolTip: {
|
||||
reversed: true,
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
{% endblock %}
|
||||
{% block main %}
|
||||
|
||||
<div class="mx-auto w-full text-center p-8">
|
||||
<div class="mx-auto w-full text-center px-4 py-8">
|
||||
<h1 class="text-2xl font-bold">
|
||||
{{ _("App packaging dashboard") }}
|
||||
</h1>
|
||||
|
@ -61,13 +61,13 @@
|
|||
</div>
|
||||
|
||||
<table id="appTable" class="mx-auto">
|
||||
<tr class="h-20">
|
||||
<th class="w-32">{{ _("App") }}</th>
|
||||
<th class="-rotate-45 w-16 text-left">{{ _("Catalog") }}</th>
|
||||
<th class="-rotate-45 w-16 text-left">{{ _("Main CI") }}</th>
|
||||
<th class="-rotate-45 w-16 text-left">{{ _("Bookworm CI") }}</th>
|
||||
<th class="-rotate-45 w-16 text-left">{{ _("Testing PR") }}</th>
|
||||
<th class="-rotate-45 w-16 text-left">{{ _("Autoupdate PR") }}</th>
|
||||
<tr class="h-40 md:h-20">
|
||||
<th class="max-w-20 md:max-w-32">{{ _("App") }}</th>
|
||||
<th class="-rotate-90 md:-rotate-45 max-w-10 md:max-w-16 text-left text-nowrap">{{ _("Catalog") }}</th>
|
||||
<th class="-rotate-90 md:-rotate-45 max-w-10 md:max-w-16 text-left text-nowrap">{{ _("Main CI") }}</th>
|
||||
<th class="-rotate-90 md:-rotate-45 max-w-10 md:max-w-16 text-left text-nowrap">{{ _("Bookworm CI") }}</th>
|
||||
<th class="-rotate-90 md:-rotate-45 max-w-10 md:max-w-16 text-left text-nowrap">{{ _("Testing PR") }}</th>
|
||||
<th class="-rotate-90 md:-rotate-45 max-w-10 md:max-w-16 text-left text-nowrap">{{ _("Autoupdate PR") }}</th>
|
||||
<th></th>
|
||||
</tr>
|
||||
{% for app, infos in data.items() %}
|
||||
|
@ -93,9 +93,9 @@
|
|||
data-last-update-autoupdate-daysago="{% if infos["ci-auto-update"] %}{{ infos["ci-auto-update"]["timestamp_updated"] | days_ago }}{% endif %}"
|
||||
data-packaging-format="{{ infos["packaging_format"] }}"
|
||||
>
|
||||
<td class="text-center text-blue-600 font-medium"><a href="{{ infos["url"] }}">{{ app }}</a></td>
|
||||
<td class="max-w-40 md:max-w-64 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 %}
|
||||
|
@ -106,8 +106,12 @@
|
|||
</a>
|
||||
</td>
|
||||
<td>
|
||||
<a class="{% if infos["ci_results"]["main"]["timestamp"] | days_ago > 30 %}opacity-50{% endif %}" href="https://ci-apps.yunohost.org/ci/apps/{{ app }}/">
|
||||
{{ infos["ci_results"]["main"]["level"] }}
|
||||
<a class="{% if infos["public_level"] == infos["ci_results"]["main"]["level"] or infos["ci_results"]["main"]["timestamp"] | days_ago > 30 %}opacity-50{% endif %}" href="https://ci-apps.yunohost.org/ci/apps/{{ app }}/">
|
||||
{% if infos["public_level"] == infos["ci_results"]["main"]["level"] %}
|
||||
=
|
||||
{% else %}
|
||||
{{ infos["ci_results"]["main"]["level"] }}
|
||||
{% endif %}
|
||||
{% if infos["ci_results"]["main"]["timestamp"] | days_ago > 30 %}
|
||||
<i class="fa fa-hourglass-o" title="{{ _("Outdated test (%(days)s days ago)", days=infos["ci_results"]["main"]["timestamp"] | days_ago) }}"></i>
|
||||
{% endif %}
|
||||
|
@ -120,9 +124,13 @@
|
|||
</a>
|
||||
</td>
|
||||
<td>
|
||||
<a class="{% if infos["ci_results"]["nextdebian"] and infos["ci_results"]["nextdebian"]["timestamp"] | days_ago > 30 %}opacity-50{% endif %}" href="https://ci-apps-bookworm.yunohost.org/ci/apps/{{ app }}/">
|
||||
<a class="{% if infos["ci_results"]["nextdebian"] and ((infos["public_level"] == infos["ci_results"]["nextdebian"]["level"]) or (infos["ci_results"]["nextdebian"]["timestamp"] | days_ago) > 30) %}opacity-50{% endif %}" href="https://ci-apps-bookworm.yunohost.org/ci/apps/{{ app }}/">
|
||||
{% if infos["ci_results"]["nextdebian"] %}
|
||||
{{ infos["ci_results"]["nextdebian"]["level"] }}
|
||||
{% if infos["public_level"] == infos["ci_results"]["nextdebian"]["level"] %}
|
||||
=
|
||||
{% else %}
|
||||
{{ infos["ci_results"]["nextdebian"]["level"] }}
|
||||
{% endif %}
|
||||
{% if infos["ci_results"]["nextdebian"]["timestamp"] | days_ago > 30 %}
|
||||
<i class="fa fa-hourglass-o" title="{{ _("Outdated test (%(days)s days ago)", days=infos["ci_results"]["nextdebian"]["timestamp"] | days_ago) }}"></i>
|
||||
{% endif %}
|
||||
|
@ -143,7 +151,7 @@
|
|||
<i class="fa fa-flask"></i>
|
||||
{% for s in infos["testing"]["statuses"] %}
|
||||
{% if s["context"] == "ci-apps-dev" %}
|
||||
<i class="fa fa-{% if s["state"] == "success" %}check-circle text-green-600{% else %}times-circle text-red-600{% endif %}"></i>
|
||||
<i class="fa fa-{% if s["state"] == "success" %}check-circle text-green-600{% else %}times-circle text-red-500{% endif %}"></i>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
{% if infos["testing"]["timestamp_updated"] | days_ago > 30 %}
|
||||
|
@ -158,7 +166,7 @@
|
|||
<i class="fa fa-arrow-up"></i>
|
||||
{% for s in infos["ci-auto-update"]["statuses"] %}
|
||||
{% if s["context"] == "ci-apps-dev" %}
|
||||
<i class="fa fa-{% if s["state"] == "success" %}check-circle text-green-600{% else %}times-circle text-red-600{% endif %}"></i>
|
||||
<i class="fa fa-{% if s["state"] == "success" %}check-circle text-green-600{% else %}times-circle text-red-500{% endif %}"></i>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
{% if infos["ci-auto-update"]["timestamp_updated"] | days_ago > 30 %}
|
||||
|
@ -256,7 +264,7 @@
|
|||
}
|
||||
else if (filterName == "regressions_bookworm")
|
||||
{
|
||||
if ((entries[i].dataset.publicLevel >= 6) && (entries[i].dataset.nextdebianCiLevel < 6))
|
||||
if ((entries[i].dataset.publicLevel >= 6) && (entries[i].dataset.nextdebianCiLevel < 6) && (entries[i].dataset.nextdebianCiLevel != entries[i].dataset.mainCiLevel))
|
||||
{
|
||||
entries[i].classList.remove("hidden");
|
||||
nb_found++;
|
||||
|
|
|
@ -5,14 +5,14 @@
|
|||
{% block main %}
|
||||
|
||||
<div class="mx-auto w-full text-center p-8">
|
||||
<img alt="YunoHost logo" src="{{ url_for('static', filename='ynh_logo_black.svg') }}" class="w-32 mx-auto">
|
||||
<img alt="YunoHost logo" src="{{ url_for('static', filename='ynh_logo_black.svg') }}" class="w-32 mx-auto dark:invert">
|
||||
<h1 class="text-2xl font-bold">
|
||||
{{ _("Application Store") }}
|
||||
</h1>
|
||||
</div>
|
||||
|
||||
<div class="grid grid-cols-1 gap-4 sm:grid-cols-2 md:grid-cols-3 max-w-screen-lg mx-auto pt-5">
|
||||
<div class="text-center border rounded-lg h-32 mx-3 sm:mx-0">
|
||||
<div class="text-center border rounded-lg h-32 mx-3 sm:mx-0 border-gray-200">
|
||||
<a
|
||||
href="{{ url_for('browse_catalog') }}"
|
||||
class="h-full relative block overflow-hidden hover:bg-gray-200 pt-12"
|
||||
|
@ -23,7 +23,7 @@
|
|||
</a>
|
||||
</div>
|
||||
{% for id, category in catalog['categories'].items() %}
|
||||
<div class="text-center border rounded-lg h-32 mx-3 sm:mx-0">
|
||||
<div class="text-center border rounded-lg h-32 mx-3 sm:mx-0 border-gray-200">
|
||||
<a
|
||||
href="{{ url_for('browse_catalog', category=id) }}"
|
||||
class="h-full relative block overflow-hidden hover:bg-gray-200 pt-10"
|
||||
|
@ -32,7 +32,7 @@
|
|||
<i class="fa fa-{{ category['icon'] }}" aria-hidden="true"></i>
|
||||
{{ category['title']|localize }}
|
||||
</h2>
|
||||
<p class="mx-auto max-w-[40ch] text-xs text-gray-500">
|
||||
<p class="mx-auto max-w-[40ch] text-xs opacity-75">
|
||||
{{ category['description']|localize }}
|
||||
</p>
|
||||
</a>
|
||||
|
|
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', _external=True)}}</link>
|
||||
<atom:link href="{{ url_for('news_rss', _external=True)}}" 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") %}
|
||||
{%- for app, url in news[status] %}
|
||||
{% set manifest = catalog["apps"].get(app, {}).get("manifest", {}) %}
|
||||
<item>
|
||||
<title>[{{ status|capitalize }}] {% if manifest %}{{ manifest['name'] }}{% else %}{{ app }}{% endif %}</title>
|
||||
<link>{{ url_for('app_info', app_id=app, _external=True) }}</link>
|
||||
<guid isPermaLink="false">{{ app }}#{{ date|format_datetime("%Y%m%d") }}</guid>
|
||||
<pubDate>{{ date|format_datetime("%a, %d %b %Y %H:%M:%S +0000") }}</pubDate>
|
||||
<description>{{ manifest.get("description", {}).get("en") }}</description>
|
||||
<content:encoded>{{ manifest.get("description", {}).get("en") }}</content:encoded>
|
||||
</item>
|
||||
{% endfor -%}
|
||||
{% endfor -%}
|
||||
{% endfor %}
|
||||
</channel>
|
||||
</rss>
|
|
@ -7,22 +7,22 @@
|
|||
<h1 class="text-2xl font-bold">
|
||||
{{ _("Application Wishlist") }}
|
||||
</h1>
|
||||
<p class="text-sm text-gray-700 mx-10 mt-2">{{ _("The wishlist is the place where people can collectively suggest and vote for apps that they would like to see packaged and made available in YunoHost's official apps catalog. Nevertheless, the fact that apps are listed here should by no mean be interpreted as a fact that the YunoHost project plans to integrate it, and is merely a source of inspiration for packaging volunteers.") }}</p>
|
||||
<p class="text-sm opacity-75 mx-10 mt-2">{{ _("The wishlist is the place where people can collectively suggest and vote for apps that they would like to see packaged and made available in YunoHost's official apps catalog. Nevertheless, the fact that apps are listed here should by no mean be interpreted as a fact that the YunoHost project plans to integrate it, and is merely a source of inspiration for packaging volunteers.") }}</p>
|
||||
</div>
|
||||
|
||||
<div class="max-w-screen-md mx-auto mt-3 mb-3">
|
||||
<div class="flex flex-col md:flex-row items-center">
|
||||
<div class="px-2 inline-block relative basis-2/3 text-gray-700">
|
||||
<div class="px-2 inline-block relative basis-2/3">
|
||||
<label for="search" class="sr-only"> {{ _("Search") }} </label>
|
||||
|
||||
<input
|
||||
type="text"
|
||||
id="search"
|
||||
placeholder="{{ _('Search for…') }}"
|
||||
class="w-full rounded-md border-gray-200 shadow-sm sm:text-sm py-2 pe-10"
|
||||
class="w-full sm:text-sm py-2 pe-10"
|
||||
>
|
||||
|
||||
<span class="absolute inset-y-0 end-0 grid w-10 place-content-center pr-4">
|
||||
<span class="absolute inset-y-0 end-0 grid w-10 place-content-center pr-4 opacity-75">
|
||||
<i class="fa fa-search" aria-hidden="true"></i>
|
||||
</span>
|
||||
</div>
|
||||
|
@ -40,13 +40,13 @@
|
|||
<select
|
||||
name="selectsort"
|
||||
id="selectsort"
|
||||
class="inline-block rounded-md border-gray-200 text-sm ml-1 pl-1 pr-7 h-8 py-0"
|
||||
class="inline-block text-sm ml-1 pl-1 pr-7 h-8 py-0"
|
||||
>
|
||||
<option {% if request.args.get("sort") in [None, "popularity"] %}selected{% endif %} value="popularity">{{ _("Popularity") }}</option>
|
||||
<option {% if request.args.get("sort") == "alpha" %}selected{% endif %} value="alpha">{{ _("Alphabetical") }}</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="inline-block flex items-center px-2 pt-2 md:pt-0 {% if not user %}text-gray-500{% endif %}" {% if not user %}title="{{ _('Requires to be logged-in') }}" aria-label="{{ _('Requires to be logged-in') }}"{% endif %}>
|
||||
<div class="inline-block flex items-center px-2 pt-2 md:pt-0 {% if not user %}opacity-75{% endif %}" {% if not user %}title="{{ _('Requires to be logged-in') }}" aria-label="{{ _('Requires to be logged-in') }}"{% endif %}>
|
||||
<label for="starsonly" class="inline-block relative mr-2 h-4 w-7 cursor-pointer">
|
||||
<span class="sr-only">{{ _("Show only apps you starred") }}</span>
|
||||
<input type="checkbox" id="starsonly" class="peer sr-only" {% if user and request.args.get("starsonly") %}checked{% endif %} {% if not user%}disabled{% endif %}>
|
||||
|
@ -64,7 +64,7 @@
|
|||
</div>
|
||||
|
||||
<div class="overflow-x-auto max-w-screen-lg mx-auto pt-5">
|
||||
<table class="min-w-full divide-y-2 divide-gray-200 bg-white text-sm">
|
||||
<table class="min-w-full divide-y-2 divide-gray-100 dark:divide-gray-700 text-sm">
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="hidden sm:table-cell whitespace-nowrap px-4 py-2 font-medium">
|
||||
|
@ -79,7 +79,7 @@
|
|||
</tr>
|
||||
</thead>
|
||||
|
||||
<tbody id="wishlist" class="divide-y divide-gray-200">
|
||||
<tbody id="wishlist" class="divide-y divide-gray-100 dark:divide-gray-700">
|
||||
{% for app, infos in wishlist.items() %}
|
||||
{% set this_app_stars = stars.get(app, {})|length %}
|
||||
{% if user %}
|
||||
|
@ -95,7 +95,7 @@
|
|||
<td class="inline-block sm:table-cell px-4 py-2 font-bold sm:max-w-[10em]">
|
||||
{{ infos['name'] }}
|
||||
</td>
|
||||
<td class="block sm:table-cell px-4 py-0 sm:py-2 text-gray-700 max-w-md">{{ infos['description'] }}</td>
|
||||
<td class="block sm:table-cell px-4 py-0 sm:py-2 opacity-75 max-w-md">{{ infos['description'] }}</td>
|
||||
<td class="float-right sm:float-none sm:table-cell py-2 px-1 sm:px-0">
|
||||
{% if infos['website'] %}
|
||||
<a
|
||||
|
@ -105,7 +105,7 @@
|
|||
class="inline-block"
|
||||
target="_blank"
|
||||
>
|
||||
<i class="fa fa-globe rounded-md border px-3 py-2 hover:bg-gray-100" aria-hidden="true"></i>
|
||||
<i class="fa fa-globe rounded-md border border-gray-300 px-3 py-2 hover:bg-gray-100" aria-hidden="true"></i>
|
||||
</a>
|
||||
{% endif %}
|
||||
</td>
|
||||
|
@ -118,7 +118,7 @@
|
|||
class="inline-block"
|
||||
target="_blank"
|
||||
>
|
||||
<i class="fa fa-code rounded-md border px-3 py-2 hover:bg-gray-100" aria-hidden="true"></i>
|
||||
<i class="fa fa-code rounded-md border border-gray-300 px-3 py-2 hover:bg-gray-100" aria-hidden="true"></i>
|
||||
</a>
|
||||
{% endif %}
|
||||
</td>
|
||||
|
|
|
@ -59,21 +59,21 @@
|
|||
<input name="csrf_token" type="text" class="hidden" value="{{ csrf_token }}" >
|
||||
|
||||
<label for="name" class="mt-5 block font-bold text-gray-700">{{ _("Name") }}</label>
|
||||
<input name="name" type="text" class="w-full mt-1 rounded-md border-gray-200 text-gray-700 shadow-sm" maxlength="30" required onkeyup="this.value = this.value.replace(/[^a-zA-Z0-9.-\\(\\)\\ ]/, '')" >
|
||||
<input name="name" type="text" class="w-full mt-1" maxlength="30" required onkeyup="this.value = this.value.replace(/[^a-zA-Z0-9.-\\(\\)\\ ]/, '')" >
|
||||
|
||||
<label for="description" class="mt-5 block font-bold text-gray-700">{{ _("App's description") }}</label>
|
||||
<textarea name="description" type="text" class="w-full mt-1 rounded-md border-gray-200 text-gray-700 shadow-sm" required rows='3' maxlength='100'></textarea>
|
||||
<span class="text-xs text-gray-600"><span class="font-bold">{{ _("Please be concise and focus on what the app does.") }}</span> {{ _("No need to repeat '[App] is …'. No need to state that it is free/open-source or self-hosted (otherwise it wouldn't be packaged for YunoHost). Avoid marketing stuff like 'the most', or vague properties like 'easy', 'simple', 'lightweight'.") }}</span>
|
||||
|
||||
<label for="upstream" class="mt-5 block font-bold text-gray-700">{{ _("Project code repository") }}</label>
|
||||
<input name="upstream" type="url" class="w-full mt-1 rounded-md border-gray-200 text-gray-700 shadow-sm" maxlength="150" required >
|
||||
<input name="upstream" type="url" class="w-full mt-1" maxlength="150" required >
|
||||
|
||||
<label for="license" class="mt-5 block font-bold text-gray-700">{{ _("Link to the project's LICENSE") }}</label>
|
||||
<input name="license" type="url" class="w-full mt-1 rounded-md border-gray-200 text-gray-700 shadow-sm" required maxlength="250"></input>
|
||||
<input name="license" type="url" class="w-full mt-1" required maxlength="250"></input>
|
||||
<span class="text-xs text-gray-600 font-bold">{{ _("The YunoHost project will only package free/open-source software (with possible case-by-case exceptions for apps which are not-totally-free)") }}</span>
|
||||
|
||||
<label for="website" class="mt-5 block font-bold text-gray-700">{{ _("Project website") }}</label>
|
||||
<input name="website" type="url" class="w-full mt-1 rounded-md border-gray-200 text-gray-700 shadow-sm" maxlength="150" >
|
||||
<input name="website" type="url" class="w-full mt-1" maxlength="150" >
|
||||
<span class="text-xs text-gray-600">{{ _("Please *do not* just copy-paste the code repository URL. If the project has no proper website, then leave the field empty.") }}</span>
|
||||
|
||||
<button
|
||||
|
|
|
@ -331,6 +331,14 @@ class AppAutoUpdater:
|
|||
continue
|
||||
tags_dict[tag_as_ints] = (tag, tag_clean)
|
||||
|
||||
if app_id == "focalboard":
|
||||
# Stupid ad-hoc patch for focalboard where 7.11.4 doesn't have the proper asset
|
||||
# because idk it was just a patch for mattermost or something
|
||||
if "v7.11.4" in tags_dict:
|
||||
del tags_dict["v7.11.4"]
|
||||
if "7.11.4" in tags_dict:
|
||||
del tags_dict["7.11.4"]
|
||||
|
||||
# sorted will sort by keys, tag_as_ints
|
||||
# reverse=True will set the last release as first element
|
||||
tags_dict = dict(sorted(tags_dict.items(), reverse=True))
|
||||
|
|
|
@ -37,7 +37,7 @@ class GithubAPI:
|
|||
|
||||
def releases(self) -> list[dict[str, Any]]:
|
||||
"""Get a list of releases for project."""
|
||||
return self.internal_api(f"repos/{self.upstream_repo}/releases")
|
||||
return self.internal_api(f"repos/{self.upstream_repo}/releases?per_page=100")
|
||||
|
||||
def url_for_ref(self, ref: str, ref_type: RefType) -> str:
|
||||
"""Get a URL for a ref."""
|
||||
|
|
|
@ -8,7 +8,7 @@ msgstr ""
|
|||
"Project-Id-Version: PROJECT VERSION\n"
|
||||
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
|
||||
"POT-Creation-Date: 2024-03-31 19:33+0200\n"
|
||||
"PO-Revision-Date: 2024-05-10 15:59+0000\n"
|
||||
"PO-Revision-Date: 2024-05-11 11:36+0000\n"
|
||||
"Last-Translator: rosbeef andino <ra@3cmr.fr>\n"
|
||||
"Language-Team: Spanish <https://translate.yunohost.org/projects/yunohost/"
|
||||
"readme-generator/es/>\n"
|
||||
|
@ -17,7 +17,7 @@ msgstr ""
|
|||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=2; plural=n != 1;\n"
|
||||
"X-Generator: Weblate 5.3.1\n"
|
||||
"X-Generator: Weblate 5.4.3\n"
|
||||
"Generated-By: Babel 2.14.0\n"
|
||||
|
||||
#: templates/ALL_README.md.j2:11
|
||||
|
@ -226,7 +226,7 @@ msgstr ""
|
|||
|
||||
#: templates/README.md.j2:83
|
||||
msgid "To try the `testing` branch, please proceed like that:"
|
||||
msgstr ""
|
||||
msgstr "Para probar la rama `testing`, sigue asÍ:"
|
||||
|
||||
#: templates/README.md.j2:87
|
||||
msgid "or"
|
||||
|
|
|
@ -33,6 +33,7 @@ upstream = "https://gitlab.com/hanklank/amara-archive"
|
|||
website = "https://amara.org"
|
||||
added_date = 1695656621 # 2023/09/25
|
||||
|
||||
|
||||
[amusewiki]
|
||||
name = "Amusewiki"
|
||||
description = "A library-oriented wiki engine and a powerful authoring, archiving and publishing platform."
|
||||
|
@ -75,6 +76,14 @@ upstream = "https://github.com/archivesspace/archivesspace"
|
|||
website = "https://archivesspace.org/"
|
||||
added_date = 1695656621 # 2023/09/25
|
||||
|
||||
|
||||
[argos-panopts]
|
||||
name = "Argos Panopts"
|
||||
description = "A monitoring and status board for your websites."
|
||||
upstream = "https://framagit.org/framasoft/framaspace/argos/"
|
||||
website = "https://framasoft.frama.io/framaspace/argos/"
|
||||
added_date = 1715934490 # 2024/05/17
|
||||
|
||||
[asqatasun]
|
||||
name = "Asqatasun"
|
||||
description = "Website analyser for web accessibility and SEO"
|
||||
|
@ -625,6 +634,14 @@ upstream = "https://github.com/forem/selfhost"
|
|||
website = "https://www.forem.com/"
|
||||
added_date = 1695656621 # 2023/09/25
|
||||
|
||||
|
||||
[formbricks]
|
||||
name = "Formbricks"
|
||||
description = "Experience Management Suite / Survey Platform"
|
||||
upstream = "https://github.com/formbricks/formbricks"
|
||||
website = "https://formbricks.com/"
|
||||
added_date = 1715531786 # 2024/05/12
|
||||
|
||||
[fractale]
|
||||
name = "Fractale"
|
||||
description = "Platform for self-organization."
|
||||
|
@ -1286,6 +1303,14 @@ upstream = "https://github.com/samuelclay/NewsBlur"
|
|||
website = "https://www.newsblur.com"
|
||||
added_date = 1695656621 # 2023/09/25
|
||||
|
||||
|
||||
[noe]
|
||||
name = "NOE"
|
||||
description = "Votre QG événementiel pour gérer votre planning de formations, votre bénévolat et vos participant.es"
|
||||
upstream = "https://gitlab.com/alternatiba/noe"
|
||||
website = "https://get.noe-app.io"
|
||||
added_date = 1715531830 # 2024/05/12
|
||||
|
||||
[nostr]
|
||||
name = "Nostr"
|
||||
description = "Censorship-resistant alternative to Twitter"
|
||||
|
@ -1514,6 +1539,13 @@ upstream = "https://github.com/pretix"
|
|||
website = "https://pretix.eu/about/en/"
|
||||
added_date = 1696008732 # 2023/09/29
|
||||
|
||||
[pritunl]
|
||||
name = "pritunl"
|
||||
description = "Distributed enterprise vpn server built using the OpenVPN protocol"
|
||||
upstream = "https://github.com/pritunl/pritunl"
|
||||
website = "https://pritunl.com/"
|
||||
added_date = 1715531577 # 2024/05/12
|
||||
|
||||
[privategpt]
|
||||
name = "PrivateGPT"
|
||||
description = "AI project that allows you to ask questions to your documents using the power of LLMs."
|
||||
|
@ -1751,7 +1783,6 @@ upstream = "https://github.com/simple-login/app"
|
|||
website = "https://simplelogin.io"
|
||||
added_date = 1695656621 # 2023/09/25
|
||||
|
||||
|
||||
[slskd]
|
||||
name = "Slskd"
|
||||
description = "A modern client-server application for the Soulseek file sharing network."
|
||||
|
@ -2164,6 +2195,14 @@ upstream = "https://github.com/yggdrasil-network/yggdrasil-go"
|
|||
website = "https://yggdrasil-network.github.io/"
|
||||
added_date = 1695656621 # 2023/09/25
|
||||
|
||||
|
||||
[yolo-jukebox]
|
||||
name = "Yolo jukebox"
|
||||
description = "comeoninternet.ogg"
|
||||
upstream = "https://framagit.org/framasoft/fun/yolo-cowboy"
|
||||
website = ""
|
||||
added_date = 1715698221 # 2024/05/14
|
||||
|
||||
[your-spotify]
|
||||
name = "your_spotify"
|
||||
description = "Spotify tracking dashboard"
|
||||
|
|