diff --git a/.github/workflows/added_dates.yml b/.github/workflows/added_dates.yml index 49a2544d..6a32fd44 100644 --- a/.github/workflows/added_dates.yml +++ b/.github/workflows/added_dates.yml @@ -12,6 +12,7 @@ jobs: - uses: actions/checkout@v4 with: fetch-depth: 0 + token: ${{ secrets.YUNOHOST_BOT_TOKEN }} - name: Set up Python 3.11 uses: actions/setup-python@v5 with: @@ -30,3 +31,6 @@ jobs: with: commit_message: "Automatically add dates to the catalog files" file_pattern: 'apps.toml wishlist.toml graveyard.toml' + commit_user_name: yunohost-bot + commit_user_email: yunohost-bot@users.noreply.github.com + commit_author: 'yunohost-bot ' diff --git a/README.md b/README.md index d756dd53..4152e7f5 100644 --- a/README.md +++ b/README.md @@ -31,16 +31,17 @@ them such as their category or maintenance state. This file is regularly read by To add your application to the catalog: -* Fork [this repository](https://github.com/YunoHost/apps) -* Edit the [`apps.toml`](/apps.toml) file - * Add your app's ID and git information at the right alphabetical place - * Indicate the app's functioning state: `notworking`, `inprogress`, or `working` - * Indicate the app category, which you can pick from `categories.toml` - * Indicate any anti-feature that your app may be subject to, see `antifeatures.toml` (or remove the `antifeatures` key if there's none) - * Indicate if your app can be thought of as an alternative to popular proprietary services (or remove the `potential_alternative_to` key if there's none) - * *Do not* add the `level` entry by yourself. Our automatic test suite ("the CI") will handle it. -* Commit and push your modifications to your repository -* Create a [Pull Request](https://github.com/YunoHost/apps/pulls/) +- Fork [this repository](https://github.com/YunoHost/apps) +- Edit the [`apps.toml`](/apps.toml) file + - Add your app's ID and git information at the right alphabetical place + - Indicate the app's functioning state: `notworking`, `inprogress`, or `working` + - Indicate the app category, which you can pick from `categories.toml` + - Indicate any anti-feature that your app may be subject to, see `antifeatures.toml` (or remove the `antifeatures` key if there's none) + - Indicate if your app can be thought of as an alternative to popular proprietary services (or remove the `potential_alternative_to` key if there's none) + - *Do not* add the `level` entry by yourself. Our automatic test suite ("the CI") will handle it. +- Add the app's logo inside the `logos` folder. Please keep this logo as small as possible. It also must be square (or almost square). The filename must be the name of the app in lower case. +- Commit and push your modifications to your repository +- Create a [Pull Request](https://github.com/YunoHost/apps/pulls/) App example addition: diff --git a/antifeatures.toml b/antifeatures.toml index 9dbb1156..76ae4adc 100644 --- a/antifeatures.toml +++ b/antifeatures.toml @@ -78,14 +78,14 @@ title.fr = "Application non maintenue " title.it = "Applicazione non mantenuta" [package-not-maintained] -description.en = "This YunoHost package is not maintained and needs adoption." -description.eu = "Pakete honek ez du mantenduko duenik, boluntario baten beharra dauka." -description.fr = "Ce package YunoHost n'est plus maintenu et doit être adopté." -description.it = "Questo pacchetto di YunoHost non è più mantenuto e necessita di essere adottato." +description.en = "This YunoHost package is not actively maintained and needs adoption. This means that minimal maintenance is made by volunteers who don't use the app, so you should expect the app to lose reliability over time. You can [learn how to package](https://yunohost.org/packaging_apps_intro) if you'd like to adopt it." +description.eu = "YunoHost pakete honek ez du mantenduko duenik, bere gain hartuko duen norbaiten beharra dauka. Honek esan nahi duena da mantentze-lanak minimoak izango direla eta aplikazioa erabiltzen ez duten boluntarioek egingo dituztela lanok; denborak aurrera egin ahala fidagarri izateari utziko dio. [Aplikazioak nola paketatu](https://yunohost.org/packaging_apps_intro) ikas dezakezu, zure gain hartu nahi baduzu." +description.fr = "Ce package YunoHost n'est pas activement maintenu et a besoin d'être adopté. Cela veut dire que la maintenance minimale est réalisée par des bénévoles qui n'utilisent pas l'application, il faut donc s'attendre à ce que l'app perde en fiabilité avec le temps. Vous pouvez [apprendre comment packager](https://yunohost.org/packaging_apps_intro) si vous voulez l'adopter." +description.it = "Questo pacchetto YunoHost non viene mantenuto attivamente e deve essere adottato. Ciò significa che la manutenzione minima è effettuata da volontari che non usano l'applicazione, quindi ci si deve aspettare che l'applicazione perda affidabilità nel tempo. È possibile [imparare a pacchettizzare](https://yunohost.org/packaging_apps_intro) se si desidera adottarla." icon = "user-times" title.en = "Package not maintained" title.eu = "Mantendu gabeko paketea" -title.fr = "Paquet non maintenu " +title.fr = "Package non maintenu " title.it = "Pacchetto non mantenuto" [paid-content] @@ -133,7 +133,7 @@ title.fr = "Logiciel en version alpha " title.it = "Software in versione alpha" [not-totally-free-upstream] -description.en = "The packaged app is under an overall free licence, but with clauses that restrict its use." +description.en = "The packaged app is under an overall free license, but with clauses that may restrict its use." description.eu = "Aplikazioak lizentzia librea du orokorrean, baina bere erabilera mugatzen duten klausulekin." description.fr = "L'application packagée est sous une licence globalement libre, mais avec des clauses qui pourraient restreindre son utilisation." description.it = "Quest’applicazione è protetta da licenza generalmente libera, ma con delle clausole che potrebbero limitare il suo utilizzo." @@ -144,7 +144,7 @@ title.fr = "Application sous licence libre restreinte " title.it = "Applicazione con licenza parzialmente libera" [not-totally-free-package] -description.en = "The YunoHost package of this app is under an overall free licence, but with clauses that restrict its use." +description.en = "The YunoHost package of this app is under an overall free license, but with clauses that may restrict its use." description.eu = "Aplikazio honen YunoHost paketeak lizentzia librea du orokorrean, baina bere erabilera mugatzen duten klausulekin." description.fr = "Le package YunoHost de cette application est sous une licence globalement libre, mais avec des clauses qui pourraient restreindre son utilisation." icon = "archive" diff --git a/apps.toml b/apps.toml index 84ede6dc..35a46a59 100644 --- a/apps.toml +++ b/apps.toml @@ -49,7 +49,7 @@ url = "https://github.com/YunoHost-Apps/acropolis_ynh" [actual] added_date = 1685962455 # 2023/06/05 category = "productivity_and_management" -level = 7 +level = 8 potential_alternative_to = [ "Bankin", "Budgea", "Linxo", "Microsoft Money", "Mint", "You Need A Budget" ] state = "working" subtags = [ "accounting" ] @@ -173,7 +173,7 @@ url = "https://github.com/YunoHost-Apps/audiobookshelf_ynh" [autobrr] added_date = 1681591997 # 2023/04/15 category = "multimedia" -level = 7 +level = 8 state = "working" url = "https://github.com/YunoHost-Apps/autobrr_ynh" @@ -358,7 +358,7 @@ url = "https://github.com/YunoHost-Apps/castopod_ynh" [cesium] added_date = 1674232499 # 2023/01/20 category = "wat" -level = 6 +level = 8 state = "working" url = "https://github.com/YunoHost-Apps/cesium_ynh" @@ -448,7 +448,7 @@ url = "https://github.com/YunoHost-Apps/cjdns_ynh" [cloudlog] added_date = 1685981922 # 2023/06/05 category = "small_utilities" -level = 7 +level = 8 state = "working" url = "https://github.com/YunoHost-Apps/cloudlog_ynh" @@ -582,7 +582,7 @@ url = "https://github.com/YunoHost-Apps/cowyo_ynh" [crabfit] added_date = 1710114839 # 2024/03/10 category = "productivity_and_management" -level = 6 +level = 7 potential_alternative_to = [ "Doodle", "OpenSondage" ] state = "working" subtags = [ "poll" ] @@ -785,7 +785,7 @@ url = "https://github.com/YunoHost-Apps/django-for-runners_ynh" [django-fritzconnection] added_date = 1674232499 # 2023/01/20 category = "system_tools" -level = 3 +level = 8 state = "working" subtags = [ "network" ] url = "https://github.com/YunoHost-Apps/django-fritzconnection_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 = 8 +level = 3 state = "working" subtags = [ "programming" ] url = "https://github.com/YunoHost-Apps/django_example_ynh" @@ -1099,7 +1099,7 @@ url = "https://github.com/YunoHost-Apps/filepizza_ynh" [firefish] added_date = 1691055044 # 2023/08/03 category = "social_media" -level = 7 +level = 0 potential_alternative_to = [ "Calckey", "Mastodon", "Misskey", "Pleroma", "Threads", "X" ] state = "working" url = "https://github.com/YunoHost-Apps/firefish_ynh" @@ -1138,6 +1138,16 @@ state = "working" subtags = [ "forum" ] url = "https://github.com/YunoHost-Apps/flarum_ynh" +[flohmarkt] +added_date = 1714137502 # 2024/04/26 +antifeatures = [ "alpha-software", "arbitrary-limitations" ] +category = "publishing" +level = 6 +potential_alternative_to = [ "ClassifiedAds.com", "kleinanzeigen.de" ] +state = "working" +subtags = [ "ecommerce" ] +url = "https://github.com/YunoHost-Apps/flohmarkt_ynh" + [flood] added_date = 1674232499 # 2023/01/20 category = "multimedia" @@ -1246,7 +1256,7 @@ url = "https://github.com/YunoHost-Apps/galene_ynh" [galette] added_date = 1674232499 # 2023/01/20 category = "productivity_and_management" -level = 8 +level = 6 state = "working" subtags = [ "business_and_ngos" ] url = "https://github.com/YunoHost-Apps/galette_ynh" @@ -1289,7 +1299,7 @@ url = "https://github.com/YunoHost-Apps/garradin_ynh" [gemserv] added_date = 1674232499 # 2023/01/20 category = "communication" -level = 6 +level = 8 state = "working" url = "https://github.com/YunoHost-Apps/gemserv_ynh" @@ -1339,7 +1349,7 @@ url = "https://github.com/YunoHost-Apps/gitlab-runner_ynh" [gitlist] added_date = 1675002183 # 2023/01/29 category = "dev" -level = 7 +level = 8 state = "working" subtags = [ "forge" ] url = "https://github.com/YunoHost-Apps/gitlist_ynh" @@ -1460,7 +1470,7 @@ url = "https://github.com/YunoHost-Apps/guacamole_ynh" [h5ai] added_date = 1674232499 # 2023/01/20 category = "small_utilities" -level = 8 +level = 0 state = "working" url = "https://github.com/YunoHost-Apps/h5ai_ynh" @@ -1500,7 +1510,7 @@ url = "https://github.com/YunoHost-Apps/headphones_ynh" [headscale] added_date = 1686503631 # 2023/06/11 category = "system_tools" -level = 7 +level = 8 potential_alternative_to = [ "Tailscale" ] state = "working" subtags = [ "network" ] @@ -1569,7 +1579,7 @@ url = "https://github.com/Yunohost-Apps/httpsh_ynh" [hubzilla] added_date = 1674232499 # 2023/01/20 category = "social_media" -level = 6 +level = 8 potential_alternative_to = [ "Facebook" ] state = "working" subtags = [ "microblogging" ] @@ -1610,7 +1620,7 @@ url = "https://github.com/YunoHost-Apps/icecoder_ynh" [iceshrimp] added_date = 1703341532 # 2023/12/23 category = "social_media" -level = 7 +level = 0 potential_alternative_to = [ "Calckey", "Mastodon", "Misskey", "Pleroma", "Threads", "X" ] state = "working" url = "https://github.com/YunoHost-Apps/iceshrimp_ynh" @@ -1639,7 +1649,9 @@ subtags = [ "accounting" ] url = "https://github.com/YunoHost-Apps/ihatemoney_ynh" [immich] +added_date = 1711921326 # 2024/03/31 category = "multimedia" +level = 6 state = "working" url = "https://github.com/YunoHost-Apps/immich_ynh" @@ -1671,7 +1683,7 @@ url = "https://github.com/YunoHost-Apps/influxdb_v2_ynh" added_date = 1674232499 # 2023/01/20 antifeatures = [ "non-free-network" ] category = "social_media" -level = 8 +level = 6 potential_alternative_to = [ "YouTube" ] state = "working" subtags = [ "videos" ] @@ -1718,8 +1730,9 @@ url = "https://github.com/YunoHost-Apps/jackett_ynh" [jappix] added_date = 1674232499 # 2023/01/20 -antifeatures = [ "package-not-maintained" ] +antifeatures = [ "deprecated-software", "package-not-maintained" ] category = "communication" +deprecated_date = 1714590228 # 2024/05/01 level = 7 state = "working" subtags = [ "chat" ] @@ -1777,7 +1790,7 @@ url = "https://github.com/YunoHost-Apps/jirafeau_ynh" [jitsi] added_date = 1674232499 # 2023/01/20 category = "communication" -level = 6 +level = 8 potential_alternative_to = [ "Google Hangouts", "Skype" ] state = "working" subtags = [ "meeting" ] @@ -1795,11 +1808,19 @@ url = "https://github.com/YunoHost-Apps/joomla_ynh" [joplin] added_date = 1702203874 # 2023/12/10 category = "office" -level = 0 -state = "notworking" +level = 7 +state = "working" subtags = [ "text" ] url = "https://github.com/YunoHost-Apps/joplin_ynh" +[jump] +added_date = 1714286036 # 2024/04/28 +category = "productivity_and_management" +level = 0 +potential_alternative_to = [ "Dashy", "Heimdall" ] +state = "notworking" +url = "https://github.com/YunoHost-Apps/jump_ynh" + [jupyterlab] added_date = 1674232499 # 2023/01/20 category = "dev" @@ -1922,7 +1943,7 @@ url = "https://github.com/YunoHost-Apps/laverna_ynh" [leantime] added_date = 1683586765 # 2023/05/08 category = "productivity_and_management" -level = 7 +level = 8 potential_alternative_to = [ "Asana", "ClickUp", "Notion" ] state = "working" subtags = [ "task" ] @@ -1940,7 +1961,7 @@ url = "https://github.com/YunoHost-Apps/leed_ynh" [lemmy] added_date = 1674232499 # 2023/01/20 category = "social_media" -level = 8 +level = 6 potential_alternative_to = [ "Hacker News", "Lobste.rs", "Reddit" ] state = "working" url = "https://github.com/YunoHost-Apps/lemmy_ynh" @@ -2040,14 +2061,14 @@ url = "https://github.com/YunoHost-Apps/limesurvey_ynh" added_date = 1685604095 # 2023/06/01 antifeatures = [ "non-free-network" ] category = "small_utilities" -level = 7 +level = 8 state = "working" url = "https://github.com/YunoHost-Apps/lingva_ynh" [linkstack] added_date = 1683443449 # 2023/05/07 category = "publishing" -level = 7 +level = 8 state = "working" url = "https://github.com/YunoHost-Apps/linkstack_ynh" @@ -2105,7 +2126,7 @@ url = "https://github.com/YunoHost-Apps/luckysheet_ynh" [lufi] added_date = 1674232499 # 2023/01/20 category = "synchronization" -level = 8 +level = 6 potential_alternative_to = [ "WeTransfer" ] state = "working" subtags = [ "files" ] @@ -2137,7 +2158,7 @@ url = "https://github.com/YunoHost-Apps/lxd-dashboard_ynh" [lychee] added_date = 1674232499 # 2023/01/20 category = "multimedia" -level = 8 +level = 6 potential_alternative_to = [ "Flickr", "Google Photos" ] state = "working" subtags = [ "pictures" ] @@ -2217,7 +2238,7 @@ url = "https://github.com/YunoHost-Apps/mattermost_ynh" [mautic] added_date = 1674232499 # 2023/01/20 category = "productivity_and_management" -level = 6 +level = 8 potential_alternative_to = [ "Marketo", "NetResult", "SalesFusion" ] state = "working" subtags = [ "business_and_ngos" ] @@ -2237,7 +2258,7 @@ added_date = 1674232499 # 2023/01/20 antifeatures = [ "deprecated-software" ] category = "communication" deprecated_date = 1709661665 # 2024/03/05 -level = 6 +level = 0 potential_alternative_to = [ "Facebook Messenger" ] state = "working" subtags = [ "chat" ] @@ -2246,7 +2267,7 @@ url = "https://github.com/YunoHost-Apps/mautrix_facebook_ynh" [mautrix_signal] added_date = 1674232499 # 2023/01/20 category = "communication" -level = 6 +level = 0 potential_alternative_to = [ "Signal" ] state = "working" subtags = [ "chat" ] @@ -2255,7 +2276,7 @@ url = "https://github.com/YunoHost-Apps/mautrix_signal_ynh" [mautrix_telegram] added_date = 1674232499 # 2023/01/20 category = "communication" -level = 8 +level = 0 potential_alternative_to = [ "Telegram" ] state = "working" subtags = [ "chat" ] @@ -2264,7 +2285,7 @@ url = "https://github.com/YunoHost-Apps/mautrix_telegram_ynh" [mautrix_whatsapp] added_date = 1674232499 # 2023/01/20 category = "communication" -level = 8 +level = 0 potential_alternative_to = [ "Whatsapp" ] state = "working" subtags = [ "chat" ] @@ -2273,7 +2294,7 @@ url = "https://github.com/YunoHost-Apps/mautrix_whatsapp_ynh" [mediawiki] added_date = 1674232499 # 2023/01/20 category = "publishing" -level = 7 +level = 8 state = "working" subtags = [ "wiki" ] url = "https://github.com/YunoHost-Apps/mediawiki_ynh" @@ -2295,7 +2316,9 @@ subtags = [ "monitoring" ] url = "https://github.com/YunoHost-Apps/metabase_ynh" [microbin] +added_date = 1712237414 # 2024/04/04 category = "small_utilities" +level = 7 state = "working" subtags = [ "pastebin" ] url = "https://github.com/YunoHost-Apps/microbin_ynh" @@ -2383,7 +2406,7 @@ url = "https://github.com/YunoHost-Apps/moncycle_ynh" added_date = 1674232499 # 2023/01/20 branch = "main" category = "system_tools" -level = 0 +level = 8 state = "working" subtags = [ "db" ] url = "https://github.com/YunoHost-Apps/mongo-express_ynh" @@ -2391,14 +2414,14 @@ url = "https://github.com/YunoHost-Apps/mongo-express_ynh" [monica] added_date = 1674232499 # 2023/01/20 category = "wat" -level = 6 +level = 0 state = "working" url = "https://github.com/YunoHost-Apps/monica_ynh" [monitorix] added_date = 1674232499 # 2023/01/20 category = "system_tools" -level = 6 +level = 8 state = "working" subtags = [ "monitoring" ] url = "https://github.com/YunoHost-Apps/monitorix_ynh" @@ -2478,7 +2501,7 @@ url = "https://github.com/YunoHost-Apps/my-mind_ynh" [my_capsule] added_date = 1674232499 # 2023/01/20 category = "publishing" -level = 6 +level = 7 state = "working" url = "https://github.com/YunoHost-Apps/my_capsule_ynh" @@ -2509,7 +2532,7 @@ url = "https://github.com/YunoHost-Apps/mygpo_ynh" [mytinytodo] added_date = 1674232499 # 2023/01/20 category = "productivity_and_management" -level = 6 +level = 8 state = "working" subtags = [ "task" ] url = "https://github.com/YunoHost-Apps/mytinytodo_ynh" @@ -2708,7 +2731,7 @@ url = "https://github.com/YunoHost-Apps/opensondage_ynh" [opentracker] added_date = 1674232499 # 2023/01/20 category = "wat" -level = 8 +level = 0 state = "working" url = "https://github.com/YunoHost-Apps/opentracker_ynh" @@ -2724,8 +2747,10 @@ url = "https://github.com/YunoHost-Apps/osada_ynh" [osjs] added_date = 1674232499 # 2023/01/20 +antifeatures = [ "deprecated-software" ] category = "wat" -level = 8 +deprecated_date = 1712777448 # 2024/04/10 +level = 7 state = "working" url = "https://github.com/YunoHost-Apps/osjs_ynh" @@ -3003,7 +3028,7 @@ url = "https://github.com/YunoHost-Apps/pico_ynh" [pihole] added_date = 1674232499 # 2023/01/20 category = "system_tools" -level = 6 +level = 8 state = "working" subtags = [ "network" ] url = "https://github.com/YunoHost-Apps/pihole_ynh" @@ -3188,7 +3213,7 @@ url = "https://github.com/YunoHost-Apps/pydio_ynh" [pyinventory] added_date = 1674232499 # 2023/01/20 category = "productivity_and_management" -level = 8 +level = 3 state = "working" subtags = [ "business_and_ngos" ] url = "https://github.com/YunoHost-Apps/pyinventory_ynh" @@ -3256,17 +3281,6 @@ state = "notworking" subtags = [ "calendar", "contacts" ] url = "https://github.com/YunoHost-Apps/radicale_ynh" -[rainloop] -added_date = 1674232499 # 2023/01/20 -antifeatures = [ "bad-security-reputation", "deprecated-software", "replaced-by-another-app" ] -category = "communication" -deprecated_date = 1676378222 # 2023/02/14 -level = 6 -potential_alternative_to = [ "GMail", "Hotmail", "Microsoft Outlook", "Yahoo! Mail" ] -state = "working" -subtags = [ "email" ] -url = "https://github.com/YunoHost-Apps/rainloop_ynh" - [rallly] added_date = 1708020558 # 2024/02/15 category = "productivity_and_management" @@ -3353,7 +3367,7 @@ url = "https://github.com/YunoHost-Apps/rocketchat_ynh" [roundcube] added_date = 1674232499 # 2023/01/20 category = "communication" -level = 6 +level = 8 potential_alternative_to = [ "GMail", "Hotmail", "Microsoft Outlook", "Yahoo! Mail" ] state = "working" subtags = [ "email" ] @@ -3415,7 +3429,7 @@ url = "https://github.com/YunoHost-Apps/satdress_ynh" [scovie] added_date = 1685183203 # 2023/05/27 category = "publishing" -level = 7 +level = 8 state = "working" subtags = [ "website" ] url = "https://github.com/YunoHost-Apps/scovie_ynh" @@ -3498,7 +3512,7 @@ url = "https://github.com/YunoHost-Apps/shaarli_ynh" [sharkey] added_date = 1707378045 # 2024/02/08 category = "social_media" -level = 7 +level = 0 potential_alternative_to = [ "Calckey", "Firefish", "Mastodon", "Misskey", "Pleroma", "Threads", "X" ] state = "working" url = "https://github.com/YunoHost-Apps/sharkey_ynh" @@ -3546,7 +3560,7 @@ url = "https://github.com/YunoHost-Apps/signaturepdf_ynh" added_date = 1710170758 # 2024/03/11 category = "office" level = 6 -potential_alternative_to = [ "Joplin", "Logreq", "Microsoft OneNote", "Obisian" ] +potential_alternative_to = [ "Joplin", "Logseq", "Microsoft OneNote", "Obsidian" ] state = "working" subtags = [ "text" ] url = "https://github.com/YunoHost-Apps/silverbullet_ynh" @@ -3587,7 +3601,7 @@ url = "https://github.com/YunoHost-Apps/simplex_ynh" added_date = 1685875056 # 2023/06/04 antifeatures = [ "non-free-network" ] category = "small_utilities" -level = 7 +level = 8 state = "working" url = "https://github.com/YunoHost-Apps/simplytranslate_ynh" @@ -3660,7 +3674,7 @@ url = "https://github.com/YunoHost-Apps/sogo_ynh" [sonarr] added_date = 1674232499 # 2023/01/20 category = "multimedia" -level = 6 +level = 8 state = "working" url = "https://github.com/YunoHost-Apps/sonarr_ynh" @@ -3744,7 +3758,7 @@ url = "https://github.com/YunoHost-Apps/strut_ynh" [superset] added_date = 1706951650 # 2024/02/03 category = "wat" -level = 1 +level = 6 state = "working" url = "https://github.com/YunoHost-Apps/superset_ynh" @@ -3766,7 +3780,7 @@ url = "https://github.com/YunoHost-Apps/svgedit_ynh" [synapse] added_date = 1674232499 # 2023/01/20 category = "communication" -level = 6 +level = 8 potential_alternative_to = [ "Discord", "Facebook Messenger", "Signal", "Skype", "Telegram", "Whatsapp" ] state = "working" subtags = [ "chat" ] @@ -3775,7 +3789,7 @@ url = "https://github.com/YunoHost-Apps/synapse_ynh" [synapse-admin] added_date = 1674232499 # 2023/01/20 category = "communication" -level = 8 +level = 1 state = "working" subtags = [ "chat" ] url = "https://github.com/YunoHost-Apps/synapse-admin_ynh" @@ -3930,7 +3944,7 @@ url = "https://github.com/YunoHost-Apps/traccar_ynh" [tracim] added_date = 1674232499 # 2023/01/20 category = "office" -level = 7 +level = 8 potential_alternative_to = [ "Dropbox", "Google Drive", "Slack", "Trello" ] state = "working" url = "https://github.com/YunoHost-Apps/tracim_ynh" @@ -4051,7 +4065,7 @@ url = "https://github.com/YunoHost-Apps/unattended_upgrades_ynh" [uptime-kuma] added_date = 1674232499 # 2023/01/20 category = "system_tools" -level = 6 +level = 8 state = "working" subtags = [ "monitoring" ] url = "https://github.com/YunoHost-Apps/uptime-kuma_ynh" @@ -4085,7 +4099,7 @@ url = "https://github.com/YunoHost-Apps/vikunja_ynh" [vore] added_date = 1690540859 # 2023/07/28 category = "reading" -level = 7 +level = 0 state = "working" subtags = [ "rssreader" ] url = "https://github.com/YunoHost-Apps/vore_ynh" @@ -4218,6 +4232,14 @@ state = "working" subtags = [ "blog", "website" ] url = "https://github.com/YunoHost-Apps/wordpress_ynh" +[workout-tracker] +added_date = 1712861274 # 2024/04/11 +category = "small_utilities" +level = 7 +potential_alternative_to = [ "Strava" ] +state = "working" +url = "https://github.com/YunoHost-Apps/workout-tracker_ynh" + [writefreely] added_date = 1674232499 # 2023/01/20 category = "social_media" @@ -4287,8 +4309,10 @@ url = "https://github.com/YunoHost-Apps/yourls_ynh" [yunomonitor] added_date = 1674232499 # 2023/01/20 +antifeatures = [ "deprecated-software" ] category = "system_tools" -level = 8 +deprecated_date = 1672947186 # 2023/01/05 +level = 7 state = "working" subtags = [ "monitoring" ] url = "https://github.com/YunoHost-Apps/yunomonitor_ynh" @@ -4311,7 +4335,7 @@ url = "https://github.com/YunoHost-Apps/z-push_ynh" [zabbix] added_date = 1674232499 # 2023/01/20 category = "system_tools" -level = 6 +level = 8 state = "working" subtags = [ "monitoring" ] url = "https://github.com/YunoHost-Apps/zabbix_ynh" @@ -4330,7 +4354,7 @@ url = "https://github.com/YunoHost-Apps/zap_ynh" added_date = 1674232499 # 2023/01/20 antifeatures = [ "replaced-by-another-app" ] category = "small_utilities" -level = 6 +level = 7 potential_alternative_to = [ "Pastebin" ] state = "working" subtags = [ "pastebin" ] @@ -4338,8 +4362,10 @@ url = "https://github.com/YunoHost-Apps/zerobin_ynh" [zeronet] added_date = 1674232499 # 2023/01/20 +antifeatures = [ "deprecated-software" ] category = "wat" -level = 6 +deprecated_date = 1714840875 # 2024/05/04 +level = 8 potential_alternative_to = [ "Mullvad" ] state = "working" url = "https://github.com/YunoHost-Apps/zeronet_ynh" @@ -4357,7 +4383,7 @@ url = "https://github.com/YunoHost-Apps/zerotier_ynh" added_date = 1693093567 # 2023/08/26 antifeatures = [ "non-free-dependencies" ] category = "system_tools" -level = 7 +level = 0 state = "working" subtags = [ "network" ] url = "https://github.com/YunoHost-Apps/zeroui_ynh" diff --git a/cron b/cron index 631a36fb..92d344f3 100644 --- a/cron +++ b/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 diff --git a/graveyard.toml b/graveyard.toml index f64ae9d6..f31bdcdc 100644 --- a/graveyard.toml +++ b/graveyard.toml @@ -253,6 +253,16 @@ category = "system_tools" killed_date = 1703600553 # 2023/12/26 url = "https://github.com/YunoHost-Apps/portainer_ynh" +[rainloop] +added_date = 1674232499 # 2023/01/20 +antifeatures = [ "bad-security-reputation", "deprecated-software", "replaced-by-another-app" ] +category = "communication" +deprecated_date = 1676378222 # 2023/02/14 +killed_date = 1715300302 # 2024/05/10 +potential_alternative_to = [ "GMail", "Hotmail", "Microsoft Outlook", "Yahoo! Mail" ] +subtags = [ "email" ] +url = "https://github.com/YunoHost-Apps/rainloop_ynh" + [reel2bits] added_date = 1554588215 # 2019/04/07 category = "social_media" diff --git a/logos/flohmarkt.png b/logos/flohmarkt.png new file mode 100644 index 00000000..1b142228 Binary files /dev/null and b/logos/flohmarkt.png differ diff --git a/logos/incus.png b/logos/incus.png new file mode 100644 index 00000000..bf8e0b21 Binary files /dev/null and b/logos/incus.png differ diff --git a/maintenance.sh b/maintenance.sh new file mode 100644 index 00000000..f7dc944d --- /dev/null +++ b/maintenance.sh @@ -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 + 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 + popd >/dev/null +} + + +function fetch_level_history() +{ + pushd store >/dev/null + venv/bin/python3 fetch_level_history.py + popd >/dev/null +} + +$1 diff --git a/rebuild.sh b/rebuild.sh deleted file mode 100644 index 4417a728..00000000 --- a/rebuild.sh +++ /dev/null @@ -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" diff --git a/schemas/manifest.v2.schema.json b/schemas/manifest.v2.schema.json index 6f38292e..e30bedea 100644 --- a/schemas/manifest.v2.schema.json +++ b/schemas/manifest.v2.schema.json @@ -579,6 +579,10 @@ "allow_prereleases": { "type": "boolean", "description": "Allow prereleases when using strategy = latest_X_release" + }, + "needs_manual_tweaks": { + "type": "boolean", + "description": "Inform the maintainer of manual steps to make autoupdate PRs work" } } } diff --git a/sourcesautoupdate.sh b/sourcesautoupdate.sh deleted file mode 100644 index 99d14565..00000000 --- a/sourcesautoupdate.sh +++ /dev/null @@ -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" diff --git a/store/.cache/.gitkeep b/store/.cache/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/store/.gitignore b/store/.gitignore index a54cfd00..27836fa2 100644 --- a/store/.gitignore +++ b/store/.gitignore @@ -1,9 +1,6 @@ config.toml .stars .wishlist_ratelimit - -assets/fork-awesome.* -assets/forkawesome-webfont.* -assets/tailwind.css -assets/tailwindcss-linux-x64 -assets/ynh_logo_* \ No newline at end of file +.cache +.tmp +assets/* diff --git a/store/README.md b/store/README.md index 9313fe93..c8a5f75e 100644 --- a/store/README.md +++ b/store/README.md @@ -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 @@ -42,7 +45,7 @@ It's based on Flask-Babel : source venv/bin/activate # Extract the english sentences from the code, needed if you modified it -pybabel extract --ignore-dirs venv -F babel.cfg -o messages.pot . +pybabel extract -F babel.cfg -o messages.pot *.py templates/*.html # If working on a new locale: initialize it (in this example: fr) pybabel init -i messages.pot -d translations -l fr diff --git a/store/app.py b/store/app.py index 318558d2..a54a418f 100644 --- a/store/app.py +++ b/store/app.py @@ -1,15 +1,17 @@ -import time +import os +import sys import re +import time +import json import toml import tomlkit import base64 import hashlib import hmac -import os import string import random import urllib -import sys +from datetime import datetime from slugify import slugify from flask import ( Flask, @@ -18,6 +20,7 @@ from flask import ( session, redirect, request, + make_response, ) from flask_babel import Babel from flask_babel import gettext as _ @@ -30,6 +33,7 @@ from utils import ( get_catalog, get_wishlist, get_stars, + get_dashboard_data, get_app_md_and_screenshots, save_wishlist_submit_for_ratelimit, check_wishlist_submit_ratelimit, @@ -61,9 +65,7 @@ for key in mandatory_config_keys: print(f"Missing key in config.toml: {key}") sys.exit(1) -if config.get("DEBUG"): - app.debug = True - app.config["DEBUG"] = True +if app.config.get("DEBUG"): app.config["TEMPLATES_AUTO_RELOAD"] = True # This is the secret key used for session signing @@ -84,6 +86,31 @@ def localize(d): return d["en"] +@app.template_filter("days_ago") +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 = { + "user": session.get("user", {}), + "locale": get_locale(), + } + + if app.config.get("DEBUG"): + d["tailwind_local"] = open("assets/tailwind-local.css").read() + + return d + + ############################################################################### @@ -96,8 +123,6 @@ def favicon(): def index(): return render_template( "index.html", - locale=get_locale(), - user=session.get("user", {}), catalog=get_catalog(), ) @@ -106,12 +131,10 @@ def index(): def browse_catalog(): return render_template( "catalog.html", - locale=get_locale(), init_sort=request.args.get("sort"), init_search=request.args.get("search"), init_category=request.args.get("category"), init_starsonly=request.args.get("starsonly"), - user=session.get("user", {}), catalog=get_catalog(), timestamp_now=int(time.time()), stars=get_stars(), @@ -134,8 +157,6 @@ def app_info(app_id): return render_template( "app.html", - locale=get_locale(), - user=session.get("user", {}), app_id=app_id, infos=infos, catalog=get_catalog(), @@ -184,11 +205,6 @@ def star_app(app_id, action): def browse_wishlist(): return render_template( "wishlist.html", - init_sort=request.args.get("sort"), - init_search=request.args.get("search"), - init_starsonly=request.args.get("starsonly"), - locale=get_locale(), - user=session.get("user", {}), wishlist=get_wishlist(), stars=get_stars(), ) @@ -208,8 +224,6 @@ def add_to_wishlist(): ) return render_template( "wishlist_add.html", - locale=get_locale(), - user=session.get("user", {}), csrf_token=None, successmsg=None, errormsg=errormsg, @@ -220,8 +234,6 @@ def add_to_wishlist(): errormsg = _("Invalid CSRF token, please refresh the page and try again") return render_template( "wishlist_add.html", - locale=get_locale(), - user=session.get("user", {}), csrf_token=csrf_token, successmsg=None, errormsg=errormsg, @@ -256,7 +268,7 @@ def add_to_wishlist(): checks = [ ( check_wishlist_submit_ratelimit(session["user"]["username"]) is True - and session["user"]["bypass_ratelimit"] is False, + or session["user"]["bypass_ratelimit"] is True, _( "Proposing wishlist additions is limited to once every 15 days per user. Please try again in a few days." ), @@ -315,8 +327,6 @@ def add_to_wishlist(): if not check: return render_template( "wishlist_add.html", - locale=get_locale(), - user=session.get("user", {}), csrf_token=csrf_token, successmsg=None, errormsg=errormsg, @@ -337,8 +347,6 @@ def add_to_wishlist(): url = f"https://apps.yunohost.org/wishlist?search={slug}" return render_template( "wishlist_add.html", - locale=get_locale(), - user=session.get("user", {}), csrf_token=csrf_token, successmsg=None, errormsg=_( @@ -354,8 +362,6 @@ def add_to_wishlist(): url = f"https://apps.yunohost.org/app/{slug}" return render_template( "wishlist_add.html", - locale=get_locale(), - user=session.get("user", {}), csrf_token=csrf_token, successmsg=None, errormsg=_( @@ -389,8 +395,6 @@ def add_to_wishlist(): ) return render_template( "wishlist_add.html", - locale=get_locale(), - user=session.get("user", {}), csrf_token=csrf_token, successmsg=None, errormsg=errormsg, @@ -444,8 +448,6 @@ Description: {description} return render_template( "wishlist_add.html", - locale=get_locale(), - user=session.get("user", {}), successmsg=successmsg, ) else: @@ -454,14 +456,112 @@ Description: {description} session["csrf_token"] = csrf_token return render_template( "wishlist_add.html", - locale=get_locale(), - user=session.get("user", {}), csrf_token=csrf_token, successmsg=None, errormsg=None, ) +@app.route("/dash") +def dash(): + return render_template("dash.html", data=get_dashboard_data(), stars=get_stars()) + + +@app.route("/charts") +def charts(): + + dashboard_data = get_dashboard_data() + level_summary = {} + for i in range(0, 9): + level_summary[i] = len( + [ + infos + for infos in dashboard_data.values() + if infos.get("ci_results", {}).get("main").get("level") == i + ] + ) + level_summary["unknown"] = len( + [ + infos + for infos in dashboard_data.values() + if infos.get("ci_results", {}).get("main").get("level") in [None, "?"] + ] + ) + + return render_template( + "charts.html", + level_summary=level_summary, + history=json.loads(open(".cache/history.json").read()), + news_per_date=json.loads(open(".cache/news.json").read()), + ) + + +@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.route("/integration/.svg") +@app.route("/badge//") +@app.route("/badge//.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 # ############################################################################### @@ -535,6 +635,22 @@ def sso_login_callback(): return redirect("/") +@app.route("/toggle_packaging") +def toggle_packaging(): + if session and "user" in session: + user = session["user"] + if not session["user"].get("packaging_enabled"): + # Use this trick to force the change to be registered + # because this session["user"]["foobar"] = value doesn't actually change the state ? idk + user["packaging_enabled"] = True + session["user"] = user + return redirect("/dash") + else: + user["packaging_enabled"] = False + session["user"] = user + return redirect("/") + + @app.route("/logout") def logout(): session.clear() diff --git a/store/assets/badges/fetch_badges b/store/assets/badges/fetch_badges new file mode 100644 index 00000000..5f1c94da --- /dev/null +++ b/store/assets/badges/fetch_badges @@ -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 diff --git a/store/assets/fetch_assets b/store/assets/fetch_assets index 99c250da..4a931514 100644 --- a/store/assets/fetch_assets +++ b/store/assets/fetch_assets @@ -1,13 +1,25 @@ -# Download standalone tailwind to compile what we need -wget https://github.com/tailwindlabs/tailwindcss/releases/download/v3.3.3/tailwindcss-linux-x64 + +# Production -> download standalone tailwind to compile only what we need +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 + +# 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 + +# Icons / Forkawesome curl https://cdn.jsdelivr.net/npm/fork-awesome@1.2.0/css/fork-awesome.min.css > fork-awesome.min.css sed -i 's@../fonts/@@g' ./fork-awesome.min.css curl https://cdn.jsdelivr.net/npm/fork-awesome@1.2.0/fonts/forkawesome-webfont.woff2?v=1.2.0 > forkawesome-webfont.woff2 curl https://cdn.jsdelivr.net/npm/fork-awesome@1.2.0/fonts/forkawesome-webfont.woff?v=1.2.0 > forkawesome-webfont.woff curl https://cdn.jsdelivr.net/npm/fork-awesome@1.2.0/fonts/forkawesome-webfont.ttf?v=1.2.0 > forkawesome-webfont.ttf +# Logos curl https://raw.githubusercontent.com/YunoHost/doc/master/images/logo_roundcorner.png > ynh_logo_roundcorner.png curl https://raw.githubusercontent.com/YunoHost/doc/master/images/ynh_logo_black.svg > ynh_logo_black.svg diff --git a/store/assets/tailwind-local.css b/store/assets/tailwind-local.css index 787ba1d2..8a2758ae 100644 --- a/store/assets/tailwind-local.css +++ b/store/assets/tailwind-local.css @@ -3,6 +3,9 @@ @tailwind utilities; @layer utilities { + 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; } diff --git a/store/assets/tailwind.config.js b/store/assets/tailwind.config.js index c5b0b2fc..76d9411d 100644 --- a/store/assets/tailwind.config.js +++ b/store/assets/tailwind.config.js @@ -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', diff --git a/store/config.toml.example b/store/config.toml.example index e85497d6..bdf0d5bc 100644 --- a/store/config.toml.example +++ b/store/config.toml.example @@ -1,5 +1,7 @@ COOKIE_SECRET = "abcdefghijklmnopqrstuvwxyz1234567890" -# This secret is configured in Discourse +# This secret is configured in Discourse, "discourse connect provider secret" +# For development, a secret for "localhost" exists. +# But then be sure to access your dev server using localhost:5000, not 127.0.0.1:5000 DISCOURSE_SSO_SECRET = "abcdefghijklmnopqrstuvwxyz1234567890" DISCOURSE_SSO_ENDPOINT = "https://forum.yunohost.org/session/sso_provider" CALLBACK_URL_AFTER_LOGIN_ON_DISCOURSE = "http://localhost:5000/sso_login_callback" diff --git a/store/fetch_level_history.py b/store/fetch_level_history.py new file mode 100644 index 00000000..37e151b4 --- /dev/null +++ b/store/fetch_level_history.py @@ -0,0 +1,200 @@ +import toml +import json +import os +from datetime import datetime + + +def _time_points_until_today(): + + year = 2017 + month = 1 + day = 1 + today = datetime.today() + date = datetime(year, month, day) + + while date < today: + yield date + + day += 14 + if day > 15: + day = 1 + month += 1 + + if month > 12: + month = 1 + year += 1 + + date = datetime(year, month, day) + + +time_points_until_today = list(_time_points_until_today()) + + +def get_lists_history(): + + os.system("rm -rf ./.tmp") + os.system("git clone https://github.com/YunoHost/apps ./.tmp/apps") + + for t in time_points_until_today: + print(t.strftime("%b %d %Y")) + + # Fetch repo at this date + cmd = 'cd ./.tmp/apps; git checkout `git rev-list -1 --before="%s" master`' + os.system(cmd % t.strftime("%b %d %Y")) + + if t < datetime(2019, 4, 4): + # Merge community and official + community = json.loads(open("./.tmp/apps/community.json").read()) + official = json.loads(open("./.tmp/apps/official.json").read()) + for key in official: + official[key]["state"] = "official" + merged = {} + merged.update(community) + merged.update(official) + else: + try: + merged = toml.loads(open("./.tmp/apps/apps.toml").read()) + except Exception: + try: + merged = json.loads(open("./.tmp/apps/apps.json").read()) + except Exception: + pass + + # Save it + json.dump( + merged, open("./.tmp/merged_lists.json.%s" % t.strftime("%y-%m-%d"), "w") + ) + + +def make_count_summary(): + + history = [] + + last_time_point = time_points_until_today[-1] + json_at_last_time_point = json.loads( + open( + "./.tmp/merged_lists.json.%s" % last_time_point.strftime("%y-%m-%d") + ).read() + ) + relevant_apps_to_track = [ + app + for app, infos in json_at_last_time_point.items() + if infos.get("state") in ["working", "official"] + ] + + for d in time_points_until_today: + + print("Analyzing %s ..." % d.strftime("%y-%m-%d")) + + # Load corresponding json + j = json.loads( + open("./.tmp/merged_lists.json.%s" % d.strftime("%y-%m-%d")).read() + ) + d_label = d.strftime("%b %d %Y") + + summary = {} + summary["date"] = d_label + for level in range(0, 10): + summary["level-%s" % level] = len( + [ + k + for k, infos in j.items() + if infos.get("state") in ["working", "official"] + and infos.get("level", None) == level + ] + ) + + history.append(summary) + + for app in relevant_apps_to_track: + + infos = j.get(app, {}) + + if not infos or infos.get("state") not in ["working", "official"]: + level = -1 + else: + level = infos.get("level", -1) + try: + level = int(level) + except Exception: + level = -1 + + json.dump(history, open(".cache/history.json", "w")) + + +def make_news(): + + news_per_date = { + d.strftime("%b %d %Y"): { + "broke": [], + "repaired": [], + "removed": [], + "added": [], + } + for d in time_points_until_today + } + previous_j = {} + + def level(infos): + lev = infos.get("level") + if lev is None or (isinstance(lev, str) and not lev.isdigit()): + return -1 + else: + return int(lev) + + for d in time_points_until_today: + d_label = d.strftime("%b %d %Y") + + print("Analyzing %s ..." % d.strftime("%y-%m-%d")) + + # Load corresponding json + j = json.loads( + open("./.tmp/merged_lists.json.%s" % d.strftime("%y-%m-%d")).read() + ) + + apps_current = set( + k + for k, infos in j.items() + if infos.get("state") in ["working", "official"] and level(infos) != -1 + ) + apps_current_good = set( + k for k, infos in j.items() if k in apps_current and level(infos) > 4 + ) + apps_current_broken = set( + k for k, infos in j.items() if k in apps_current and level(infos) <= 4 + ) + + apps_previous = set( + k + for k, infos in previous_j.items() + if infos.get("state") in ["working", "official"] and level(infos) != -1 + ) + apps_previous_good = set( + k + for k, infos in previous_j.items() + if k in apps_previous and level(infos) > 4 + ) + apps_previous_broken = set( + k + for k, infos in previous_j.items() + if k in apps_previous and level(infos) <= 4 + ) + + news = news_per_date[d_label] + for app in set(apps_previous_good & apps_current_broken): + news["broke"].append((app, j[app]["url"])) + for app in set(apps_previous_broken & apps_current_good): + news["repaired"].append((app, j[app]["url"])) + for app in set(apps_current - apps_previous): + news["added"].append((app, j[app]["url"])) + for app in set(apps_previous - apps_current): + news["removed"].append((app, previous_j[app]["url"])) + + previous_j = j + + json.dump(news_per_date, open(".cache/news.json", "w")) + + +get_lists_history() +make_count_summary() +make_news() diff --git a/store/fetch_main_dashboard.py b/store/fetch_main_dashboard.py new file mode 100644 index 00000000..ce15110e --- /dev/null +++ b/store/fetch_main_dashboard.py @@ -0,0 +1,126 @@ +import os +import sys +import requests +import json +import toml +from github import Github + +sys.path = [os.path.dirname(__file__)] + sys.path +from utils import get_catalog + + +try: + config = toml.loads(open("config.toml").read()) +except Exception: + print( + "You should create a config.toml with the appropriate key/values, cf config.toml.example" + ) + sys.exit(1) + +github_token = config.get("GITHUB_TOKEN") + +if github_token is None: + print("You should add a GITHUB_TOKEN to config.toml") + sys.exit(1) + +g = Github(github_token) + +catalog = get_catalog() +main_ci_apps_results = requests.get( + "https://ci-apps.yunohost.org/ci/api/results" +).json() +nextdebian_ci_apps_results = requests.get( + "https://ci-apps-bookworm.yunohost.org/ci/api/results" +).json() + + +def get_github_infos(github_orga_and_repo): + + repo = g.get_repo(github_orga_and_repo) + infos = {} + + pulls = [p for p in repo.get_pulls()] + + infos["nb_prs"] = len(pulls) + infos["nb_issues"] = repo.open_issues_count - infos["nb_prs"] + + testings = [p for p in pulls if p.head.ref == "testing"] + testing = testings[0] if testings else None + ci_auto_updates = [p for p in pulls if p.head.ref.startswith("ci-auto-update")] + ci_auto_update = ( + sorted(ci_auto_updates, key=lambda p: p.created_at, reverse=True)[0] + if ci_auto_updates + else None + ) + + for p in ([testing] if testing else []) + ( + [ci_auto_update] if ci_auto_update else [] + ): + + if p.head.label != "YunoHost-Apps:testing" and not ( + p.user.login == "yunohost-bot" and p.head.ref.startswith("ci-auto-update-") + ): + continue + + infos["testing" if p.head.ref == "testing" else "ci-auto-update"] = { + "branch": p.head.ref, + "url": p.html_url, + "timestamp_created": int(p.created_at.timestamp()), + "timestamp_updated": int(p.updated_at.timestamp()), + "statuses": [ + { + "state": s.state, + "context": s.context, + "url": s.target_url, + "timestamp": int(s.updated_at.timestamp()), + } + for s in repo.get_commit(p.head.sha).get_combined_status().statuses + ], + } + + return infos + + +consolidated_infos = {} +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"], + "timestamp_latest_commit": infos["lastUpdate"], + "maintainers": infos["manifest"]["maintainers"], + "antifeatures": infos["antifeatures"], + "packaging_format": infos["manifest"]["packaging_format"], + "ci_results": { + "main": ( + { + "level": main_ci_apps_results[app]["level"], + "timestamp": main_ci_apps_results[app]["timestamp"], + } + if app in main_ci_apps_results + else None + ), + "nextdebian": ( + { + "level": nextdebian_ci_apps_results[app]["level"], + "timestamp": nextdebian_ci_apps_results[app]["timestamp"], + } + if app in nextdebian_ci_apps_results + else None + ), + }, + } + + if infos["git"]["url"].lower().startswith("https://github.com/"): + consolidated_infos[app].update( + get_github_infos( + infos["git"]["url"].lower().replace("https://github.com/", "") + ) + ) + +open(".cache/dashboard.json", "w").write(json.dumps(consolidated_infos)) diff --git a/store/messages.pot b/store/messages.pot index 6af8cf79..7db085c8 100644 --- a/store/messages.pot +++ b/store/messages.pot @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PROJECT VERSION\n" "Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" -"POT-Creation-Date: 2024-04-01 00:57+0200\n" +"POT-Creation-Date: 2024-05-09 23:14+0200\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -17,16 +17,16 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "Generated-By: Babel 2.14.0\n" -#: app.py:150 +#: app.py:162 #, python-format msgid "App %(app_id)s not found" msgstr "" -#: app.py:153 +#: app.py:165 msgid "You must be logged in to be able to star an app" msgstr "" -#: app.py:155 app.py:205 app.py:513 templates/wishlist_add.html:33 +#: app.py:167 app.py:212 app.py:530 templates/wishlist_add.html:33 msgid "" "Note that, due to various abuses, we restricted login on the app store to" " 'trust level 1' users.

'Trust level 1' is obtained after " @@ -35,71 +35,71 @@ msgid "" "minutes reading posts." msgstr "" -#: app.py:203 +#: app.py:210 msgid "You must be logged in to submit an app to the wishlist" msgstr "" -#: app.py:220 +#: app.py:225 msgid "Invalid CSRF token, please refresh the page and try again" msgstr "" -#: app.py:260 +#: app.py:263 msgid "" "Proposing wishlist additions is limited to once every 15 days per user. " "Please try again in a few days." msgstr "" -#: app.py:264 +#: app.py:267 msgid "App name should be at least 3 characters" msgstr "" -#: app.py:265 +#: app.py:268 msgid "App name should be less than 30 characters" msgstr "" -#: app.py:268 +#: app.py:271 msgid "App description should be at least 5 characters" msgstr "" -#: app.py:272 +#: app.py:275 msgid "App description should be less than 100 characters" msgstr "" -#: app.py:276 +#: app.py:279 msgid "Upstream code repo URL should be at least 10 characters" msgstr "" -#: app.py:280 +#: app.py:283 msgid "Upstream code repo URL should be less than 150 characters" msgstr "" -#: app.py:284 +#: app.py:287 msgid "License URL should be at least 10 characters" msgstr "" -#: app.py:288 +#: app.py:291 msgid "License URL should be less than 250 characters" msgstr "" -#: app.py:290 +#: app.py:293 msgid "Website URL should be less than 150 characters" msgstr "" -#: app.py:293 +#: app.py:296 msgid "App name contains special characters" msgstr "" -#: app.py:300 +#: app.py:303 msgid "" "Please focus on what the app does, without using marketing, fuzzy terms, " "or repeating that the app is 'free' and 'self-hostable'." msgstr "" -#: app.py:310 +#: app.py:313 msgid "No need to repeat the name of the app. Focus on what the app does." msgstr "" -#: app.py:344 +#: app.py:343 #, python-format msgid "" "An entry with the name %(slug)s already exists in the wishlist, instead, " @@ -107,14 +107,14 @@ msgid "" "interest." msgstr "" -#: app.py:361 +#: app.py:358 #, python-format msgid "" "An app with the name %(slug)s already exists in the catalog, you can see its page here." msgstr "" -#: app.py:386 +#: app.py:383 #, python-format msgid "" "Failed to create the pull request to add the app to the wishlist… Maybe " @@ -122,7 +122,7 @@ msgid "" "please report the issue to the YunoHost team." msgstr "" -#: app.py:438 +#: app.py:433 #, python-format msgid "" "Your proposed app has succesfully been submitted. It must now be " @@ -130,7 +130,7 @@ msgid "" "href='%(url)s'>%(url)s" msgstr "" -#: app.py:511 +#: app.py:528 msgid "Unfortunately, login was denied." msgstr "" @@ -242,39 +242,52 @@ msgstr "" msgid "YunoHost package license" msgstr "" -#: templates/base.html:5 +#: templates/base.html:11 msgid "YunoHost app store" msgstr "" -#: templates/base.html:18 templates/base.html:113 templates/index.html:3 +#: templates/base.html:31 templates/base.html:154 templates/index.html:3 msgid "Home" msgstr "" -#: templates/base.html:27 templates/base.html:122 +#: templates/base.html:40 templates/base.html:163 templates/dash.html:66 msgid "Catalog" msgstr "" -#: templates/base.html:33 templates/base.html:131 +#: templates/base.html:46 templates/base.html:172 msgid "Wishlist" msgstr "" -#: templates/base.html:46 templates/base.html:141 +#: templates/base.html:52 +msgid "Packaging dashboard" +msgstr "" + +#: templates/base.html:57 +msgid "Charts & history" +msgstr "" + +#: templates/base.html:71 templates/base.html:182 msgid "YunoHost documentation" msgstr "" -#: templates/base.html:54 templates/base.html:151 +#: templates/base.html:79 templates/base.html:192 msgid "Login using YunoHost's forum" msgstr "" -#: templates/base.html:86 templates/base.html:179 +#: templates/base.html:111 templates/base.html:120 templates/base.html:220 +#: templates/base.html:229 +msgid "Packaging boards" +msgstr "" + +#: templates/base.html:127 templates/base.html:237 msgid "Logout" msgstr "" -#: templates/base.html:99 +#: templates/base.html:140 msgid "Toggle menu" msgstr "" -#: templates/base.html:197 +#: templates/base.html:255 msgid "" "Made with " "using TailwindCSS" msgstr "" -#: templates/base.html:198 +#: templates/base.html:256 msgid "Source" msgstr "" -#: templates/base.html:199 +#: templates/base.html:257 msgid "Terms of Services" msgstr "" @@ -306,7 +319,7 @@ msgstr "" msgid "All apps" msgstr "" -#: templates/catalog.html:117 templates/wishlist.html:39 +#: templates/catalog.html:117 templates/dash.html:34 templates/wishlist.html:39 msgid "Sort by" msgstr "" @@ -319,16 +332,16 @@ msgstr "" msgid "Newest" msgstr "" -#: templates/catalog.html:125 templates/wishlist.html:46 +#: templates/catalog.html:125 templates/dash.html:40 templates/wishlist.html:46 msgid "Alphabetical" msgstr "" -#: templates/catalog.html:128 templates/wishlist.html:49 +#: templates/catalog.html:128 templates/dash.html:47 templates/wishlist.html:49 msgid "Requires to be logged-in" msgstr "" -#: templates/catalog.html:130 templates/catalog.html:139 -#: templates/wishlist.html:51 templates/wishlist.html:60 +#: templates/catalog.html:130 templates/catalog.html:139 templates/dash.html:49 +#: templates/dash.html:58 templates/wishlist.html:51 templates/wishlist.html:60 msgid "Show only apps you starred" msgstr "" @@ -366,6 +379,204 @@ msgid "" "advise against their installation and advise users to find alternatives." msgstr "" +#: templates/charts.html:5 +msgid "Apps quality level from automatic tests" +msgstr "" + +#: templates/charts.html:9 +msgid "Apps quality level history" +msgstr "" + +#: templates/charts.html:14 +msgid "History" +msgstr "" + +#: templates/charts.html:22 +msgid "Added" +msgstr "" + +#: templates/charts.html:28 +msgid "Repaired" +msgstr "" + +#: templates/charts.html:34 +msgid "Broke" +msgstr "" + +#: templates/charts.html:40 +msgid "Removed" +msgstr "" + +#: templates/charts.html:80 +msgid "Unknown" +msgstr "" + +#: templates/charts.html:81 +msgid "Level 0" +msgstr "" + +#: templates/charts.html:82 +msgid "Level 1" +msgstr "" + +#: templates/charts.html:83 +msgid "Level 2" +msgstr "" + +#: templates/charts.html:84 +msgid "Level 3" +msgstr "" + +#: templates/charts.html:85 +msgid "Level 4" +msgstr "" + +#: templates/charts.html:86 +msgid "Level 5" +msgstr "" + +#: templates/charts.html:87 +msgid "Level 6" +msgstr "" + +#: templates/charts.html:88 +msgid "Level 7" +msgstr "" + +#: templates/charts.html:89 +msgid "Level 8" +msgstr "" + +#: templates/charts.html:107 +#, python-format +msgid "Level %(level)s:" +msgstr "" + +#: templates/charts.html:107 +msgid "Total:" +msgstr "" + +#: templates/charts.html:108 +#, python-format +msgid "Level %(level)s" +msgstr "" + +#: templates/dash.html:3 templates/dash.html:9 +msgid "App packaging dashboard" +msgstr "" + +#: templates/dash.html:11 +msgid "" +"This is where packagers can monitor the status of automatic tests (CI) " +"and ongoing major pull requests accross all apps. If you want to get " +"started with app packaging in YunoHost, please check out the packaging " +"documentation and come say hi to us on the app packaging chatroom!" +msgstr "" + +#: templates/dash.html:17 +msgid "Filter" +msgstr "" + +#: templates/dash.html:23 +msgid "(None)" +msgstr "" + +#: templates/dash.html:24 +msgid "Regressions on main CI" +msgstr "" + +#: templates/dash.html:25 +msgid "Broken / low quality apps" +msgstr "" + +#: templates/dash.html:26 +msgid "Outdated tests on main CI" +msgstr "" + +#: templates/dash.html:27 +msgid "Major regressions on Bookworm CI" +msgstr "" + +#: templates/dash.html:28 +msgid "Apps with testings PRs" +msgstr "" + +#: templates/dash.html:29 +msgid "Apps with autoupdate PRs" +msgstr "" + +#: templates/dash.html:30 +msgid "Packaging v1 apps" +msgstr "" + +#: templates/dash.html:41 +msgid "Quality level" +msgstr "" + +#: templates/dash.html:42 templates/dash.html:173 +msgid "Popularity stars" +msgstr "" + +#: templates/dash.html:43 +msgid "Last update on main/master branch" +msgstr "" + +#: templates/dash.html:44 +msgid "Last update on testing branch" +msgstr "" + +#: templates/dash.html:65 +msgid "App" +msgstr "" + +#: templates/dash.html:67 +msgid "Main CI" +msgstr "" + +#: templates/dash.html:68 +msgid "Bookworm CI" +msgstr "" + +#: templates/dash.html:69 +msgid "Testing PR" +msgstr "" + +#: templates/dash.html:70 +msgid "Autoupdate PR" +msgstr "" + +#: templates/dash.html:102 templates/dash.html:116 templates/dash.html:131 +msgid "Broken" +msgstr "" + +#: templates/dash.html:104 templates/dash.html:118 templates/dash.html:133 +msgid "Low quality" +msgstr "" + +#: templates/dash.html:112 templates/dash.html:127 +#, python-format +msgid "Outdated test (%(days)s days ago)" +msgstr "" + +#: templates/dash.html:150 templates/dash.html:165 +#, python-format +msgid "Inactive (%(days)s days ago)" +msgstr "" + +#: templates/dash.html:177 +msgid "Packaging v1" +msgstr "" + +#: templates/dash.html:180 +msgid "Deprecated" +msgstr "" + +#: templates/dash.html:183 +msgid "Not maintained" +msgstr "" + #: templates/index.html:10 msgid "Application Store" msgstr "" @@ -374,44 +585,10 @@ msgstr "" msgid "Browse all applications" msgstr "" -#: templates/wishlist.html:3 templates/wishlist.html:8 -msgid "Application Wishlist" -msgstr "" - -#: templates/wishlist.html:10 -msgid "" -"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." -msgstr "" - #: templates/wishlist.html:33 templates/wishlist_add.html:3 msgid "Suggest an app" msgstr "" -#: templates/wishlist.html:71 templates/wishlist_add.html:61 -msgid "Name" -msgstr "" - -#: templates/wishlist.html:74 -msgid "Description" -msgstr "" - -#: templates/wishlist.html:102 templates/wishlist.html:103 -msgid "Official website" -msgstr "" - -#: templates/wishlist.html:115 templates/wishlist.html:116 -msgid "Code repository" -msgstr "" - -#: templates/wishlist.html:129 templates/wishlist.html:130 -msgid "Star this app" -msgstr "" - #: templates/wishlist_add.html:8 msgid "Suggest an application to be added to YunoHost's catalog" msgstr "" @@ -430,6 +607,10 @@ msgid "" "send every random nerdy stuff you find on the Internet." msgstr "" +#: templates/wishlist.html:71 templates/wishlist_add.html:61 +msgid "Name" +msgstr "" + #: templates/wishlist_add.html:64 msgid "App's description" msgstr "" @@ -474,3 +655,33 @@ msgstr "" msgid "Submit" msgstr "" +#: templates/wishlist.html:3 templates/wishlist.html:8 +msgid "Application Wishlist" +msgstr "" + +#: templates/wishlist.html:10 +msgid "" +"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." +msgstr "" + +#: templates/wishlist.html:74 +msgid "Description" +msgstr "" + +#: templates/wishlist.html:102 templates/wishlist.html:103 +msgid "Official website" +msgstr "" + +#: templates/wishlist.html:115 templates/wishlist.html:116 +msgid "Code repository" +msgstr "" + +#: templates/wishlist.html:129 templates/wishlist.html:130 +msgid "Star this app" +msgstr "" + diff --git a/store/requirements.txt b/store/requirements.txt index 82089229..a8d624b4 100644 --- a/store/requirements.txt +++ b/store/requirements.txt @@ -1,10 +1,32 @@ -Flask==2.3.2 -python-slugify -PyGithub -toml -tomlkit -pycmarkgfm -gunicorn -emoji -Babel -Flask-Babel +Babel==2.14.0 +blinker==1.8.1 +certifi==2024.2.2 +cffi==1.16.0 +charset-normalizer==3.3.2 +click==8.1.7 +cryptography==42.0.5 +Deprecated==1.2.14 +emoji==2.11.1 +Flask==3.0.3 +flask-babel==4.0.0 +gunicorn==22.0.0 +idna==3.7 +itsdangerous==2.2.0 +Jinja2==3.1.4 +MarkupSafe==2.1.5 +packaging==24.0 +pycmarkgfm==1.2.1 +pycparser==2.22 +PyGithub==2.3.0 +PyJWT==2.8.0 +PyNaCl==1.5.0 +python-slugify==8.0.4 +pytz==2024.1 +requests==2.31.0 +text-unidecode==1.3 +toml==0.10.2 +tomlkit==0.12.4 +typing_extensions==4.11.0 +urllib3==2.2.1 +Werkzeug==3.0.3 +wrapt==1.16.0 diff --git a/store/templates/app.html b/store/templates/app.html index 85c039de..0970b720 100644 --- a/store/templates/app.html +++ b/store/templates/app.html @@ -16,7 +16,7 @@ loading="lazy" class="h-12 w-12 rounded-lg object-cover shadow-sm mt-1" > -

12 %}text-2xl{% else %}text-3xl{% endif %} font-bold text-gray-900">{{ infos["manifest"]["name"] }}

