diff --git a/qtribu/constants.py b/qtribu/constants.py index 1225a2ea..bb0f9324 100644 --- a/qtribu/constants.py +++ b/qtribu/constants.py @@ -18,6 +18,7 @@ ICON_ARTICLE = QIcon(str(DIR_PLUGIN_ROOT.joinpath("resources/images/article.svg"))) ICON_GEORDP = QIcon(str(DIR_PLUGIN_ROOT.joinpath("resources/images/geordp.svg"))) +LOCAL_CDN_PATH: Path = Path().home() / ".geotribu/cdn/" # Classes diff --git a/qtribu/gui/form_article.py b/qtribu/gui/form_article.py index 9c162caa..a0ac3262 100644 --- a/qtribu/gui/form_article.py +++ b/qtribu/gui/form_article.py @@ -9,16 +9,15 @@ # standard from functools import partial from pathlib import Path +from typing import Optional, Union # PyQGIS from qgis.PyQt import uic -from qgis.PyQt.QtCore import Qt -from qgis.PyQt.QtGui import QIcon -from qgis.PyQt.QtWidgets import QDialog +from qgis.PyQt.QtWidgets import QDialog, QDialogButtonBox, QWidget # plugin -from qtribu.__about__ import DIR_PLUGIN_ROOT -from qtribu.constants import GEORDP_NEWS_ICONS, GeotribuImage +from qtribu.__about__ import __title__, __version__ +from qtribu.constants import ICON_ARTICLE from qtribu.toolbelt import NetworkRequestsManager, PlgLogger, PlgOptionsManager from qtribu.toolbelt.commons import open_url_in_browser @@ -26,9 +25,11 @@ class ArticleForm(QDialog): """QDialog form to submit an article.""" - LOCAL_CDN_PATH: Path = Path().home() / ".geotribu/cdn/" + ISSUE_FORM_BASE_URL: str = ( + "https://github.com/geotribu/website/issues/new?template=ARTICLE.yml" + ) - def __init__(self, parent=None): + def __init__(self, parent: Optional[QWidget] = None): """Constructor. :param parent: parent widget or application @@ -42,84 +43,30 @@ def __init__(self, parent=None): self.qntwk = NetworkRequestsManager() # custom icon - self.setWindowIcon(QIcon(str(DIR_PLUGIN_ROOT / "resources/images/news.png"))) - - # icon combobox - self.cbb_icon_populate() - self.cbb_icon.textActivated.connect(self.cbb_icon_selected) + self.setWindowIcon(ICON_ARTICLE) # publication - self.chb_license.setChecked( - self.plg_settings.get_value_from_key( - key="license_global_accept", exp_type=bool - ) + self.cbb_license.addItems( + [ + "Creative Commons International BY-NC-SA 4.0", + "Creative Commons International BY-SA 4.0", + "Beerware (Révision 42)", + "autre - merci de préciser dans le champ libre en fin de formulaire", + ] ) # connect help button self.btn_box.helpRequested.connect( partial( open_url_in_browser, - "https://contribuer.geotribu.fr/rdp/add_news/", + "https://contribuer.geotribu.fr/articles/workflow/", ) ) + self.btn_box.button(QDialogButtonBox.Ok).clicked.connect(self.on_btn_submit) + self.btn_box.button(QDialogButtonBox.Ok).setDefault(True) + self.btn_box.button(QDialogButtonBox.Ok).setText(self.tr("Submit")) - def cbb_icon_populate(self) -> None: - """Populate combobox of article icons.""" - # save current index - current_item_idx = self.cbb_icon.currentIndex() - - # clear - self.cbb_icon.clear() - - # populate - self.cbb_icon.addItem("", None) - for rdp_icon in GEORDP_NEWS_ICONS: - if rdp_icon.kind != "icon": - continue - - if rdp_icon.local_path().is_file(): - self.cbb_icon.addItem( - QIcon(str(rdp_icon.local_path().resolve())), rdp_icon.name, rdp_icon - ) - else: - self.cbb_icon.addItem(rdp_icon.name, rdp_icon) - - # icon tooltip - self.cbb_icon.setItemData( - GEORDP_NEWS_ICONS.index(rdp_icon) + 1, - rdp_icon.description, - Qt.ToolTipRole, - ) - - # restore current index - self.cbb_icon.setCurrentIndex(current_item_idx) - - def cbb_icon_selected(self) -> None: - """Download selected icon locally if it doesn't exist already.""" - selected_icon: GeotribuImage = self.cbb_icon.currentData() - if not selected_icon: - return - - icon_local_path = selected_icon.local_path() - if not icon_local_path.is_file(): - self.log( - message=f"Icon doesn't exist locally: {icon_local_path}", log_level=4 - ) - icon_local_path.parent.mkdir(parents=True, exist_ok=True) - self.qntwk.download_file( - remote_url=selected_icon.url, - local_path=str(icon_local_path.resolve()), - ) - # repopulate combobx to get updated items icons - self.cbb_icon_populate() - - def accept(self) -> bool: - """Auto-connected to the OK button (within the button box), i.e. the `accepted` - signal. Check if required form fields are correctly filled. - - :return: False if some check fails. True and emit accepted() signal if everything is ok. - :rtype: bool - """ + def check_required_fields(self) -> bool: invalid_fields = [] error_message = "" @@ -131,21 +78,21 @@ def accept(self) -> bool: ) # check description - if len(self.txt_description.toPlainText()) < 25: + if len(self.txt_description.toPlainText()) < 10: invalid_fields.append(self.txt_description) error_message += self.tr( - "- Description is not long enough (25 characters at least).\n" + "- The description is not long enough (10 characters at least).\n" ) - if len(self.txt_description.toPlainText()) > 160: + + # check date + if not len(self.dte_proposed_date.date().toString("dd/MM/yyyy")): invalid_fields.append(self.txt_description) - error_message += self.tr( - "- Description is too long (160 characters maximum).\n" - ) + error_message += self.tr("- Date has to be filled.\n") # check license - if not self.chb_license.isChecked(): - invalid_fields.append(self.chb_license) - error_message += self.tr("- License must be accepted.\n") + # if not self.cbb_license.isChecked(): + # invalid_fields.append(self.chb_license) + # error_message += self.tr("- License must be accepted.\n") # check author firstname if len(self.wdg_author.lne_firstname.text()) < 2: @@ -186,6 +133,55 @@ def accept(self) -> bool: for wdg in invalid_fields: wdg.setStyleSheet("border: 1px solid red;") return False - else: + + return True + + def on_btn_submit(self) -> Union[bool, str, None]: + """Check if required form fields are correctly filled and submit to Github issue + form. + + :return: False if some check fails. True and emit accepted() signal if + everything is ok. + :rtype: bool + """ + if not self.check_required_fields(): + return False + + completed_url = ( + f"{self.ISSUE_FORM_BASE_URL}" + f"&in_author_name={self.wdg_author.lne_firstname.text()} " + f"{self.wdg_author.lne_lastname.text()}" + f"&in_author_mail={self.wdg_author.lne_email.text()}" + f"&in_author_linkedin={self.wdg_author.lne_linkedin_account.text()}" + f"&in_author_mastodon={self.wdg_author.lne_mastodon_account.text()}" + f"&in_author_twitter={self.wdg_author.lne_twitter_account.text()}" + f"&in_author_license=true" + f"&cb_author_content_relationship={self.chb_transparency.isChecked()}" + f"&in_art_title={self.lne_title.text()}" + f"&in_art_date={self.dte_proposed_date.date().toString('dd/MM/yyyy')}" + f"&tx_art_content={self.txt_description.toPlainText()}" + f"&tx_misc_comment={self.txt_comment.toPlainText()} " + f"\n---\n\n{__title__} {__version__}" + f"&title=[Proposition] {self.lne_title.text()} - {__title__} {__version__}" + ) + self.log(message=f"Opening issue form: {completed_url}", log_level=4) + url_opened = open_url_in_browser(url=completed_url) + if url_opened: + self.log( + message=self.tr("Issue form URL opened in default system web browser."), + log_level=4, + ) super().accept() return True + else: + self.log( + parent_location=self, + message=self.tr( + "Opening issue form URL in default system web browser failed. " + "Check if there is any special characters in form fields and try again." + ), + push=True, + duration=10, + log_level=2, + ) + return False diff --git a/qtribu/gui/form_article.ui b/qtribu/gui/form_article.ui index 342fefa8..d32e3d51 100644 --- a/qtribu/gui/form_article.ui +++ b/qtribu/gui/form_article.ui @@ -6,7 +6,7 @@ 0 0 - 763 + 801 810 @@ -61,35 +61,77 @@ - + + + + 11 + 75 + true + + - Icon: + Planned publication date: - - + + + false + + + QAbstractSpinBox::PlusMinus + + true + + true + + + + 2030 + 12 + 31 + + + + + 2024 + 5 + 30 + + + + true + + + Qt::TimeZone + - + Keywords: - + true - + + + + 150 + 16777215 + + 11 @@ -100,9 +142,12 @@ Description: + + true + - + IBeamCursor @@ -148,16 +193,6 @@ - - - - I accept that my contribution is published under the CC BY-NC-SA 4.0 - - - false - - - @@ -173,19 +208,22 @@ - + Transparency: - + - I'm not related to the published content. If not, I give some details in the comment area. + I'm sure that the content fit with editing rules. If not, I give some details in the comment area. + + + @@ -252,22 +290,6 @@ - - btn_box - accepted() - dlg_form_rdp_news - accept() - - - 248 - 254 - - - 157 - 274 - - - btn_box rejected() diff --git a/qtribu/gui/form_rdp_news.py b/qtribu/gui/form_rdp_news.py index 5883a63f..39c6ea90 100644 --- a/qtribu/gui/form_rdp_news.py +++ b/qtribu/gui/form_rdp_news.py @@ -20,8 +20,13 @@ from qgis.PyQt.QtWidgets import QDialog, QDialogButtonBox, QWidget # plugin -from qtribu.__about__ import DIR_PLUGIN_ROOT, __title__, __version__ -from qtribu.constants import GEORDP_NEWS_CATEGORIES, GEORDP_NEWS_ICONS, GeotribuImage +from qtribu.__about__ import __title__, __version__ +from qtribu.constants import ( + GEORDP_NEWS_CATEGORIES, + GEORDP_NEWS_ICONS, + ICON_GEORDP, + GeotribuImage, +) from qtribu.toolbelt import NetworkRequestsManager, PlgLogger, PlgOptionsManager from qtribu.toolbelt.commons import open_url_in_browser @@ -29,7 +34,6 @@ class RdpNewsForm(QDialog): """QDialog form to submit a news to a next GeoRDP.""" - LOCAL_CDN_PATH: Path = Path().home() / ".geotribu/cdn/" ISSUE_FORM_BASE_URL: str = ( "https://github.com/geotribu/website/issues/new?template=RDP_NEWS.yml" ) @@ -48,7 +52,7 @@ def __init__(self, parent: Optional[QWidget] = None): self.qntwk = NetworkRequestsManager() # custom icon - self.setWindowIcon(QIcon(str(DIR_PLUGIN_ROOT / "resources/images/news.png"))) + self.setWindowIcon(ICON_GEORDP) # title self.lne_title.textChanged.connect(self.auto_preview) @@ -266,7 +270,8 @@ def on_btn_submit(self) -> Union[bool, str, None]: f"&in_news_title={self.lne_title.text()}" f"&in_news_icon={self.cbb_icon.currentText()}" f"&tx_news_content={self.txt_body.toPlainText()}" - f"&tx_misc_comment={self.txt_comment.toPlainText()}" + f"&tx_misc_comment={self.txt_comment.toPlainText()} " + f"\n---\n\n{__title__} {__version__}" f"&title=[GeoRDP] {self.lne_title.text()} - {__title__} {__version__}" ) self.log(message=f"Opening issue form: {completed_url}", log_level=4) diff --git a/qtribu/gui/form_rdp_news.ui b/qtribu/gui/form_rdp_news.ui index 59eeb313..ba853083 100644 --- a/qtribu/gui/form_rdp_news.ui +++ b/qtribu/gui/form_rdp_news.ui @@ -90,6 +90,12 @@ + + + 200 + 16777215 + + 11 @@ -98,7 +104,10 @@ - Body: + Body using Markdown syntax: + + + true diff --git a/qtribu/resources/i18n/qtribu_fr.ts b/qtribu/resources/i18n/qtribu_fr.ts index 3de21e56..31a12508 100644 --- a/qtribu/resources/i18n/qtribu_fr.ts +++ b/qtribu/resources/i18n/qtribu_fr.ts @@ -4,7 +4,7 @@ ArticleForm - + - A title is required, with at least 3 characters. - Un titre est requis, avec 3 caractères minimum. @@ -14,61 +14,83 @@ - Description is not long enough (25 characters at least). - - La description doit faire au moins 25 caractères. + - La description doit faire au moins 25 caractères. - Description is too long (160 characters maximum). - -La description doit faire 160 caractères maximum. + -La description doit faire 160 caractères maximum. - + - License must be accepted. - La licence doit être acceptée. - + - For attribution purpose, author's firstname is required. - Pour les besoins d'attribution, le prénom de l'auteur/e est requis. - + - For attribution purpose, author's lastname is required. - Pour les besoins d'attribution, le nom de l'auteur/e est requis. - + - For attribution purpose, author's email is required. - Pour les besoins d'attribution, l'email de l'auteur/e est requis. - + Some of required fields are incorrectly filled. Certains champs requis ne sont pas correctement renseignés. - + See details... Voir les détails... - + Fields in bold must be filled. Missing fields: Les champs dont le nom est en gras sont requis. Champs incorrects : + + + Submit + Envoyer + + + + - The description is not long enough (10 characters at least). + + - La description doit faire au moins 10 caractères. + + + + + Issue form URL opened in default system web browser. + Le formulaire prérempli a été ouvert dans le navigateur web par défaut du système. + + + + Opening issue form URL in default system web browser failed. Check if there is any special characters in form fields and try again. + L'ouverture de l'URL par le navigateur par défaut du système a échoué. Vérifier qu'il n'y a pas de caractère trop spécial dans les champs renseignés et réessayer. + AuthorInformationsWidget @@ -225,90 +247,83 @@ RdpNewsForm - + - A category is required. - Une catégorie est requise. - + - A title is required, with at least 3 characters. - Un titre est requis, avec 3 caractères minimum. - - - News is not long enougth (25 characters at least). - - - Le contenu de la news n'est pas assez long (25 caractères minimum). - - - - + - License must be accepted. - La licence doit être acceptée. - + - For attribution purpose, author's firstname is required. - Pour les besoins d'attribution, le prénom de l'auteur/e est requis. - + - For attribution purpose, author's lastname is required. - Pour les besoins d'attribution, le nom de l'auteur/e est requis. - + - For attribution purpose, author's email is required. - Pour les besoins d'attribution, l'email de l'auteur/e est requis. - + Some of required fields are incorrectly filled. Certains champs requis ne sont pas correctement renseignés. - + See details... Voir les détails... - + Fields in bold must be filled. Missing fields: Les champs dont le nom est en gras sont requis. Champs incorrects : - + Submit Envoyer - + - News is not long enough (25 characters at least). - Le contenu de la news doit faire au moins 25 caractères. - + Issue form URL opened in default system web browser. Le formulaire prérempli a été ouvert dans le navigateur web par défaut du système. - + Opening issue form URL in default system web browser failed. Check if there is any special characters in form fields and try again. L'ouverture de l'URL par le navigateur par défaut du système a échoué. Vérifier qu'il n'y a pas de caractère trop spécial dans les champs renseignés et réessayer. @@ -400,7 +415,7 @@ Icône : - + Category: Catégorie : @@ -412,30 +427,30 @@ Body: - Corps de la news : + Corps de la news : - + Publication Transparence et publication - + License: Licence : - + I accept that my contribution is published under the CC BY-NC-SA 4.0 J'accepte que ma contribution soit publiée en CC BY-NC-SA 4.0 - + Comment: Commentaire libre : - + Transparency: Transparence : @@ -445,40 +460,51 @@ Je ne fais pas d'autopromotion. Si c'est le cas, je donne des détails en commentaire. - + Preview Prévisualiser - + Enable auto generation of preview every time the input text changes. Activer la prévisualisation brute à la volée. - + Auto-preview Rendu automatique - + Minimal preview. Be careful, this render is not contractual with the final render on Geotribu website. Prévisualisation brute. Attention, ce rendu n'est pas contractuel et très différent du rendu final sur le site Geotribu. - + Raw preview: Rendu brut : - + I'm not related to the published content. If not, I give some details in the comment area. Ceci n'est pas une autopromotion, une publicité ou un simple copié/collé d'un CP etc. Si c'est le cas, ne pas cocher et donner des précisions en commentaire. - + Description: - Contenu de la news : + Description du projet d'article ou contenu complet au format Markdown : + + + + Body using Markdown syntax: + Corps du texte au format Markdown : + + + + I'm sure that the content fit with editing rules. If not, I give some details in the comment area. + Ceci n'est pas une publicité ou un simple copié/collé d'un CP etc. +Si c'est le cas, ne pas cocher et donner des précisions en commentaire.