Skip to content

Commit

Permalink
Merge pull request #170 from geotribu/feature/connect-article-form
Browse files Browse the repository at this point in the history
feature(forms): connecte le formulaire d'article au formulaire GitHub
  • Loading branch information
Guts authored May 1, 2024
2 parents 3322ade + 6087679 commit ed1505d
Show file tree
Hide file tree
Showing 6 changed files with 232 additions and 173 deletions.
1 change: 1 addition & 0 deletions qtribu/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
164 changes: 80 additions & 84 deletions qtribu/gui/form_article.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,26 +9,27 @@
# 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


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
Expand All @@ -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 = ""

Expand All @@ -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:
Expand Down Expand Up @@ -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
Loading

0 comments on commit ed1505d

Please sign in to comment.