+

12 %}text-2xl{% else %}text-3xl{% endif %} font-bold">{{ infos["manifest"]["name"] }}

{% if infos['category'] %} @@ -82,7 +82,7 @@ {{ _("Demo") }} {% endif %} - + Install
with
YunoHost
diff --git a/store/templates/base.html b/store/templates/base.html index 18e8fa22..0791df62 100644 --- a/store/templates/base.html +++ b/store/templates/base.html @@ -1,3 +1,9 @@ +{% if user and user.get('packaging_enabled') or request.endpoint in ["dash", "charts"] %} + {% set packaging_enabled = True %} +{% else %} + {% set packaging_enabled = False %} +{% endif %} + @@ -7,9 +13,16 @@ + - +
-
+
{% block main %} {% endblock %}
- diff --git a/store/templates/catalog.html b/store/templates/catalog.html index d07fd883..7beedddb 100644 --- a/store/templates/catalog.html +++ b/store/templates/catalog.html @@ -16,7 +16,7 @@ >
@@ -27,12 +27,12 @@ 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" >
-

+

{{ infos['manifest']['name'] }}

@@ -53,14 +53,16 @@
-

+

{{ infos['manifest']['description']|localize }}

{% if infos['category'] %} - + {{ catalog['categories'][infos['category']]['title']|localize|lower }} {% endif %} @@ -76,7 +78,7 @@ {% endblock %} {% block main %}
-

+

{{ _("Application Catalog") }}

@@ -89,8 +91,8 @@ type="text" id="search" placeholder="{{ _('Search for…') }}" - {% if init_search %}value="{{ init_search }}"{% endif %} - class="w-full rounded-md border-gray-200 shadow-sm sm:text-sm py-2 pe-10" + {% if request.args.get("search") %}value="{{ request.args.get("search") }}"{% endif %} + class="w-full sm:text-sm py-2 pe-10" > @@ -102,11 +104,11 @@
@@ -118,17 +120,17 @@
-
+