mirror of
https://github.com/YunoHost/yunodevtools.git
synced 2024-09-03 20:16:19 +02:00
appstore: draft app page with markdown description, screenshot, buttons for demo and vote
This commit is contained in:
parent
c6cfcfdc78
commit
6915740484
6 changed files with 131 additions and 11 deletions
44
store/app.py
44
store/app.py
|
@ -1,3 +1,4 @@
|
|||
import markdown
|
||||
import time
|
||||
import re
|
||||
import toml
|
||||
|
@ -13,6 +14,7 @@ from slugify import slugify
|
|||
from flask import Flask, send_from_directory, render_template, session, redirect, request
|
||||
from github import Github, InputGitAuthor
|
||||
|
||||
locale = "en"
|
||||
app = Flask(__name__, static_url_path='/assets', static_folder="assets")
|
||||
catalog = json.load(open("apps.json"))
|
||||
catalog['categories'] = {c['id']:c for c in catalog['categories']}
|
||||
|
@ -122,8 +124,48 @@ def browse_catalog(category_filter=None):
|
|||
@app.route('/app/<app_id>')
|
||||
def app_info(app_id):
|
||||
infos = catalog["apps"].get(app_id)
|
||||
if not infos:
|
||||
app_folder = os.path.join(config["APPS_CACHE"], app_id)
|
||||
if not infos or not os.path.exists(app_folder):
|
||||
return f"App {app_id} not found", 404
|
||||
|
||||
if os.path.exists(os.path.join(app_folder, "doc", f"DESCRIPTION_{locale}.md")):
|
||||
description_path = os.path.join(app_folder, "doc", f"DESCRIPTION_{locale}.md")
|
||||
elif os.path.exists(os.path.join(app_folder, "doc", "DESCRIPTION.md")):
|
||||
description_path = os.path.join(app_folder, "doc", "DESCRIPTION.md")
|
||||
else:
|
||||
description_path = None
|
||||
if description_path:
|
||||
with open(description_path) as f:
|
||||
infos["full_description_html"] = markdown.markdown(f.read())
|
||||
else:
|
||||
infos["full_description_html"] = infos['manifest']['description'][locale]
|
||||
|
||||
if os.path.exists(os.path.join(app_folder, "doc", f"PRE_INSTALL_{locale}.md")):
|
||||
pre_install_path = os.path.join(app_folder, "doc", f"PRE_INSTALL_{locale}.md")
|
||||
elif os.path.exists(os.path.join(app_folder, "doc", "PRE_INSTALL.md")):
|
||||
pre_install_path = os.path.join(app_folder, "doc", "PRE_INSTALL.md")
|
||||
else:
|
||||
pre_install_path = None
|
||||
if pre_install_path:
|
||||
with open(pre_install_path) as f:
|
||||
infos["pre_install_html"] = markdown.markdown(f.read())
|
||||
|
||||
infos["screenshot"] = None
|
||||
|
||||
screenshots_folder = os.path.join(app_folder, "doc", "screenshots")
|
||||
|
||||
if os.path.exists(screenshots_folder):
|
||||
with os.scandir(screenshots_folder) as it:
|
||||
for entry in it:
|
||||
ext = os.path.splitext(entry.name)[1].replace(".", "").lower()
|
||||
if entry.is_file() and ext in ("png", "jpg", "jpeg", "webp", "gif"):
|
||||
with open(entry.path, "rb") as img_file:
|
||||
data = base64.b64encode(img_file.read()).decode("utf-8")
|
||||
infos[
|
||||
"screenshot"
|
||||
] = f"data:image/{ext};charset=utf-8;base64,{data}"
|
||||
break
|
||||
|
||||
return render_template("app.html", user=session.get('user', {}), app_id=app_id, infos=infos)
|
||||
|
||||
|
||||
|
|
|
@ -2,3 +2,4 @@ Flask==2.3.2
|
|||
python-slugify
|
||||
PyGithub
|
||||
toml
|
||||
markdown
|
||||
|
|
|
@ -1,9 +1,55 @@
|
|||
{% extends "base.html" %}
|
||||
{% block main %}
|
||||
<div class="max-w-screen-lg mx-auto pt-5">
|
||||
<div class="max-w-screen-md mx-auto pt-5">
|
||||
|
||||
<h2>{{ app_id }}</h2>
|
||||
<span class="flex mb-3">
|
||||
<img {% if infos['logo_hash'] %}
|
||||
src="https://app.yunohost.org/default/v3/logos/{{ infos['logo_hash'] }}.png"
|
||||
{% else %}
|
||||
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"
|
||||
/>
|
||||
<h2 class="grow pl-2 pt-3 text-3xl font-bold text-gray-900">{{ infos["manifest"]["name"] }}</h2>
|
||||
<div class="mt-2">
|
||||
<a
|
||||
href="#"
|
||||
class="mr-3 inline-block group btn border text-violet-600 border-violet-500 hover:bg-violet-500 hover:text-white"
|
||||
>
|
||||
123 <i class="fa fa-star-o inline-block group-hover:hidden" aria-hidden="true"></i>
|
||||
<i class="fa fa-star hidden group-hover:inline-block" aria-hidden="true"></i>
|
||||
</a>
|
||||
{% if infos["manifest"]["upstream"]["demo"] %}
|
||||
<a
|
||||
class="btn btn-success inline-block"
|
||||
href="{{ infos["manifest"]["upstream"]["demo"] }}"
|
||||
>
|
||||
<i class="fa fa-external-link fa-fw" aria-hidden="true"></i>
|
||||
Try the demo
|
||||
</a>
|
||||
{% endif %}
|
||||
</div>
|
||||
</span>
|
||||
|
||||
<p>{{ infos }}</p>
|
||||
<p class="text-sm text-slate-500">Current version: {{ infos["manifest"]["version"] }}</p>
|
||||
{% if infos["potential_alternative_to"] %}
|
||||
<p class="text-sm text-slate-500">Potential alternative to: {{ infos["potential_alternative_to"]|join(', ') }}</p>
|
||||
{% endif %}
|
||||
|
||||
<div class="from-markdown">{{ infos["full_description_html"]|safe }}</div>
|
||||
|
||||
{% if infos["screenshot"] %}
|
||||
<img src="{{ infos["screenshot"] }}" />
|
||||
{% endif %}
|
||||
|
||||
|
||||
<p>{{ infos["category"] }}</p>
|
||||
<p>{{ infos["level"] }}</p>
|
||||
|
||||
<p>Antifeatures: {{ infos["anti_features"] }}</p>
|
||||
<p>{{ infos["manifest"]["integration"] }}</p>
|
||||
<p>{{ infos["manifest"]["upstream"] }}</p>
|
||||
<div class="from-markdown">{{ infos["pre_install_html"] | safe }}</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
|
|
@ -7,6 +7,38 @@
|
|||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<script src="{{ url_for('static', filename='tailwindcss.js') }}"></script>
|
||||
<link rel="stylesheet" href="{{ url_for('static', filename='fork-awesome.min.css') }}" rel="preload">
|
||||
<style type="text/tailwindcss">
|
||||
@layer utilities {
|
||||
.btn {
|
||||
@apply text-sm font-medium rounded-md px-4 py-2.5 transition;
|
||||
}
|
||||
.btn-sm {
|
||||
@apply text-xs font-medium rounded-md px-2 py-2 transition;
|
||||
}
|
||||
.btn-success {
|
||||
@apply text-white bg-green-500 hover:bg-green-700;
|
||||
}
|
||||
.btn-primary {
|
||||
@apply text-white bg-blue-500 hover:bg-blue-700;
|
||||
}
|
||||
.btn-primary-outline {
|
||||
@apply border text-blue-600 border-blue-500 hover:text-blue-400;
|
||||
}
|
||||
.from-markdown {
|
||||
@apply my-4;
|
||||
}
|
||||
.from-markdown p {
|
||||
@apply mb-2;
|
||||
}
|
||||
.from-markdown h3 {
|
||||
@apply text-xl mb-1 font-semibold;
|
||||
}
|
||||
.from-markdown ul {
|
||||
padding: revert;
|
||||
list-style: disc;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
@ -39,7 +71,7 @@
|
|||
<div class="flex items-center gap-4">
|
||||
<div class="sm:flex sm:gap-4">
|
||||
<a
|
||||
class="rounded-md border text-blue-600 border-blue-500 px-5 py-2.5 text-sm font-medium hover:text-blue-400 hidden md:block"
|
||||
class="btn btn-primary-outline hidden md:inline-block"
|
||||
href="https://yunohost.org/docs/"
|
||||
>
|
||||
<i class="fa fa-external-link fa-fw" aria-hidden="true"></i>
|
||||
|
@ -47,7 +79,7 @@
|
|||
</a>
|
||||
{% if not user %}
|
||||
<a
|
||||
class="rounded-md bg-blue-500 px-5 py-2.5 text-sm font-medium text-white transition hover:bg-blue-700 hidden md:block"
|
||||
class="btn btn-primary hidden md:inline-block"
|
||||
href="{{ url_for('login_using_discourse') }}"
|
||||
>
|
||||
Login using YunoHost's forum
|
||||
|
@ -63,7 +95,7 @@
|
|||
src="{{ user['avatar_url'] }}"
|
||||
class="h-10 w-10 rounded-full object-cover"
|
||||
/>
|
||||
<p class="ms-2 hidden text-left text-xs sm:block">
|
||||
<p class="ms-2 hidden text-left text-xs sm:inline-block">
|
||||
<strong class="block font-medium">{{ user['username'] }}</strong>
|
||||
</p>
|
||||
<i class="fa fa-caret-down fa-fw" aria-hidden="true"></i>
|
||||
|
|
|
@ -25,7 +25,7 @@
|
|||
|
||||
<a
|
||||
|
||||
class="inline-block rounded-md border text-blue-600 border-blue-500 px-4 pt-3 text-sm font-medium hover:bg-blue-500 hover:text-white"
|
||||
class="btn btn-primary-outline"
|
||||
href="{{ url_for('add_to_wishlist') }}"
|
||||
>
|
||||
<i class="fa fa-plus fa-fw" aria-hidden="true"></i>
|
||||
|
@ -83,12 +83,11 @@
|
|||
<td class="text-center max-w-[5em]">
|
||||
<a
|
||||
href="#"
|
||||
class="inline-block group rounded-md border text-violet-600 border-violet-500 px-2 py-2 text-xs font-medium hover:bg-violet-500 hover:text-white"
|
||||
class="inline-block group btn-sm border text-violet-600 border-violet-500 hover:bg-violet-500 hover:text-white"
|
||||
>
|
||||
123 <i class="fa fa-star-o inline-block group-hover:hidden" aria-hidden="true"></i>
|
||||
<i class="fa fa-star hidden group-hover:inline-block" aria-hidden="true"></i>
|
||||
</a>
|
||||
</a>
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
|
|
|
@ -66,7 +66,7 @@
|
|||
|
||||
<button
|
||||
type="submit"
|
||||
class="mx-auto block rounded-md border text-white bg-blue-500 px-4 mt-5 py-2 font-medium {% if user %}hover:bg-blue-700{% endif %}"
|
||||
class="block mx-auto btn btn-primary mt-5 {% if user %}hover:bg-blue-700{% endif %}"
|
||||
{% if not user %}disabled{% endif %}
|
||||
>
|
||||
Submit
|
||||
|
|
Loading…
Add table
Reference in a new issue