1
0
Fork 0
mirror of https://github.com/YunoHost/apps.git synced 2024-09-03 20:06:07 +02:00

appgenerator: more refactoring of the way we handled the specific technology

This commit is contained in:
Alexandre Aubin 2023-11-09 18:12:15 +01:00 committed by Alexandre Aubin
parent 09edb1540a
commit 14e735a725
2 changed files with 296 additions and 402 deletions

View file

@ -77,99 +77,6 @@ def markdown_file_to_html_string(file):
### Forms ### Forms
## PHP forms
class Form_PHP(FlaskForm):
use_php = BooleanField("Nécessite PHP", default=False)
php_config_file = SelectField(
"Type de fichier PHP",
choices=[
(
"php-fpm.conf",
Markup(
'Fichier de configuration PHP complet <i class="grayed_hint">(php-fpm.conf)</i>'
),
),
(
"php_extra-fpm.conf",
Markup(
'Fichier de configuration PHP particulier <i class ="grayed_hint">(extra_php-fpm.conf)</i>'
),
),
],
default="php_extra-fpm.conf",
validators=[DataRequired()],
)
## TODO : figure out how to include these comments/title values
# 'title': 'Remplace la configuration générée par défaut par un fichier de configuration complet. À éviter si possible.
# '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",
validators=[Optional()],
render_kw={
"class": "form-control",
"style": "width: 50%;height:11em;min-height: 5.5em; max-height: 55em;flex-grow: 1;box-sizing: border-box;",
"title": "TODO",
"placeholder": "; Additional php.ini defines, specific to this pool of workers. \n\nphp_admin_value[upload_max_filesize] = 100M \nphp_admin_value[post_max_size] = 100M",
},
)
## NodeJS forms
class Form_NodeJS(FlaskForm):
use_nodejs = BooleanField("Nécessite NodeJS", default=False)
use_nodejs_version = StringField(
"Version de NodeJS",
render_kw={
"placeholder": "20",
"class": "form-control",
"title": "Saisissez la version de NodeJS à installer. Cela peut-être une version majeure (ex: 20) ou plus précise (ex: 20.1).",
},
) # TODO : this should be validated using a regex, should be only numbers and any (≥0) number of dots in between
use_nodejs_needs_yarn = BooleanField(
"Nécessite Yarn",
default=False,
render_kw={
"title": "Faut-il installer automatiquement Yarn ? Cela configurera les dépôts spécifiques à Yarn."
},
)
## Python forms
class Form_Python(FlaskForm):
use_python = BooleanField(
"Nécessite Python", default=False
) ## TODO -> python3, python3-pip, python3-ven dependencies by default
python_dependencies_type = SelectField(
"Configuration des dépendances Python",
choices=[
("requirements.txt", Markup("Fichier <i>requirements.txt</i>")),
("manual_list", "Liste manuelle"),
],
default="requirements.txt",
validators=[DataRequired(), Optional()],
)
python_requirements = TextAreaField(
"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;",
"title": "Lister les dépendances à installer, une par ligne, avec un numéro de version derrière.\nEx: 'dépendance==1.0'.",
"placeholder": "tensorflow==2.3.1 \nuvicorn==0.12.2 \nfastapi==0.63.0",
},
)
python_dependencies_list = StringField(
"Liste de dépendances python",
render_kw={
"placeholder": "tensorflow uvicorn fastapi",
"class": "form-control",
"title": "Lister les dépendances à installer, séparées d'un espace.",
},
)
class GeneralInfos(FlaskForm): class GeneralInfos(FlaskForm):
app_id = StringField( app_id = StringField(
@ -192,17 +99,24 @@ class GeneralInfos(FlaskForm):
}, },
) )
description_en = TextAreaField( description_en = StringField(
"Description courte (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)", 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()], validators=[DataRequired()],
) )
description_fr = TextAreaField( description_fr = StringField(
"Description courte (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)", 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()], validators=[DataRequired()],
) )
# TODO :
# long descriptions that go into doc/DESCRIPTION.md
# screenshot
class IntegrationInfos(FlaskForm): class IntegrationInfos(FlaskForm):
# TODO : people shouldnt have to put the ~ynh1 ? This should be added automatically when rendering the app files ? # TODO : people shouldnt have to put the ~ynh1 ? This should be added automatically when rendering the app files ?
@ -245,7 +159,7 @@ class IntegrationInfos(FlaskForm):
ldap = SelectField( ldap = SelectField(
"L'app s'intègrera avec le LDAP", "L'app s'intègrera avec le LDAP",
description="c-à-d pouvoir se connecter en utilisant ses identifiants YunoHost", description="c-à-d pouvoir se connecter en utilisant ses identifiants YunoHost. 'LDAP' corresponds à la technologie utilisée par YunoHost comme base de compte utilisateurs centralisée. L'interface entre l'app et le LDAP de YunoHost nécessite le plus souvent de remplir des paramètres dans la configuration de l'app (voir plus tard)",
choices=[ choices=[
("false", "No"), ("false", "No"),
("true", "Yes"), ("true", "Yes"),
@ -256,7 +170,7 @@ class IntegrationInfos(FlaskForm):
) )
sso = SelectField( sso = SelectField(
"L'app s'intègrera avec le SSO (Single Sign On) de 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", description="c-à-d être connecté automatiquement à l'app si connecté au portail YunoHost. Le SSO de YunoHost se base sur le principe du 'Basic HTTP auth header', c'est à vous de vérifier si l'application supporte ce mécanisme de SSO.",
choices=[ choices=[
("false", "Yes"), ("false", "Yes"),
("true", "No"), ("true", "No"),
@ -328,19 +242,17 @@ class InstallQuestions(FlaskForm):
) )
init_main_permission = BooleanField( init_main_permission = BooleanField(
"Demander qui pourra accéder à l'app (parmi visitors/all_users/admins)", "Demander qui pourra accéder à l'app",
description="Parmis les groupes d'utilisateurs : par défaut au moins 'visitors', 'all_users' et 'admins' existent. (Corresponds anciennement à la notion d'app privée/publique)",
default=True, default=True,
) )
init_admin_permission = BooleanField( init_admin_permission = BooleanField(
"Demander qui pourra accéder à l'interface d'admin (ceci suppose que l'app dispose d'une interface d'admin)", "Demander qui pourra accéder à l'interface d'admin",
description="Ceci est suppose apriori que l'app dispose d'une interface d'admin",
default=False, default=False,
) )
# admin_password_help_message = BooleanField("TODO ", default=False,
# render_kw={"class": "",
# "title": "TODO"})
language = SelectMultipleField( language = SelectMultipleField(
"Langues supportées", "Langues supportées",
choices=[ choices=[
@ -407,7 +319,7 @@ class Resources(FlaskForm):
) )
database = SelectField( database = SelectField(
"Initialiser une base de données", "Initialiser une base de données SQL",
choices=[ choices=[
("false", "Non"), ("false", "Non"),
("mysql", "MySQL/MariaDB"), ("mysql", "MySQL/MariaDB"),
@ -422,37 +334,117 @@ class Resources(FlaskForm):
) )
install_dir = BooleanField( install_dir = BooleanField(
"Initialiser un dossier d'installation de l'app (typiquement /var/www/$app)", "Initialiser un dossier d'installation de l'app",
description="Par défaut il s'agit de /var/www/$app",
default=True, default=True,
) )
data_dir = BooleanField( data_dir = BooleanField(
"Initialiser un dossier pour les données de l'app (typiquement /home/yunohost.app/$app)", "Initialiser un dossier destiné à stocker les données de l'app",
description="Par défaut il s'agit de /home/yunohost.app/$app",
default=False, default=False,
) )
ports = BooleanField(
"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 class SpecificTechnology(FlaskForm):
class GeneratorForm(
GeneralInfos, IntegrationInfos, UpstreamInfos, InstallQuestions, Resources, main_technology = SelectField(
Form_PHP, Form_NodeJS, Form_Python "Technologie principale de l'app",
): choices=[
generator_mode = SelectField( ("none", "None / Static"),
"Mode du générateur", ("php", "PHP"),
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.", ("nodejs", "NodeJS"),
choices=[("false", "Version épurée"), ("true", "Version tutoriel")], ("python", "Python"),
default="true", ("ruby", "Ruby"),
("other", "Other"),
],
default="none",
validators=[DataRequired()], validators=[DataRequired()],
) )
install_snippet = TextAreaField(
"Commandes spécifiques d'installation",
description="Ces commandes seront éxécutées depuis le répertoire d'installation de l'app (par défaut, /var/www/$app) après que les sources aient été déployées. Le champ est pré-rempli avec un exemple classique basé sur la technologie sélectionnée. Vous devriez sans-doute le comparer et l'adapter en fonction de la doc d'installation de l'app.",
validators=[Optional()],
render_kw={
"spellcheck": "false"
}
)
#
# PHP
#
# TODO : add a tip about adding the PHP dependencies in the APT deps earlier
# TODO : add a tip about the auto-prepared nginx config that will include the fastcgi snippet
use_composer = BooleanField(
"Utiliser composer",
description="Composer est un gestionnaire de dépendance PHP utilisé par certaines apps",
default=False,
)
#
# NodeJS
#
nodejs_version = StringField(
"Version de NodeJS",
description="For example: 16.4, 18, 18.2, 20, 20.1, ...",
render_kw={
"placeholder": "20",
},
)
use_yarn = BooleanField(
"Installer et utiliser Yarn",
default=False,
)
# NodeJS / Python / Ruby / ...
# TODO : add a tip about the auto-prepared nginx config that will include a proxy_pass / reverse proxy to an auto-prepared systemd service
systemd_execstart = StringField(
"Commande pour lancer le daemon de l'app (depuis le service systemd)",
description="Corresponds to 'ExecStart' statement in systemd. You can use '__INSTALL_DIR__' to refer to the install directory, or '__APP__' to refer to the app id",
render_kw={
"placeholder": "__INSTALL_DIR__/bin/app --some-option",
},
)
class AppConfig(FlaskForm):
use_custom_config_file = BooleanField(
"L'app utilise un fichier de configuration spécifique",
description="Typiquement : .env, config.json, conf.ini, params.yml, ...",
default=True,
)
custom_config_file = StringField(
"Nom ou chemin du fichier à utiliser",
validators=[Optional()],
render_kw={
"placeholder": "config.json",
},
)
custom_config_file_content = TextAreaField(
"Modèle de fichier de configuration de l'app",
description="Dans ce modèle, vous pouvez utilisez la syntaxe __FOOBAR__ qui sera automatiquement remplacé par la valeur de la variable $foobar",
validators=[Optional()],
render_kw={
"spellcheck": "false"
}
)
class MoreAdvanced(FlaskForm):
supports_change_url = BooleanField( supports_change_url = BooleanField(
"L'application autorise le changement d'adresse (changement de domaine ou de chemin)", "Gérer le changement d'URL d'installation (script change_url)",
default=True, default=True,
render_kw={ render_kw={
"title": "Faut-il permettre le changement d'URL pour l'application ? (fichier change_url)" "title": "Faut-il permettre le changement d'URL pour l'application ? (fichier change_url)"
@ -460,7 +452,7 @@ class GeneratorForm(
) )
use_logrotate = BooleanField( use_logrotate = BooleanField(
"Utiliser logrotate pour gérer les journaux", "Utiliser logrotate pour les journaux de l'app",
default=True, default=True,
render_kw={ render_kw={
"title": "Si l'application genère des journaux (log), cette option permet d'en gérer l'archivage. Recommandé." "title": "Si l'application genère des journaux (log), cette option permet d'en gérer l'archivage. Recommandé."
@ -477,18 +469,15 @@ class GeneratorForm(
) )
use_cron = BooleanField( use_cron = BooleanField(
"Ajouter une tâche CRON pour cette application", "Ajouter une tâche CRON pour cette application",
description="Corresponds à des opérations périodiques de l'application",
default=False, 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( cron_config_file = TextAreaField(
"Saisissez le contenu du fichier CRON", "Saisissez le contenu du fichier CRON",
validators=[Optional()], validators=[Optional()],
render_kw={ render_kw={
"class": "form-control", "class": "form-control",
"style": "width: 50%;height:22em;min-height: 5.5em; max-height: 55em;flex-grow: 1;box-sizing: border-box;", "spellcheck": "false",
"title": "Saisir le contenu du fichier de la tâche CRON.",
}, },
) )
@ -503,71 +492,17 @@ class GeneratorForm(
}, },
) )
nginx_config_file = TextAreaField(
"Saisissez le contenu du fichier de configuration du serveur NGINX",
validators=[Optional()],
render_kw={
"class": "form-control",
"style": "width: 50%;height:22em;min-height: 5.5em; max-height: 55em;flex-grow: 1;box-sizing: border-box;",
"title": "Saisir le contenu du fichier de configuration du serveur NGINX.",
"placeholder": "location __PATH__/ {\n \n proxy_pass http://127.0.0.1:__PORT__;\n proxy_set_header X-Real-IP $remote_addr;\n proxy_set_header Host $host;\n proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;\n \n # Include SSOWAT user panel.\n include conf.d/yunohost_panel.conf.inc;\n }",
},
)
use_systemd_service = BooleanField( ## Main form
"Utiliser un service système (via systemd) pour gérer le fonctionnement de l'application ", class GeneratorForm(
default=False, GeneralInfos, IntegrationInfos, UpstreamInfos, InstallQuestions, Resources, SpecificTechnology, AppConfig, MoreAdvanced
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é." generator_mode = SelectField(
}, "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.",
systemd_config_file = TextAreaField( choices=[("false", "Version épurée"), ("true", "Version tutoriel")],
"Saisissez le contenu du fichier de configuration du service SystemD", default="true",
validators=[Optional()], validators=[DataRequired()],
render_kw={
"class": "form-control",
"style": "width: 50%;height:22em;min-height: 5.5em; max-height: 55em;flex-grow: 1;box-sizing: border-box;",
"title": "Saisir le contenu du fichier de configuration du service systemd.",
},
)
systemd_service_description = StringField(
"Description du service de l'application",
validators=[Optional()],
render_kw={
"placeholder": "A short description of the app",
"class": "form-control",
"style": "width: 30%;",
"title": "Décrire en une ligne ce que fait ce service. Ceci sera affiché dans l'interface d'administration.",
},
)
use_custom_config_file = BooleanField(
"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",
validators=[Optional()],
render_kw={
"placeholder": "config.json",
"class": "form-control",
"style": "width: 30%;",
"title": "Décrire en une ligne ce que fait ce service. Ceci sera affiché dans l'interface d'administration.",
},
)
custom_config_file_content = TextAreaField(
"Saisissez le contenu du fichier de configuration personnalisé",
validators=[Optional()],
render_kw={
"class": "form-control",
"style": "width: 50%;height:22em;min-height: 5.5em; max-height: 55em;flex-grow: 1;box-sizing: border-box;",
"title": "Saisir le contenu du fichier de configuration personnalisé.",
},
) )
submit = SubmitField("Soumettre") submit = SubmitField("Soumettre")

View file

@ -1,5 +1,24 @@
{% import "bootstrap/wtf.html" as wtf %} {% import "bootstrap/wtf.html" as wtf %}
{% macro form_field(field,
form_type="basic",
horizontal_columns=('lg', 2, 10),
button_map={}) %}
{% if field.widget.input_type == 'checkbox' %}
<div class="checkbox">
<label>
{{field()|safe}} {{field.label.text|safe}}
</label>
{%- if field.description -%}
<p class="help-block">{{field.description|safe}}</p>
{%- endif %}
</div>
{% else %}
{{ wtf.form_field(field, form_type, horizontal_columns, button_map) }}
{% endif %}
{% endmacro %}
{% extends "bootstrap/base.html" %} {% extends "bootstrap/base.html" %}
{% block title %} {% block title %}
@ -13,39 +32,6 @@ YunoHost app generator
{% block content %} {% block content %}
<script> <script>
function showForm(element, type) {
if (type == 'PHP') {
form = 'php_config_file';
} else if (type == 'NodeJS') {
form = 'nodejs_config';
} else if (type == 'Python') {
form = 'python_config';
} else if (type == 'Python_dependencies') {
form = 'python_dependencies_form';
} else if (type == 'SystemD') {
form = 'systemd_config';
} else if (type == 'fail2ban') {
form = 'fail2ban_config';
} else if (type == 'custom_config') {
form = 'custom_config';
} else if (type == 'cron') {
form = 'cron_config';
}
if(element.checked==true) {
selects = document.getElementsByClassName(form);
for(var i=0, il = selects.length;i<il;i++){
selects[i].style.display='inline';
}
} else {
selects = document.getElementsByClassName(form);
for(var i=0, il = selects.length;i<il;i++){
selects[i].style.display='none';
}
}
}
function showPage(tag,page) { function showPage(tag,page) {
console.log("ERREUR"); console.log("ERREUR");
console.log(tag); console.log(tag);
@ -229,18 +215,18 @@ YunoHost app generator
{{ main_form.hidden_tag() }} {{ main_form.hidden_tag() }}
{{ wtf.form_errors(main_form, hiddens="only") }} {{ wtf.form_errors(main_form, hiddens="only") }}
{{ wtf.form_field(main_form.generator_mode) }} {{ form_field(main_form.generator_mode) }}
<div class="panel panel-primary"> <div class="panel panel-primary">
<div class="panel-heading"> <div class="panel-heading">
<h2 class="panel-title">1/6 - Informations générales</h2> <h2 class="panel-title">1/8 - Informations générales</h2>
</div> </div>
<div class="panel-body"> <div class="panel-body">
<div> <div>
{{ wtf.form_field(main_form.app_name) }} {{ form_field(main_form.app_name) }}
{{ wtf.form_field(main_form.app_id) }} {{ form_field(main_form.app_id) }}
{{ wtf.form_field(main_form.description_en) }} {{ form_field(main_form.description_en) }}
{{ wtf.form_field(main_form.description_fr) }} {{ form_field(main_form.description_fr) }}
</div> </div>
</div> </div>
</div> </div>
@ -248,33 +234,33 @@ YunoHost app generator
<div class="panel panel-primary"> <div class="panel panel-primary">
<div class="panel-heading"> <div class="panel-heading">
<h2 class="panel-title">2/6 - Informations sur l'upstream</h2> <h2 class="panel-title">2/8 - Informations sur l'upstream</h2>
</div> </div>
<div class="panel-body"> <div class="panel-body">
<p><i>Le terme upstream désigne le projet original qui maintient l'app</i></p> <p><i>Le terme upstream désigne le projet original qui maintient l'app</i></p>
<div> <div>
{{ wtf.form_field(main_form.license) }} {{ form_field(main_form.license) }}
{{ wtf.form_field(main_form.website) }} {{ form_field(main_form.website) }}
{{ wtf.form_field(main_form.demo) }} {{ form_field(main_form.demo) }}
{{ wtf.form_field(main_form.admindoc) }} {{ form_field(main_form.admindoc) }}
{{ wtf.form_field(main_form.userdoc) }} {{ form_field(main_form.userdoc) }}
{{ wtf.form_field(main_form.code) }} {{ form_field(main_form.code) }}
</div> </div>
</div> </div>
</div> </div>
<div class="panel panel-primary"> <div class="panel panel-primary">
<div class="panel-heading"> <div class="panel-heading">
<h2 class="panel-title">3/6 - Intégration dans YunoHost</h2> <h2 class="panel-title">3/8 - Intégration dans YunoHost</h2>
</div> </div>
<div class="panel-body"> <div class="panel-body">
<div> <div>
{{ wtf.form_field(main_form.version) }} {{ form_field(main_form.version) }}
{{ wtf.form_field(main_form.maintainers) }} {{ form_field(main_form.maintainers) }}
{{ wtf.form_field(main_form.multi_instance) }} {{ form_field(main_form.multi_instance) }}
{{ wtf.form_field(main_form.architectures) }} {{ form_field(main_form.architectures) }}
{{ wtf.form_field(main_form.ldap) }} {{ form_field(main_form.ldap) }}
{{ wtf.form_field(main_form.sso) }} {{ form_field(main_form.sso) }}
</div> </div>
</div> </div>
</div> </div>
@ -282,7 +268,7 @@ YunoHost app generator
<div class="panel panel-primary"> <div class="panel panel-primary">
<div class="panel-heading"> <div class="panel-heading">
<h2 class="panel-title">4/6 - Questions à poser pendant l'installation</h2> <h2 class="panel-title">4/8 - Questions à poser pendant l'installation</h2>
</div> </div>
<div class="panel-body"> <div class="panel-body">
<p> <p>
@ -293,17 +279,17 @@ YunoHost app generator
</p> </p>
<div> <div>
{{ wtf.form_field(main_form.domain_and_path) }} {{ form_field(main_form.domain_and_path) }}
{{ wtf.form_field(main_form.init_main_permission) }} {{ form_field(main_form.init_main_permission) }}
{{ wtf.form_field(main_form.init_admin_permission) }} {{ form_field(main_form.init_admin_permission) }}
{{ wtf.form_field(main_form.language) }} {{ form_field(main_form.language) }}
</div> </div>
</div> </div>
</div> </div>
<div class="panel panel-primary"> <div class="panel panel-primary">
<div class="panel-heading"> <div class="panel-heading">
<h2 class="panel-title">5/6 - Ressources à initialiser</h2> <h2 class="panel-title">5/8 - Ressources à initialiser</h2>
</div> </div>
<div class="panel-body"> <div class="panel-body">
<p> <p>
@ -312,171 +298,144 @@ YunoHost app generator
<h3>Sources du logiciel</h3> <h3>Sources du logiciel</h3>
<div style="margin-left: 2em;"> <div style="margin-left: 2em;">
{{ wtf.form_field(main_form.source_url) }} {{ form_field(main_form.source_url) }}
{{ wtf.form_field(main_form.sha256sum) }} {{ form_field(main_form.sha256sum) }}
{{ wtf.form_field(main_form.auto_update) }} {{ form_field(main_form.auto_update) }}
</div> </div>
<div> <div>
{{ wtf.form_field(main_form.system_user) }} {{ form_field(main_form.system_user) }}
{{ wtf.form_field(main_form.install_dir) }} {{ form_field(main_form.install_dir) }}
{{ wtf.form_field(main_form.data_dir) }} {{ form_field(main_form.data_dir) }}
{{ wtf.form_field(main_form.apt_dependencies) }} {{ form_field(main_form.apt_dependencies) }}
{{ wtf.form_field(main_form.ports) }} {{ form_field(main_form.database) }}
{{ wtf.form_field(main_form.database) }}
</div> </div>
</div> </div>
</div> </div>
<div class="panel panel-primary">
<div class="panel-heading">
<h2 class="panel-title">6/8 - Technologie spécifique</h2>
</div>
<div class="panel-body">
{{ form_field(main_form.main_technology) }}
<div id="php_options">
<div class="alert alert-info" role="alert"><span class="glyphicon glyphicon-info-sign" aria-hidden="true"></span> You probably want to make sure to have 'phpX.Y-fpm' and others 'phpX.Y-foobar' libraries listed the apt dependencies earlier (with X.Y being the php version you want to use)</div>
<div class="alert alert-info" role="alert"><span class="glyphicon glyphicon-info-sign" aria-hidden="true"></span> The generated application draft will include an nginx configuration snippet that interfaces with PHP-FPM</div>
{{ form_field(main_form.use_composer) }}
</div>
<div id="nodejs_options">
{{ form_field(main_form.nodejs_version) }}
{{ form_field(main_form.use_yarn) }}
</div>
<div id="python_options">
<div class="alert alert-info" role="alert"><span class="glyphicon glyphicon-info-sign" aria-hidden="true"></span> You probably want to make sure to have 'python3' and 'python3-venv' listed in the apt dependencies earlier. Other dependencies should be installed inside a venv (cf the proposed install snippet)</div>
</div>
{{ form_field(main_form.install_snippet) }}
<div id="systemd_options">
<div class="alert alert-info" role="alert"><span class="glyphicon glyphicon-info-sign" aria-hidden="true"></span> The generated application draft will include an nginx configuration snippet that reverse-proxies to a systemd service using an internal port</div>
{{ form_field(main_form.systemd_execstart) }}
</div>
</div>
<script>
let main_technology = document.getElementById("main_technology");
let install_snippet = document.getElementById("install_snippet");
function update_main_technology()
{
document.getElementById("php_options").classList.add("hide");
document.getElementById("nodejs_options").classList.add("hide");
document.getElementById("python_options").classList.add("hide");
document.getElementById("systemd_options").classList.add("hide");
if (main_technology.value == "php") document.getElementById("php_options").classList.remove("hide");
if (main_technology.value == "nodejs") document.getElementById("nodejs_options").classList.remove("hide");
if (main_technology.value == "python") document.getElementById("python_options").classList.remove("hide");
if ((main_technology.value != "php") && (main_technology.value != "none")) document.getElementById("systemd_options").classList.remove("hide");
if (main_technology.value == "none")
{
install_snippet.value = "some_command --build";
}
else if (main_technology.value == "php")
{
if (document.getElementById("use_composer").checked)
{
install_snippet.value = "ynh_install_composer";
}
else
{
install_snippet.value = "some_command --build";
}
}
else if (main_technology.value == "nodejs")
{
if (document.getElementById("use_yarn").checked)
{
install_snippet.value = "ynh_exec_as $app $ynh_node_load_PATH yarn install --production --pure-lockfile\nynh_exec_as $app $ynh_node_load_PATH yarn build";
}
else
{
install_snippet.value = "ynh_exec_as $app $ynh_node_load_PATH $ynh_npm install --production --ignore-scripts\nynh_exec_as $app $ynh_node_load_PATH $ynh_npm run build"
}
}
else if (main_technology.value == "python")
{
install_snippet.value = "python3 -m venv venv\nvenv/bin/pip3 install -r requirements.txt";
}
else if (main_technology.value == "ruby")
{
install_snippet.value = "ynh_gem update --system --no-document\nynh_gem install bundler foreman --no-document\nbundle config set --local deployment 'true'\nbundle config set --local without 'development test'\nbundle install";
}
}
main_technology.addEventListener("change", update_main_technology);
document.getElementById("use_composer").addEventListener("change", update_main_technology);
document.getElementById("use_yarn").addEventListener("change", update_main_technology);
update_main_technology();
</script>
</div>
<h2>6/6 - Options et technologies spécifiques (to be reworked)</h2> <div class="panel panel-primary">
<div class="panel-heading">
<h2 class="panel-title">7/8 - Configuration de l'app</h2>
</div>
<div class="panel-body">
{{ form_field(main_form.use_custom_config_file) }}
<!-- TODO : this show/hide the other fields -->
<div id="custom_config_file_options">
{{ form_field(main_form.custom_config_file) }}
{{ form_field(main_form.custom_config_file_content) }}
</div>
</div>
<script>
let use_custom_config_file = document.getElementById("use_custom_config_file");
function update_custom_config_file()
{
document.getElementById("custom_config_file_options").classList.add("hide");
if (use_custom_config_file.checked) document.getElementById("custom_config_file_options").classList.remove("hide");
}
use_custom_config_file.addEventListener("change", update_custom_config_file);
update_custom_config_file();
</script>
</div>
{{ main_form.supports_change_url.label}} {{ main_form.supports_change_url()}} <div class="panel panel-primary">
<br> <div class="panel-heading">
<h2 class="panel-title">8/8 - Options avancées</h2>
{{ main_form.use_logrotate.label}} {{ main_form.use_logrotate()}} </div>
<br> <div class="panel-body">
{{ form_field(main_form.supports_change_url) }}
<!-- FAIL2BAN --> {{ form_field(main_form.use_logrotate) }}
{{ main_form.use_fail2ban.label}} {{ main_form.use_fail2ban(onchange="showForm(this, 'fail2ban')")}} {{ form_field(main_form.use_fail2ban) }}
{{ form_field(main_form.fail2ban_regex) }}
{%- if parameters['use_fail2ban'] == True -%} {# Not shown by default, so we show it if needed #} {{ form_field(main_form.use_cron) }}
<style>.fail2ban_config {display:inline;}</style> {{ form_field(main_form.cron_config_file) }}
{%- else -%} </div>
<style>.fail2ban_config {display:none;}</style> </div>
{%- endif -%}
<fieldset name="fail2ban_main_form" class="box fail2ban_config" style="width:90%;">
<legend>Configuration pour fail2ban</legend>
{{ main_form.fail2ban_regex.label}} {{ main_form.fail2ban_regex(style="width:60%;")}}
</fieldset>
<br>
<!-- CRON -->
{{ main_form.use_cron.label }} {{ main_form.use_cron(onchange="showForm(this, 'cron')") }}
{%- if parameters['use_cron'] == True -%} {# Not shown by default, so we show it if needed #}
<style>.cron_config {display:inline;}</style>
{%- else -%}
<style>.cron_config {display:none;}</style>
{%- endif -%}
<fieldset name="cron_main_form" class="box cron_config" style="width:90%;">
<legend>Configuration pour CRON</legend>
{{ main_form.cron_config_file.label}} {{ main_form.cron_config_file()}}
</fieldset>
<br>
<!-- NGINX -->
<fieldset name="nginx_main_form" class="box nginx_config" style="width:90%;">
<legend>Configuration pour le serveur NGINX</legend>
{{ main_form.nginx_config_file.label }}<br>
{{ main_form.nginx_config_file() }}
</fieldset>
<br>
<!-- SYSTEMD -->
{{ main_form.use_systemd_service.label}} {{ main_form.use_systemd_service(onchange="showForm(this, 'SystemD')")}}
<br>
{%- if parameters['use_systemd_service'] == True -%} {# Not shown by default, so we show it if needed #}
<style>.systemd_config {display:inline;}</style>
{%- else -%}
<style>.systemd_config {display:none;}</style>
{%- endif -%}
<fieldset name="systemd_main_form" class="box systemd_config" style="width:90%;">
<legend>Configuration pour le service SystemD</legend>
{{ main_form.systemd_service_description.label }} {{ main_form.systemd_service_description() }}<br>
{{ main_form.systemd_config_file.label }}<br>
{{ main_form.systemd_config_file() }}
</fieldset>
<br>
<!-- CONFIG FILE -->
{{ main_form.use_custom_config_file.label}} {{ main_form.use_custom_config_file(onchange="showForm(this,
'custom_config')")}}
<br>
{%- if parameters['use_custom_config_file'] == True -%} {# Not shown by default, so we show it if needed #}
<style>.custom_config {display:inline;}</style>
{%- else -%}
<style>.custom_config {display:none;}</style>
{%- endif -%}
<fieldset name="custom_config_main_form" class="box custom_config" style="width:90%;">
<legend>Fichier de configuration personnalisé</legend>
{{ main_form.custom_config_file.label }} {{ main_form.custom_config_file() }}<br>
{{ main_form.custom_config_file_content.label }}<br>
{{ main_form.custom_config_file_content() }}
</fieldset>
<h3>Utilisation de PHP</h3>
{{ main_form.use_php.label}} {{ main_form.use_php(onchange="showForm(this, 'PHP')") }}<br>
{%- if parameters['use_php'] == True -%} {# Not shown by default, so we show it if needed #}
<style>.php_config_file {display:inline;}</style>
{%- else -%}
<style>.php_config_file {display:none;}</style>
{%- endif -%}
<fieldset name="php_main_form" class="box php_config_file" style="width:90%;">
<legend>Fichier de configuration pour PHP</legend>
{{ main_form.php_config_file.label }} {{ main_form.php_config_file()}}<br>
{{ main_form.php_config_file_content.label }} {{ main_form.php_config_file_content()}}<br>
<!class="custom-select" TODO fix label>
</fieldset>
<h3>Utilisation de NodeJS</h3>
{{ main_form.use_nodejs.label}} {{ main_form.use_nodejs(onchange="showForm(this, 'NodeJS')") }} <br>
{%- if parameters['use_nodejs'] == True -%} {# Not shown by default, so we show it if needed #}
<style>.nodejs_config {display:inline;}</style>
{%- else -%}
<style>.nodejs_config {display:none;}</style>
{%- endif -%}
<fieldset name="nodejs_main_form" class="box nodejs_config" style="width:90%;">
<legend>Configuration pour NodeJS</legend>
{{ main_form.use_nodejs_version.label}} {{ main_form.use_nodejs_version() }} <br>
{{ main_form.use_nodejs_needs_yarn.label}} {{ main_form.use_nodejs_needs_yarn() }} <br>
</fieldset>
<h3>Utilisation de Python</h3>
{{ main_form.use_python.label}} {{ main_form.use_python(onchange="showForm(this, 'Python')") }} <br>
{%- if parameters['use_python'] == True -%} {# Not shown by default, so we show it if needed #}
<style>.python_config {display:inline;}</style>
{%- else -%}
<style>.python_config {display:none;}</style>
{%- endif -%}
<fieldset name="python_main_form" class="box python_config" style="width:90%;">
<legend>Configuration pour Python</legend>
{{ main_form.python_dependencies_type.label}} {{ main_form.python_dependencies_type(onchange="showForm(this,
'Python_dependencies')") }} <br>
<div name="python_dependencies_form"> <!-- TODO : this has to be changed by Javascript-->
{%- if parameters['python_dependencies_type'] == 'requirements.txt' -%}
{{ main_form.python_requirements.label}} {{ main_form.python_requirements() }}
{%- else -%}
{{ main_form.python_dependencies_list.label}} {{ main_form.python_dependencies_list() }}
{%- endif -%}
<br>
</div>
</fieldset>
<!-- Submit button --> <!-- Submit button -->
<br> <div class="text-center">
{{ main_form.submit(class="btn btn-primary btn-sm btn-center") }} {{ main_form.submit(class="btn btn-primary") }}
</div>
{% if parameters['invalid_form'] %} {% if parameters['invalid_form'] %}
<p class="alert">Formulaire invalide, veuillez vérifier quel champ contient une erreur svp.</p> <p class="alert">Formulaire invalide, veuillez vérifier quel champ contient une erreur svp.</p>