mirror of
https://github.com/YunoHost/apps.git
synced 2024-09-03 20:06:07 +02:00
appgenerator: simplify/rework the HTML/form structure using Flask-Bootstrap's macro
This commit is contained in:
parent
f6845e9580
commit
09edb1540a
3 changed files with 229 additions and 634 deletions
|
@ -13,6 +13,7 @@ from markupsafe import Markup # No longer imported from Flask
|
|||
|
||||
# Form libraries
|
||||
from flask_wtf import FlaskForm
|
||||
from flask_bootstrap import Bootstrap
|
||||
from wtforms import (
|
||||
StringField,
|
||||
RadioField,
|
||||
|
@ -42,6 +43,7 @@ from secrets import token_urlsafe
|
|||
|
||||
#### Create FLASK and Jinja Environments
|
||||
app = Flask(__name__)
|
||||
Bootstrap(app)
|
||||
app.config["SECRET_KEY"] = token_urlsafe(16) # Necessary for the form CORS
|
||||
cors = CORS(app)
|
||||
|
||||
|
@ -77,9 +79,10 @@ def markdown_file_to_html_string(file):
|
|||
|
||||
|
||||
## PHP forms
|
||||
class Form_PHP_Config(FlaskForm):
|
||||
class Form_PHP(FlaskForm):
|
||||
use_php = BooleanField("Nécessite PHP", default=False)
|
||||
php_config_file = SelectField(
|
||||
"Type de fichier PHP :",
|
||||
"Type de fichier PHP",
|
||||
choices=[
|
||||
(
|
||||
"php-fpm.conf",
|
||||
|
@ -102,7 +105,7 @@ class Form_PHP_Config(FlaskForm):
|
|||
# 'title': "Choisir un fichier permettant un paramétrage d'options complémentaires. C'est généralement recommandé."
|
||||
|
||||
php_config_file_content = TextAreaField(
|
||||
"Saisissez le contenu du fichier de configuration PHP :",
|
||||
"Saisissez le contenu du fichier de configuration PHP",
|
||||
validators=[Optional()],
|
||||
render_kw={
|
||||
"class": "form-control",
|
||||
|
@ -113,15 +116,11 @@ class Form_PHP_Config(FlaskForm):
|
|||
)
|
||||
|
||||
|
||||
class Form_PHP(Form_PHP_Config):
|
||||
use_php = BooleanField("Nécessite PHP", default=False)
|
||||
|
||||
|
||||
## NodeJS forms
|
||||
class Form_NodeJS(FlaskForm):
|
||||
use_nodejs = BooleanField("Nécessite NodeJS", default=False)
|
||||
use_nodejs_version = StringField(
|
||||
"Version de NodeJS :",
|
||||
"Version de NodeJS",
|
||||
render_kw={
|
||||
"placeholder": "20",
|
||||
"class": "form-control",
|
||||
|
@ -145,7 +144,7 @@ class Form_Python(FlaskForm):
|
|||
"Nécessite Python", default=False
|
||||
) ## TODO -> python3, python3-pip, python3-ven dependencies by default
|
||||
python_dependencies_type = SelectField(
|
||||
"Configuration des dépendances Python :",
|
||||
"Configuration des dépendances Python",
|
||||
choices=[
|
||||
("requirements.txt", Markup("Fichier <i>requirements.txt</i>")),
|
||||
("manual_list", "Liste manuelle"),
|
||||
|
@ -154,7 +153,7 @@ class Form_Python(FlaskForm):
|
|||
validators=[DataRequired(), Optional()],
|
||||
)
|
||||
python_requirements = TextAreaField(
|
||||
"La liste de dépendances inclue dans le fichier requirements.txt :",
|
||||
"La liste de dépendances inclue dans le fichier requirements.txt",
|
||||
render_kw={
|
||||
"class": "form-control",
|
||||
"style": "width: 50%;height:5.5em;min-height: 5.5em; max-height: 55em;flex-grow: 1;box-sizing: border-box;",
|
||||
|
@ -163,7 +162,7 @@ class Form_Python(FlaskForm):
|
|||
},
|
||||
)
|
||||
python_dependencies_list = StringField(
|
||||
"Liste de dépendances python :",
|
||||
"Liste de dépendances python",
|
||||
render_kw={
|
||||
"placeholder": "tensorflow uvicorn fastapi",
|
||||
"class": "form-control",
|
||||
|
@ -175,45 +174,33 @@ class GeneralInfos(FlaskForm):
|
|||
|
||||
app_id = StringField(
|
||||
Markup(
|
||||
"""Identifiant (id) de l'application <i class="grayed_hint">(en minuscule et sans espaces)</i> :"""
|
||||
"Identifiant (id) de l'application"
|
||||
),
|
||||
description="En minuscule et sans espace.",
|
||||
validators=[DataRequired(), Regexp("[a-z_1-9]+.*(?<!_ynh)$")],
|
||||
render_kw={
|
||||
"placeholder": "yunohost_awesome_app",
|
||||
"class": "form-control",
|
||||
"title": "Définir l'identifiant de l'application, utilisé pour le nom du dépôt Github",
|
||||
"placeholder": "my_super_app",
|
||||
},
|
||||
)
|
||||
|
||||
app_name = StringField(
|
||||
"Nom de l'application :",
|
||||
"Nom de l'application",
|
||||
description="Il s'agit du nom l'application, affiché dans les interfaces utilisateur·ice·s",
|
||||
validators=[DataRequired()],
|
||||
render_kw={
|
||||
"placeholder": "My Great App",
|
||||
"class": "form-control",
|
||||
"title": "Définir le nom de l'application, affiché dans l'interface",
|
||||
"placeholder": "My super App",
|
||||
},
|
||||
)
|
||||
|
||||
description_en = TextAreaField(
|
||||
"Description en quelques mots de l'application (en) :",
|
||||
"Description courte (en)",
|
||||
description="Expliquez en *quelques* (10~15) mots l'utilité de l'app ou ce qu'elle fait (l'objectif est de donner une idée grossière pour des utilisateurs qui naviguent dans un catalogue de 100+ apps)",
|
||||
validators=[DataRequired()],
|
||||
render_kw={
|
||||
"class": "form-control",
|
||||
"style": "resize: none;",
|
||||
"title": "Explain in *a few (10~15) words* the purpose of the app \\"
|
||||
"or what it actually does (it is meant to give a rough idea to users browsing a catalog of 100+ apps)",
|
||||
},
|
||||
)
|
||||
description_fr = TextAreaField(
|
||||
"Description en quelques mots de l'application (fr) :",
|
||||
"Description courte (fr)",
|
||||
description="Expliquez en *quelques* (10~15) mots l'utilité de l'app ou ce qu'elle fait (l'objectif est de donner une idée grossière pour des utilisateurs qui naviguent dans un catalogue de 100+ apps)",
|
||||
validators=[DataRequired()],
|
||||
render_kw={
|
||||
"class": "form-control",
|
||||
"style": "resize: none;",
|
||||
"title": "Expliquez en *quelques* (10~15) mots l'utilité de l'app \\"
|
||||
"ou ce qu'elle fait (l'objectif est de donner une idée grossière pour des utilisateurs qui naviguent dans un catalogue de 100+ apps)",
|
||||
},
|
||||
)
|
||||
|
||||
class IntegrationInfos(FlaskForm):
|
||||
|
@ -222,28 +209,24 @@ class IntegrationInfos(FlaskForm):
|
|||
version = StringField(
|
||||
"Version",
|
||||
validators=[Regexp("\d{1,4}.\d{1,4}(.\d{1,4})?(.\d{1,4})?~ynh\d+")],
|
||||
render_kw={"class": "form-control", "placeholder": "1.0~ynh1"},
|
||||
render_kw={"placeholder": "1.0~ynh1"},
|
||||
)
|
||||
|
||||
maintainers = StringField(
|
||||
"Mainteneur·euse de l'app YunoHost créée",
|
||||
render_kw={
|
||||
"class": "form-control",
|
||||
"placeholder": "Généralement vous mettez votre nom ici… Si vous êtes d'accord ;)",
|
||||
},
|
||||
description="Généralement vous mettez votre nom ici… Si vous êtes d'accord ;)"
|
||||
)
|
||||
|
||||
yunohost_required_version = StringField(
|
||||
"Minimum YunoHost version",
|
||||
description="Version minimale de Yunohost pour que l'application fonctionne.",
|
||||
render_kw={
|
||||
"class": "form-control",
|
||||
"placeholder": "11.1.21",
|
||||
"title": "Version minimale de Yunohost pour que l'application fonctionne.",
|
||||
},
|
||||
)
|
||||
|
||||
architectures = SelectMultipleField(
|
||||
"Architectures supportées :",
|
||||
"Architectures supportées",
|
||||
choices=[
|
||||
("all", "Toutes les architectures"),
|
||||
("amd64", "amd64"),
|
||||
|
@ -261,30 +244,26 @@ class IntegrationInfos(FlaskForm):
|
|||
)
|
||||
|
||||
ldap = SelectField(
|
||||
"L'app s'intègrera avec le LDAP (c-a-d pouvoir se connecter en utilisant ses identifiants YunoHost)",
|
||||
"L'app s'intègrera avec le LDAP",
|
||||
description="c-à-d pouvoir se connecter en utilisant ses identifiants YunoHost",
|
||||
choices=[
|
||||
("false", "False"),
|
||||
("true", "True"),
|
||||
("false", "No"),
|
||||
("true", "Yes"),
|
||||
("not_relevant", "Not relevant"),
|
||||
],
|
||||
default="not_relevant",
|
||||
validators=[DataRequired()],
|
||||
render_kw={
|
||||
"title": "Not to confuse with the 'sso' key: the 'ldap' key corresponds to wether or not a user *can* login on the app using its YunoHost credentials."
|
||||
},
|
||||
)
|
||||
sso = SelectField(
|
||||
"L'app s'intègrera avec le SSO (Single Sign On) de YunoHost (c-a-d être connecté automatiquement à l'app si connecté au portail YunoHost)",
|
||||
"L'app s'intègrera avec le SSO (Single Sign On) de YunoHost",
|
||||
description="c-à-d être connecté automatiquement à l'app si connecté au portail YunoHost",
|
||||
choices=[
|
||||
("false", "False"),
|
||||
("true", "True"),
|
||||
("false", "Yes"),
|
||||
("true", "No"),
|
||||
("not_relevant", "Not relevant"),
|
||||
],
|
||||
default="not_relevant",
|
||||
validators=[DataRequired()],
|
||||
render_kw={
|
||||
"title": "Not to confuse with the 'ldap' key: the 'sso' key corresponds to wether or not a user is *automatically logged-in* on the app when logged-in on the YunoHost portal."
|
||||
},
|
||||
)
|
||||
|
||||
|
||||
|
@ -292,48 +271,47 @@ class UpstreamInfos(FlaskForm):
|
|||
|
||||
license = StringField(
|
||||
"Licence",
|
||||
description="You should check this on the upstream repository. The expected format is a SPDX id listed in https://spdx.org/licenses/",
|
||||
validators=[DataRequired()],
|
||||
render_kw={"class": "form-control", "placeholder": "GPL"},
|
||||
)
|
||||
|
||||
website = StringField(
|
||||
"Site web officiel",
|
||||
description="Leave empty if there is no official website",
|
||||
validators=[URL(), Optional()],
|
||||
render_kw={
|
||||
"class": "form-control",
|
||||
"placeholder": "https://awesome-app-website.com",
|
||||
},
|
||||
)
|
||||
demo = StringField(
|
||||
"Démo officielle de l'app",
|
||||
description="Leave empty if there is no official demo",
|
||||
validators=[URL(), Optional()],
|
||||
render_kw={
|
||||
"class": "form-control",
|
||||
"placeholder": "https://awesome-app-website.com/demo",
|
||||
},
|
||||
)
|
||||
admindoc = StringField(
|
||||
"Documentation d'aministration",
|
||||
description="Leave empty if there is no official admin doc",
|
||||
validators=[URL(), Optional()],
|
||||
render_kw={
|
||||
"class": "form-control",
|
||||
"placeholder": "https://awesome-app-website.com/doc/admin",
|
||||
},
|
||||
)
|
||||
userdoc = StringField(
|
||||
"Documentation d'utilisation",
|
||||
description="Leave empty if there is no official user doc",
|
||||
validators=[URL(), Optional()],
|
||||
render_kw={
|
||||
"class": "form-control",
|
||||
"placeholder": "https://awesome-app-website.com/doc/user",
|
||||
},
|
||||
)
|
||||
code = StringField(
|
||||
"Dépôt de code",
|
||||
validators=[URL(), Optional()],
|
||||
validators=[URL(), DataRequired()],
|
||||
render_kw={
|
||||
"class": "form-control",
|
||||
"placeholder": "https://awesome-app-website.com/get-the-code",
|
||||
"placeholder": "https://some.git.forge/org/app",
|
||||
},
|
||||
)
|
||||
|
||||
|
@ -359,12 +337,12 @@ class InstallQuestions(FlaskForm):
|
|||
default=False,
|
||||
)
|
||||
|
||||
# admin_password_help_message = BooleanField("TODO :", default=False,
|
||||
# admin_password_help_message = BooleanField("TODO ", default=False,
|
||||
# render_kw={"class": "",
|
||||
# "title": "TODO"})
|
||||
|
||||
language = SelectMultipleField(
|
||||
"Langues supportées :",
|
||||
"Langues supportées",
|
||||
choices=[
|
||||
("_", "None / not relevant"),
|
||||
("en", "English"),
|
||||
|
@ -394,7 +372,6 @@ class Resources(FlaskForm):
|
|||
"Code source ou exécutable de l'application",
|
||||
validators=[DataRequired(), URL()],
|
||||
render_kw={
|
||||
"class": "form-control",
|
||||
"placeholder": "https://github.com/foo/bar/archive/refs/tags/v1.2.3.tar.gz",
|
||||
},
|
||||
)
|
||||
|
@ -402,17 +379,14 @@ class Resources(FlaskForm):
|
|||
"Checksum sha256 des sources",
|
||||
validators=[DataRequired(), Length(min=64, max=64)],
|
||||
render_kw={
|
||||
"class": "form-control",
|
||||
"placeholder": "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef",
|
||||
},
|
||||
)
|
||||
|
||||
auto_update = BooleanField(
|
||||
"Activer le robot de mise à jour automatique des sources",
|
||||
description="Si le logiciel est disponible sur github et publie des releases ou des tags pour ses nouvelles versions, un robot proposera automatiquement des mises à jour de l'url et de la checksum.",
|
||||
default=False,
|
||||
render_kw={
|
||||
"title": "Si le logiciel est disponible sur github et publie des releases ou des tags pour ses nouvelles versions, un robot proposera automatiquement des mises à jour de l'url et de la checksum."
|
||||
},
|
||||
)
|
||||
|
||||
## TODO
|
||||
|
@ -426,22 +400,20 @@ class Resources(FlaskForm):
|
|||
|
||||
|
||||
apt_dependencies = StringField(
|
||||
"Dépendances à installer via apt (séparées par des virgules)",
|
||||
"Dépendances à installer via apt (séparées par des virgules et/ou espaces)",
|
||||
render_kw={
|
||||
"placeholder": "foo foo2.1-ext somerandomdep",
|
||||
"class": "form-control",
|
||||
"placeholder": "foo, bar2.1-ext, libwat",
|
||||
},
|
||||
)
|
||||
|
||||
database = SelectField(
|
||||
"Initialiser une base de données :",
|
||||
"Initialiser une base de données",
|
||||
choices=[
|
||||
("false", "Non"),
|
||||
("mysql", "MySQL/MariaDB"),
|
||||
("postgresql", "PostgreSQL"),
|
||||
],
|
||||
default="false",
|
||||
render_kw={"title": "L'application nécessite-t-elle une base de données ?"},
|
||||
)
|
||||
|
||||
system_user = BooleanField(
|
||||
|
@ -460,7 +432,8 @@ class Resources(FlaskForm):
|
|||
)
|
||||
|
||||
ports = BooleanField(
|
||||
"L'app aura besoin d'un port interne pour le reverse proxy entre nginx et l'app (généralement pas nécessaire pour les apps statiques ou php, mais généralement nécessaire pour les apps de type nodejs, python, ruby, ...)",
|
||||
"L'app aura besoin d'un port interne pour le reverse proxy entre nginx et l'app",
|
||||
description="(généralement pas nécessaire pour les apps statiques ou php, mais généralement nécessaire pour les apps de type nodejs, python, ruby, ...)",
|
||||
)
|
||||
|
||||
## Main form
|
||||
|
@ -469,12 +442,15 @@ class GeneratorForm(
|
|||
Form_PHP, Form_NodeJS, Form_Python
|
||||
):
|
||||
generator_mode = SelectField(
|
||||
"Mode du générateur :",
|
||||
"Mode du générateur",
|
||||
description="En mode tutoriel, l'application générée contiendra des commentaires additionnels pour faciliter la compréhension. En version épurée, l'application générée ne contiendra que le minimum nécessaire.",
|
||||
choices=[("false", "Version épurée"), ("true", "Version tutoriel")],
|
||||
default="true",
|
||||
validators=[DataRequired()],
|
||||
)
|
||||
|
||||
|
||||
|
||||
supports_change_url = BooleanField(
|
||||
"L'application autorise le changement d'adresse (changement de domaine ou de chemin)",
|
||||
default=True,
|
||||
|
@ -484,7 +460,7 @@ class GeneratorForm(
|
|||
)
|
||||
|
||||
use_logrotate = BooleanField(
|
||||
"Utiliser logrotate pour gérer les journaux :",
|
||||
"Utiliser logrotate pour gérer les journaux",
|
||||
default=True,
|
||||
render_kw={
|
||||
"title": "Si l'application genère des journaux (log), cette option permet d'en gérer l'archivage. Recommandé."
|
||||
|
@ -493,21 +469,21 @@ class GeneratorForm(
|
|||
# TODO : specify custom log file
|
||||
# custom_log_file = "/var/log/$app/$app.log" "/var/log/nginx/${domain}-error.log"
|
||||
use_fail2ban = BooleanField(
|
||||
"Protéger l'application des attaques par force brute (via fail2ban) :",
|
||||
"Protéger l'application des attaques par force brute (via fail2ban)",
|
||||
default=True,
|
||||
render_kw={
|
||||
"title": "Si l'application genère des journaux (log) d'erreurs de connexion, cette option permet de bannir automatiquement les IP au bout d'un certain nombre d'essais de mot de passe. Recommandé."
|
||||
},
|
||||
)
|
||||
use_cron = BooleanField(
|
||||
"Ajouter une tâche CRON pour cette application :",
|
||||
"Ajouter une tâche CRON pour cette application",
|
||||
default=False,
|
||||
render_kw={
|
||||
"title": "Créer une tâche cron pour gérer des opérations périodiques de l'application."
|
||||
},
|
||||
)
|
||||
cron_config_file = TextAreaField(
|
||||
"Saisissez le contenu du fichier CRON :",
|
||||
"Saisissez le contenu du fichier CRON",
|
||||
validators=[Optional()],
|
||||
render_kw={
|
||||
"class": "form-control",
|
||||
|
@ -517,7 +493,7 @@ class GeneratorForm(
|
|||
)
|
||||
|
||||
fail2ban_regex = StringField(
|
||||
"Expression régulière pour fail2ban :",
|
||||
"Expression régulière pour fail2ban",
|
||||
# Regex to match into the log for a failed login
|
||||
validators=[Optional()],
|
||||
render_kw={
|
||||
|
@ -528,7 +504,7 @@ class GeneratorForm(
|
|||
)
|
||||
|
||||
nginx_config_file = TextAreaField(
|
||||
"Saisissez le contenu du fichier de configuration du serveur NGINX :",
|
||||
"Saisissez le contenu du fichier de configuration du serveur NGINX",
|
||||
validators=[Optional()],
|
||||
render_kw={
|
||||
"class": "form-control",
|
||||
|
@ -539,14 +515,14 @@ class GeneratorForm(
|
|||
)
|
||||
|
||||
use_systemd_service = BooleanField(
|
||||
"Utiliser un service système (via systemd) pour gérer le fonctionnement de l'application :",
|
||||
"Utiliser un service système (via systemd) pour gérer le fonctionnement de l'application ",
|
||||
default=False,
|
||||
render_kw={
|
||||
"title": "Un service systemd s'occupera de démarrer l'application avec le système, et permettra de l'arrêter ou la redémarrer. Recommandé."
|
||||
},
|
||||
)
|
||||
systemd_config_file = TextAreaField(
|
||||
"Saisissez le contenu du fichier de configuration du service SystemD :",
|
||||
"Saisissez le contenu du fichier de configuration du service SystemD",
|
||||
validators=[Optional()],
|
||||
render_kw={
|
||||
"class": "form-control",
|
||||
|
@ -555,7 +531,7 @@ class GeneratorForm(
|
|||
},
|
||||
)
|
||||
systemd_service_description = StringField(
|
||||
"Description du service de l'application :",
|
||||
"Description du service de l'application",
|
||||
validators=[Optional()],
|
||||
render_kw={
|
||||
"placeholder": "A short description of the app",
|
||||
|
@ -566,14 +542,15 @@ class GeneratorForm(
|
|||
)
|
||||
|
||||
use_custom_config_file = BooleanField(
|
||||
"Utiliser un fichier de configuration personnalisé :",
|
||||
"Utiliser un fichier de configuration personnalisé ",
|
||||
default=False,
|
||||
render_kw={
|
||||
"title": "Est-ce que l'application nécessite un fichier de configuration personnalisé ? (du type .env, config.json, parameters.yaml, …)"
|
||||
},
|
||||
)
|
||||
|
||||
custom_config_file = StringField(
|
||||
"Nom du fichier à utiliser :",
|
||||
"Nom du fichier à utiliser",
|
||||
validators=[Optional()],
|
||||
render_kw={
|
||||
"placeholder": "config.json",
|
||||
|
@ -584,7 +561,7 @@ class GeneratorForm(
|
|||
)
|
||||
|
||||
custom_config_file_content = TextAreaField(
|
||||
"Saisissez le contenu du fichier de configuration personnalisé :",
|
||||
"Saisissez le contenu du fichier de configuration personnalisé",
|
||||
validators=[Optional()],
|
||||
render_kw={
|
||||
"class": "form-control",
|
||||
|
|
|
@ -1,316 +1,17 @@
|
|||
:root {
|
||||
color-scheme:light;
|
||||
--yiq-contrasted-threshold: 150;
|
||||
--white: hsl(0, 0%, 100%);
|
||||
--white-h: 0;
|
||||
--white-s: 0%;
|
||||
--white-l: 100%;
|
||||
--black: hsl(0, 0%, 0%);
|
||||
--black-h: 0;
|
||||
--black-s: 0%;
|
||||
--black-l: 0%;
|
||||
--blue: hsl(211, 64%, 50%);
|
||||
--blue-h: 211;
|
||||
--blue-s: 64%;
|
||||
--blue-l: 50%;
|
||||
--indigo: hsl(263, 90%, 51%);
|
||||
--indigo-h: 263;
|
||||
--indigo-s: 90%;
|
||||
--indigo-l: 51%;
|
||||
--purple: hsl(280, 61%, 50%);
|
||||
--purple-h: 280;
|
||||
--purple-s: 61%;
|
||||
--purple-l: 50%;
|
||||
--pink: hsl(332, 79%, 58%);
|
||||
--pink-h: 332;
|
||||
--pink-s: 79%;
|
||||
--pink-l: 58%;
|
||||
--red: hsl(354, 70%, 54%);
|
||||
--red-h: 354;
|
||||
--red-s: 70%;
|
||||
--red-l: 54%;
|
||||
--orange: hsl(27, 98%, 54%);
|
||||
--orange-h: 27;
|
||||
--orange-s: 98%;
|
||||
--orange-l: 54%;
|
||||
--yellow: hsl(45, 100%, 66%);
|
||||
--yellow-h: 45;
|
||||
--yellow-s: 100%;
|
||||
--yellow-l: 66%;
|
||||
--green: hsl(134, 61%, 41%);
|
||||
--green-h: 134;
|
||||
--green-s: 61%;
|
||||
--green-l: 41%;
|
||||
--teal: hsl(162, 73%, 46%);
|
||||
--teal-h: 162;
|
||||
--teal-s: 73%;
|
||||
--teal-l: 46%;
|
||||
--cyan: hsl(188, 78%, 41%);
|
||||
--cyan-h: 188;
|
||||
--cyan-s: 78%;
|
||||
--cyan-l: 41%;
|
||||
--gray-100: hsl(210, 17%, 98%);
|
||||
--gray-100-h: 210;
|
||||
--gray-100-s: 17%;
|
||||
--gray-100-l: 98%;
|
||||
--gray-200: hsl(210, 16%, 93%);
|
||||
--gray-200-h: 210;
|
||||
--gray-200-s: 16%;
|
||||
--gray-200-l: 93%;
|
||||
--gray-300: hsl(210, 14%, 89%);
|
||||
--gray-300-h: 210;
|
||||
--gray-300-s: 14%;
|
||||
--gray-300-l: 89%;
|
||||
--gray-400: hsl(210, 14%, 83%);
|
||||
--gray-400-h: 210;
|
||||
--gray-400-s: 14%;
|
||||
--gray-400-l: 83%;
|
||||
--gray-500: hsl(210, 11%, 71%);
|
||||
--gray-500-h: 210;
|
||||
--gray-500-s: 11%;
|
||||
--gray-500-l: 71%;
|
||||
--gray-600: hsl(208, 7%, 46%);
|
||||
--gray-600-h: 208;
|
||||
--gray-600-s: 7%;
|
||||
--gray-600-l: 46%;
|
||||
--gray-700: hsl(210, 9%, 31%);
|
||||
--gray-700-h: 210;
|
||||
--gray-700-s: 9%;
|
||||
--gray-700-l: 31%;
|
||||
--gray-800: hsl(210, 10%, 23%);
|
||||
--gray-800-h: 210;
|
||||
--gray-800-s: 10%;
|
||||
--gray-800-l: 23%;
|
||||
--gray-900: hsl(210, 11%, 15%);
|
||||
--gray-900-h: 210;
|
||||
--gray-900-s: 11%;
|
||||
--gray-900-l: 15%
|
||||
.form-horizontal .form-group {
|
||||
margin-left: 0;
|
||||
margin-right: 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
h1,.h1 {
|
||||
font-size:2.25rem
|
||||
align="center";
|
||||
h2 {
|
||||
font-weight: bold;
|
||||
font-size: 1.3em !important;
|
||||
}
|
||||
|
||||
h2, .h2 {
|
||||
font-size: 1.35rem;
|
||||
.checkbox {
|
||||
margin-bottom: 15px !important;
|
||||
}
|
||||
|
||||
h3, .h3 {
|
||||
font-size: 1.26rem;
|
||||
.checkbox label {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
h1,
|
||||
h2,
|
||||
h3,
|
||||
h4,
|
||||
h5,
|
||||
h6 {
|
||||
margin-top:.8rem;
|
||||
margin-bottom:.2rem;
|
||||
font-weight:500;
|
||||
line-height:1.2;
|
||||
}
|
||||
|
||||
body {
|
||||
/* font-family: 'source_sans_proregular'; */
|
||||
font-family: FiraGO,Fira Sans,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,Noto Sans,sans-serif,"Apple Color Emoji","Segoe UI Emoji",Segoe UI Symbol,"Noto Color Emoji";
|
||||
font-size: 1em;
|
||||
line-height: 2.2;
|
||||
color: var(--gray-900);
|
||||
text-align: left;
|
||||
|
||||
width: 100%;
|
||||
padding-right: 15px;
|
||||
padding-left: 15px;
|
||||
margin-right: auto;
|
||||
margin-left: auto;
|
||||
max-width: 85%;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
.message {
|
||||
padding: 10px;
|
||||
margin: 5px;
|
||||
background-color: #2980b9;
|
||||
color:#FFF;
|
||||
}
|
||||
|
||||
.text-secondary {
|
||||
color: var(--gray-600) !important;
|
||||
}
|
||||
|
||||
.alert {
|
||||
padding: 20px;
|
||||
margin: 5px;
|
||||
color: #970020;
|
||||
background-color: #ffd5de;
|
||||
}
|
||||
|
||||
.grayed_hint {
|
||||
color: darkgray;
|
||||
}
|
||||
|
||||
.box {
|
||||
border:20px solid black
|
||||
padding: 50px auto;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.code-block {
|
||||
background-color: #282c34;
|
||||
color: #ebf2ff;
|
||||
border-radius: 5px;
|
||||
padding: 10px;
|
||||
|
||||
overflow: auto;
|
||||
height: 400px;
|
||||
|
||||
white-space: pre;
|
||||
|
||||
font-family: 'Courier New', Courier, monospace;
|
||||
font-size: 14px;
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
|
||||
|
||||
.btn {
|
||||
display:inline-block;
|
||||
font-weight:400;
|
||||
color:var(--gray-900);
|
||||
text-align:center;
|
||||
vertical-align:middle;
|
||||
user-select:none;
|
||||
background-color:transparent;
|
||||
border:1px solid transparent;
|
||||
padding:.375rem .75rem;
|
||||
font-size:.9rem;
|
||||
line-height:1.5;
|
||||
border-radius:.25rem;
|
||||
transition:color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out
|
||||
}
|
||||
|
||||
.btn-primary {
|
||||
color:hsla(0,0%,calc(-100 * (var(--blue-l) - calc(calc(var(--yiq-contrasted-threshold) / 2.56) * 1%))),1);
|
||||
background-color:var(--blue);
|
||||
border-color:var(--blue);
|
||||
font-size: larger;
|
||||
}
|
||||
.btn-primary:hover {
|
||||
color:hsla(0,0%,calc(-100 * (calc(var(--blue-l) + -7.5%) - calc(calc(var(--yiq-contrasted-threshold) / 2.56) * 1%))),1);
|
||||
background-color:hsla(var(--blue-h),var(--blue-s),calc(var(--blue-l) + -7.5%),var(--blue-a, 1));
|
||||
border-color:hsla(var(--blue-h),var(--blue-s),calc(var(--blue-l) + -10%),var(--blue-a, 1))
|
||||
}
|
||||
.btn-primary:focus,
|
||||
.btn-primary.focus {
|
||||
color:hsla(0,0%,calc(-100 * (calc(var(--blue-l) + -7.5%) - calc(calc(var(--yiq-contrasted-threshold) / 2.56) * 1%))),1);
|
||||
background-color:hsla(var(--blue-h),var(--blue-s),calc(var(--blue-l) + -7.5%),var(--blue-a, 1));
|
||||
border-color:hsla(var(--blue-h),var(--blue-s),calc(var(--blue-l) + -10%),var(--blue-a, 1));
|
||||
box-shadow:0 0 0 .2rem hsla(calc((0 + var(--blue-h)) / 2),calc((0% + var(--blue-s)) / 2),calc((calc(-100 * (var(--blue-l) - calc(calc(var(--yiq-contrasted-threshold) / 2.56) * 1%))) + var(--blue-l)) / 2),.5)
|
||||
}
|
||||
.btn-primary.disabled,
|
||||
.btn-primary:disabled {
|
||||
color:hsla(0,0%,calc(-100 * (var(--blue-l) - calc(calc(var(--yiq-contrasted-threshold) / 2.56) * 1%))),1);
|
||||
background-color:var(--blue);
|
||||
border-color:var(--blue)
|
||||
}
|
||||
|
||||
.btn-center {
|
||||
margin-left:auto;
|
||||
margin-right:auto;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.btn-sm,
|
||||
.btn-group-sm>.btn {
|
||||
padding:.25rem .5rem;
|
||||
//font-size:.7875rem;
|
||||
line-height:1.5;
|
||||
border-radius:.2rem;
|
||||
}
|
||||
|
||||
|
||||
.form-control {
|
||||
#display: block;
|
||||
#width: 100%;
|
||||
#height: calc(1.5em + .75rem + 2px);
|
||||
padding: .375rem .75rem;
|
||||
padding-right: 0.5rem;
|
||||
margin-left:0.75rem;
|
||||
font-size: .9rem;
|
||||
font-weight: 400;
|
||||
line-height: 1.5;
|
||||
color: var(--gray-700);
|
||||
background-color: var(--white);
|
||||
background-clip: padding-box;
|
||||
border: 1px solid var(--gray-400);
|
||||
border-radius: .25rem;
|
||||
transition: border-color .15s ease-in-out,box-shadow .15s ease-in-out;
|
||||
}
|
||||
.form-control.is-invalid {
|
||||
border-color: var(--red);
|
||||
padding-right: calc(1.5em + .75rem) !important;
|
||||
background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' fill='none' stroke='var%28--red%29' viewBox='0 0 12 12'%3e%3ccircle cx='6' cy='6' r='4.5'/%3e%3cpath stroke-linejoin='round' d='M5.8 3.6h.4L6 6.5z'/%3e%3ccircle cx='6' cy='8.2' r='.6' fill='var%28--red%29' stroke='none'/%3e%3c/svg%3e");
|
||||
background-repeat: no-repeat;
|
||||
background-position: right calc(.375em + .1875rem) center;
|
||||
background-size: calc(.75em + .375rem) calc(.75em + .375rem);
|
||||
}
|
||||
|
||||
|
||||
|
||||
.custom-select {
|
||||
|
||||
display: inline-block;
|
||||
width: 100%;
|
||||
height: calc(1.5em + .75rem + 2px);
|
||||
padding: .375rem 1.75rem .375rem .75rem;
|
||||
font-size: .9rem;
|
||||
font-weight: 400;
|
||||
line-height: 1.5;
|
||||
color: var(--gray-700);
|
||||
vertical-align: middle;
|
||||
background: var(--white) url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='4' height='5' viewBox='0 0 4 5'%3e%3cpath fill='var%28--gray-800%29' d='M2 0L0 2h4zm0 5L0 3h4z'/%3e%3c/svg%3e") right .75rem center/8px 10px no-repeat;
|
||||
border: 1px solid var(--gray-400);
|
||||
border-radius: .25rem;
|
||||
appearance: none;
|
||||
|
||||
}
|
||||
|
||||
|
||||
.nav {
|
||||
display:flex;
|
||||
flex-wrap:wrap;
|
||||
padding-left:0;
|
||||
margin-bottom:0;
|
||||
list-style:none
|
||||
}
|
||||
.nav-tabs .nav-item.show .nav-link {
|
||||
color:var(--gray-700);
|
||||
background-color:var(--white);
|
||||
border-color:var(--gray-300) var(--gray-300) var(--white)
|
||||
}
|
||||
|
||||
nav a {
|
||||
margin-left: 50px;
|
||||
// text-decoration: none; // removing links underline is a bad idea
|
||||
}
|
||||
|
||||
footer .nav-item:before {
|
||||
/* content:"\2022"; */
|
||||
width:1rem;
|
||||
display:inline-block;
|
||||
margin-left:-1.15rem;
|
||||
padding-top:1rem!important;
|
||||
margin-top:auto!important;
|
||||
}
|
||||
|
||||
|
||||
.test {
|
||||
color:red;
|
||||
}
|
|
@ -1,9 +1,17 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<link rel="stylesheet" type="text/css" href="{{ url_for('static', filename='stylesheet.css') }}">
|
||||
{% import "bootstrap/wtf.html" as wtf %}
|
||||
|
||||
{% extends "bootstrap/base.html" %}
|
||||
|
||||
{% block title %}
|
||||
YunoHost app generator
|
||||
{% endblock %}
|
||||
|
||||
{% block styles %}
|
||||
{{super()}}
|
||||
<link rel="stylesheet" href="{{url_for('.static', filename='stylesheet.css')}}">
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<script>
|
||||
function showForm(element, type) {
|
||||
if (type == 'PHP') {
|
||||
|
@ -136,52 +144,51 @@
|
|||
|
||||
function download_zip() {
|
||||
|
||||
var xhr = new XMLHttpRequest();
|
||||
var xhr = new XMLHttpRequest();
|
||||
|
||||
// retrieve variables
|
||||
template_manifest_content = encodeURIComponent( {{ template_manifest_content | safe |tojson }} );
|
||||
template_install_content = encodeURIComponent( {{ template_install_content | safe |tojson }} );
|
||||
template_remove_content = encodeURIComponent( {{ template_remove_content | safe |tojson }} );
|
||||
template_backup_content = encodeURIComponent( {{ template_backup_content | safe |tojson }} );
|
||||
template_restore_content = encodeURIComponent( {{ template_restore_content | safe |tojson }} );
|
||||
template_upgrade_content = encodeURIComponent( {{ template_upgrade_content | safe |tojson }} );
|
||||
template_config_content = encodeURIComponent( {{ template_config_content | safe |tojson }} );
|
||||
template_change_url_content = encodeURIComponent( {{ template_change_url_content | safe |tojson }} );
|
||||
|
||||
// retrieve variables
|
||||
template_manifest_content = encodeURIComponent( {{ template_manifest_content | safe |tojson }} );
|
||||
template_install_content = encodeURIComponent( {{ template_install_content | safe |tojson }} );
|
||||
template_remove_content = encodeURIComponent( {{ template_remove_content | safe |tojson }} );
|
||||
template_backup_content = encodeURIComponent( {{ template_backup_content | safe |tojson }} );
|
||||
template_restore_content = encodeURIComponent( {{ template_restore_content | safe |tojson }} );
|
||||
template_upgrade_content = encodeURIComponent( {{ template_upgrade_content | safe |tojson }} );
|
||||
template_config_content = encodeURIComponent( {{ template_config_content | safe |tojson }} );
|
||||
template_change_url_content = encodeURIComponent( {{ template_change_url_content | safe |tojson }} );
|
||||
custom_config_file = encodeURIComponent( {{ parameters['custom_config_file'] | safe |tojson }} );
|
||||
custom_config_file_content = encodeURIComponent( {{ parameters['custom_config_file_content'] | safe |tojson }} );
|
||||
systemd_config_file = encodeURIComponent( {{ parameters['systemd_config_file'] | safe |tojson }} );
|
||||
nginx_config_file = encodeURIComponent( {{ parameters['nginx_config_file'] | safe |tojson }} );
|
||||
cron_config_file = encodeURIComponent( {{ parameters['cron_config_file'] | safe |tojson }} );
|
||||
use_php = encodeURIComponent( "{{ parameters['use_php'] | safe }}" );
|
||||
php_config_file = encodeURIComponent( {{ parameters['php_config_file'] | safe |tojson }} );
|
||||
php_config_file_content = encodeURIComponent( {{ parameters['php_config_file_content'] | safe |tojson }} );
|
||||
|
||||
custom_config_file = encodeURIComponent( {{ parameters['custom_config_file'] | safe |tojson }} );
|
||||
custom_config_file_content = encodeURIComponent( {{ parameters['custom_config_file_content'] | safe |tojson }} );
|
||||
systemd_config_file = encodeURIComponent( {{ parameters['systemd_config_file'] | safe |tojson }} );
|
||||
nginx_config_file = encodeURIComponent( {{ parameters['nginx_config_file'] | safe |tojson }} );
|
||||
cron_config_file = encodeURIComponent( {{ parameters['cron_config_file'] | safe |tojson }} );
|
||||
use_php = encodeURIComponent( "{{ parameters['use_php'] | safe }}" );
|
||||
php_config_file = encodeURIComponent( {{ parameters['php_config_file'] | safe |tojson }} );
|
||||
php_config_file_content = encodeURIComponent( {{ parameters['php_config_file_content'] | safe |tojson }} );
|
||||
// pass the variables back into the python code
|
||||
|
||||
// pass the variables back into the python code
|
||||
//var url = '/download_as_zip?app_id=' + '{{ parameters['app_id'] }}' + '&template_manifest_content=' + template_manifest_content + '&template_install_content=' + template_install_content + '&template_remove_content=' + template_remove_content + '&template_backup_content=' + template_backup_content + '&template_restore_content=' + template_restore_content + '&template_upgrade_content=' + template_upgrade_content + '&template_config_content=' + template_config_content + '&template_change_url_content=' + template_change_url_content + '&custom_config_file=' + custom_config_file+ '&custom_config_file_content=' + custom_config_file_content + '&nginx_config_file=' + nginx_config_file + '&systemd_config_file=' + systemd_config_file + '&use_php=' + use_php + '&php_config_file=' + php_config_file + '&php_config_file_content=' + php_config_file_content;
|
||||
|
||||
//var url = '/download_as_zip?app_id=' + '{{ parameters['app_id'] }}' + '&template_manifest_content=' + template_manifest_content + '&template_install_content=' + template_install_content + '&template_remove_content=' + template_remove_content + '&template_backup_content=' + template_backup_content + '&template_restore_content=' + template_restore_content + '&template_upgrade_content=' + template_upgrade_content + '&template_config_content=' + template_config_content + '&template_change_url_content=' + template_change_url_content + '&custom_config_file=' + custom_config_file+ '&custom_config_file_content=' + custom_config_file_content + '&nginx_config_file=' + nginx_config_file + '&systemd_config_file=' + systemd_config_file + '&use_php=' + use_php + '&php_config_file=' + php_config_file + '&php_config_file_content=' + php_config_file_content;
|
||||
|
||||
var formData = new FormData();
|
||||
console.log(formData)
|
||||
formData.append('app_id', "{{ parameters['app_id'] }}");
|
||||
console.log(formData)
|
||||
//formData.append('template_manifest_content', template_manifest_content);
|
||||
//formData.append('template_install_content', template_install_content);
|
||||
//formData.append('template_remove_content', template_remove_content);
|
||||
//formData.append('template_backup_content', template_backup_content);
|
||||
//formData.append('template_restore_content', template_restore_content);
|
||||
//formData.append('template_upgrade_content', template_upgrade_content);
|
||||
//formData.append('template_config_content', template_config_content);
|
||||
formData.append('custom_config_file', custom_config_file);
|
||||
formData.append('custom_config_file_content', custom_config_file_content);
|
||||
formData.append('systemd_config_file', systemd_config_file);
|
||||
formData.append('nginx_config_file', nginx_config_file);
|
||||
formData.append('cron_config_file', cron_config_file);
|
||||
formData.append('use_php', use_php);
|
||||
formData.append('php_config_file', php_config_file);
|
||||
formData.append('php_config_file_content', php_config_file_content);
|
||||
var url = '/download_zip?' + new URLSearchParams(formData).toString()
|
||||
var formData = new FormData();
|
||||
console.log(formData)
|
||||
formData.append('app_id', "{{ parameters['app_id'] }}");
|
||||
console.log(formData)
|
||||
//formData.append('template_manifest_content', template_manifest_content);
|
||||
//formData.append('template_install_content', template_install_content);
|
||||
//formData.append('template_remove_content', template_remove_content);
|
||||
//formData.append('template_backup_content', template_backup_content);
|
||||
//formData.append('template_restore_content', template_restore_content);
|
||||
//formData.append('template_upgrade_content', template_upgrade_content);
|
||||
//formData.append('template_config_content', template_config_content);
|
||||
formData.append('custom_config_file', custom_config_file);
|
||||
formData.append('custom_config_file_content', custom_config_file_content);
|
||||
formData.append('systemd_config_file', systemd_config_file);
|
||||
formData.append('nginx_config_file', nginx_config_file);
|
||||
formData.append('cron_config_file', cron_config_file);
|
||||
formData.append('use_php', use_php);
|
||||
formData.append('php_config_file', php_config_file);
|
||||
formData.append('php_config_file_content', php_config_file_content);
|
||||
var url = '/download_zip?' + new URLSearchParams(formData).toString()
|
||||
|
||||
xhr.open('GET', url, true);
|
||||
//xhr.open('GET', '/download_as_zip', true);
|
||||
|
@ -212,184 +219,119 @@
|
|||
console.log(xhr.status)
|
||||
}
|
||||
</script>
|
||||
<title>YunoHost app generator</title>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<!--
|
||||
<h1>TODO nav bar ?</h1>
|
||||
<div class="container" style="max-width: 800px;">
|
||||
<h1 class="message text-center">Formulaire de génération d'une application Yunohost</h1>
|
||||
|
||||
<br>
|
||||
<ul id="navigation">
|
||||
{% for item in navigation %}
|
||||
<li><a href="{{ item.href }}">{{ item.caption }}</a></li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
-->
|
||||
|
||||
<h1 class="message" style="text-align:center">Formulaire de génération d'une application Yunohost</h1>
|
||||
<form id="main-form" method="POST">
|
||||
<form id="main-form" class="form form-horizontal" method="POST" role="form">
|
||||
{{ main_form.hidden_tag() }}
|
||||
{{ wtf.form_errors(main_form, hiddens="only") }}
|
||||
|
||||
{{ wtf.form_field(main_form.generator_mode) }}
|
||||
|
||||
{{ main_form.generator_mode.label }} {{ main_form.generator_mode() }}
|
||||
{# TODO : this doesn't work, should be changed on the fly. Is it worth the trouble ?
|
||||
{% if main_form.generator_mode %}
|
||||
L'application générée contiendra des commentaires additionnels pour faciliter la compréhension
|
||||
{% else %}
|
||||
L'application générée ne contiendra que le minimum nécessaire
|
||||
{% endif %}
|
||||
<br>
|
||||
#}
|
||||
<br>
|
||||
<span><i class="grayed_hint">En mode tutoriel, l'application générée contiendra des commentaires additionnels pour faciliter la compréhension. En version épurée, l'application générée ne contiendra que le minimum nécessaire.</i></span>
|
||||
|
||||
|
||||
|
||||
<hr/>
|
||||
|
||||
|
||||
|
||||
<h2>Informations générales</h2>
|
||||
|
||||
<div>
|
||||
{{ main_form.app_name.label }} {{ main_form.app_name()}}
|
||||
<br>
|
||||
{{ main_form.app_id.label}} {{ main_form.app_id() }}
|
||||
<br>
|
||||
|
||||
|
||||
<div style="display:flex; text-align:center">
|
||||
{{ main_form.description_en.label}}
|
||||
{{ main_form.description_en(style="height:
|
||||
2.5em;min-height: 2em; max-height: 4em;flex-grow: 1;box-sizing: border-box;")}}
|
||||
<div class="panel panel-primary">
|
||||
<div class="panel-heading">
|
||||
<h2 class="panel-title">1/6 - Informations générales</h2>
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
<div>
|
||||
{{ wtf.form_field(main_form.app_name) }}
|
||||
{{ wtf.form_field(main_form.app_id) }}
|
||||
{{ wtf.form_field(main_form.description_en) }}
|
||||
{{ wtf.form_field(main_form.description_fr) }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<br>
|
||||
<div style="display:flex">
|
||||
{{ main_form.description_fr.label}} {{ main_form.description_fr(style="
|
||||
height:
|
||||
2.5em;min-height: 1em; max-height: 4em;flex-grow: 1;box-sizing: border-box;")}}
|
||||
|
||||
|
||||
<div class="panel panel-primary">
|
||||
<div class="panel-heading">
|
||||
<h2 class="panel-title">2/6 - Informations sur l'upstream</h2>
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
<p><i>Le terme upstream désigne le projet original qui maintient l'app</i></p>
|
||||
<div>
|
||||
{{ wtf.form_field(main_form.license) }}
|
||||
{{ wtf.form_field(main_form.website) }}
|
||||
{{ wtf.form_field(main_form.demo) }}
|
||||
{{ wtf.form_field(main_form.admindoc) }}
|
||||
{{ wtf.form_field(main_form.userdoc) }}
|
||||
{{ wtf.form_field(main_form.code) }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="panel panel-primary">
|
||||
<div class="panel-heading">
|
||||
<h2 class="panel-title">3/6 - Intégration dans YunoHost</h2>
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
<div>
|
||||
{{ wtf.form_field(main_form.version) }}
|
||||
{{ wtf.form_field(main_form.maintainers) }}
|
||||
{{ wtf.form_field(main_form.multi_instance) }}
|
||||
{{ wtf.form_field(main_form.architectures) }}
|
||||
{{ wtf.form_field(main_form.ldap) }}
|
||||
{{ wtf.form_field(main_form.sso) }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="panel panel-primary">
|
||||
<div class="panel-heading">
|
||||
<h2 class="panel-title">4/6 - Questions à poser pendant l'installation</h2>
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
<p>
|
||||
<em>Cette partie sert à indiquer les questions qui devront être posées.</em>
|
||||
<br/>
|
||||
<em>NB: seules des questions standard sont proposées ici, il faudra éventuellement compléter à la main en
|
||||
suivant le modèle des autres questions.</em>
|
||||
</p>
|
||||
|
||||
<div>
|
||||
{{ wtf.form_field(main_form.domain_and_path) }}
|
||||
{{ wtf.form_field(main_form.init_main_permission) }}
|
||||
{{ wtf.form_field(main_form.init_admin_permission) }}
|
||||
{{ wtf.form_field(main_form.language) }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="panel panel-primary">
|
||||
<div class="panel-heading">
|
||||
<h2 class="panel-title">5/6 - Ressources à initialiser</h2>
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
<p>
|
||||
<em>Il s'agit d'éléments techniques configurés avant que le "vrai" script d'install de l'app ne soit lancé. Typiquement : créer un user système, télécharger les sources de l'app, initialiser le dossier d'install et de données, installer des dépendances avec apt, créer une base de donnée SQL, ...</em>
|
||||
</p>
|
||||
|
||||
<h3>Sources du logiciel</h3>
|
||||
<div style="margin-left: 2em;">
|
||||
{{ wtf.form_field(main_form.source_url) }}
|
||||
{{ wtf.form_field(main_form.sha256sum) }}
|
||||
{{ wtf.form_field(main_form.auto_update) }}
|
||||
</div>
|
||||
|
||||
|
||||
<div>
|
||||
{{ wtf.form_field(main_form.system_user) }}
|
||||
{{ wtf.form_field(main_form.install_dir) }}
|
||||
{{ wtf.form_field(main_form.data_dir) }}
|
||||
{{ wtf.form_field(main_form.apt_dependencies) }}
|
||||
{{ wtf.form_field(main_form.ports) }}
|
||||
{{ wtf.form_field(main_form.database) }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
<hr/>
|
||||
|
||||
|
||||
<h2>Informations sur l'upstream</h2>
|
||||
|
||||
<div>
|
||||
<p><i>Le terme upstream désigne le projet original qui maintient l'app</i></p>
|
||||
{{ main_form.license.label}} {{ main_form.license()}}
|
||||
<br>
|
||||
{{ main_form.website.label}} {{ main_form.website()}}
|
||||
<br>
|
||||
{{ main_form.demo.label}} {{ main_form.demo()}}
|
||||
<br>
|
||||
{{ main_form.admindoc.label}} {{ main_form.admindoc()}}
|
||||
<br>
|
||||
{{ main_form.userdoc.label}} {{ main_form.userdoc()}}
|
||||
<br>
|
||||
{{ main_form.code.label}} {{ main_form.code()}}
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
<hr/>
|
||||
|
||||
|
||||
<h2>Informations sur le paquet et l'intégration dans YunoHost</h2>
|
||||
|
||||
<div>
|
||||
{{ main_form.version.label}} {{ main_form.version()}}
|
||||
<br>
|
||||
{{ main_form.maintainers.label}} {{ main_form.maintainers(style="width: 60%;")}}
|
||||
<br>
|
||||
{{ main_form.multi_instance.label}} {{ main_form.multi_instance()}}
|
||||
<br>
|
||||
<div style="display: flex; align-items: center;">
|
||||
{{ main_form.architectures.label}} {{ main_form.architectures()}}
|
||||
</div>
|
||||
<br>
|
||||
{{ main_form.ldap.label}} {{ main_form.ldap()}}
|
||||
<br>
|
||||
{{ main_form.sso.label}} {{ main_form.sso()}}
|
||||
<br>
|
||||
</div>
|
||||
|
||||
|
||||
<hr/>
|
||||
|
||||
|
||||
|
||||
<h2>Questions à poser pendant l'installation</h2>
|
||||
|
||||
<div>
|
||||
<p>
|
||||
<i>Cette partie sert à indiquer les questions qui devront être posées.</i>
|
||||
<br>
|
||||
<em>NB: seules des questions standard sont proposées ici, il faudra éventuellement compléter à la main en
|
||||
suivant le modèle des autres questions.</em>
|
||||
</p>
|
||||
|
||||
{{ main_form.domain_and_path.label}} {{ main_form.domain_and_path()}}
|
||||
<br>
|
||||
|
||||
{{ main_form.init_main_permission.label}} {{ main_form.init_main_permission()}}
|
||||
<br>
|
||||
|
||||
{{ main_form.init_admin_permission.label}} {{ main_form.init_admin_permission()}}
|
||||
<br>
|
||||
|
||||
{{ main_form.language.label}} {{ main_form.language()}}
|
||||
</div>
|
||||
|
||||
|
||||
<hr/>
|
||||
|
||||
|
||||
<h2>Ressources à initialiser</h2>
|
||||
|
||||
<div>
|
||||
<p>
|
||||
<i>Il s'agit d'éléments techniques configurés avant que le "vrai" script d'install de l'app ne soit lancé. Typiquement : créer un user système, télécharger les sources de l'app, initialiser le dossier d'install et de données, installer des dépendances avec apt, créer une base de donnée SQL, ...</i>
|
||||
</p>
|
||||
|
||||
<span>Sources du logiciel</span>
|
||||
<div style="padding-left: 2em;">
|
||||
{{ main_form.source_url.label}} {{ main_form.source_url()}}
|
||||
<br/>
|
||||
{{ main_form.sha256sum.label}} {{ main_form.sha256sum()}}
|
||||
<br/>
|
||||
{{ main_form.auto_update.label}} {{ main_form.auto_update()}}
|
||||
<br/>
|
||||
</div>
|
||||
|
||||
|
||||
{{ main_form.system_user.label}} {{ main_form.system_user()}}
|
||||
<br>
|
||||
|
||||
{{ main_form.install_dir.label}} {{ main_form.install_dir()}}
|
||||
<br>
|
||||
|
||||
{{ main_form.data_dir.label}} {{ main_form.data_dir()}}
|
||||
<br>
|
||||
|
||||
{{ main_form.apt_dependencies.label}} {{ main_form.apt_dependencies(style="width:40%;")}}
|
||||
<br>
|
||||
|
||||
{{ main_form.ports.label}} {{ main_form.ports()}}
|
||||
<br>
|
||||
|
||||
{{ main_form.database.label }} {{ main_form.database() }}
|
||||
</div>
|
||||
|
||||
<hr/>
|
||||
|
||||
|
||||
<h2>Technologies spécifiques (to be reworked)</h2>
|
||||
<h2>6/6 - Options et technologies spécifiques (to be reworked)</h2>
|
||||
|
||||
{{ main_form.supports_change_url.label}} {{ main_form.supports_change_url()}}
|
||||
<br>
|
||||
|
@ -476,30 +418,6 @@
|
|||
</fieldset>
|
||||
|
||||
|
||||
<!-- how to validate only if both field are checked (or none of them) ?
|
||||
<label for="boolField">Bool Field:</label>
|
||||
<input type="checkbox" id="boolField" name="boolField">
|
||||
<br>
|
||||
|
||||
<label for="requiredField">Required Field:</label>
|
||||
<input type="text" id="requiredField" name="requiredField">
|
||||
<br>
|
||||
|
||||
<script>
|
||||
document.getElementById(document).ready
|
||||
document.getElementById(document).ready(function() {
|
||||
document.getElementById('#myForm').submit(function(event) {
|
||||
var boolField = document.getElementById('#boolField').prop('checked');
|
||||
var requiredField = document.getElementById('#requiredField').val();
|
||||
|
||||
if (boolField && requiredField === '') {
|
||||
event.preventDefault(); // Empêche la soumission du formulaire
|
||||
alert('Le champ requis doit être rempli lorsque le champ booléen est coché.');
|
||||
}
|
||||
});
|
||||
});
|
||||
</script> -->
|
||||
|
||||
|
||||
<h3>Utilisation de PHP</h3>
|
||||
{{ main_form.use_php.label}} {{ main_form.use_php(onchange="showForm(this, 'PHP')") }}<br>
|
||||
|
@ -870,6 +788,5 @@ End of the result part
|
|||
-->
|
||||
{% endif %}
|
||||
|
||||
</body>
|
||||
|
||||
</html>
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
|
Loading…
Add table
Reference in a new issue