diff --git a/afpy/__init__.py b/afpy/__init__.py index 49adb6f..023e6a2 100644 --- a/afpy/__init__.py +++ b/afpy/__init__.py @@ -47,18 +47,15 @@ def page_not_found(e): from afpy.routes.home import home_bp from afpy.routes.posts import posts_bp, post_render -from afpy.routes.jobs import jobs_bp, jobs_render from afpy.routes.rss import rss_bp application.register_blueprint(home_bp) application.register_blueprint(posts_bp) -application.register_blueprint(jobs_bp) application.register_blueprint(rss_bp) from afpy.models.AdminUser import AdminUser, AdminUser_Admin from afpy.models.NewsEntry import NewsEntry, NewsEntry_Admin -from afpy.models.JobPost import JobPost, JobPost_Admin from afpy.models.Slug import Slug, SlugAdmin @@ -66,7 +63,6 @@ from afpy.routes.admin import ( AdminIndexView, NewAdminView, ChangePasswordView, - JobsModerateView, NewsModerateView, CustomFileAdmin, ) @@ -81,10 +77,8 @@ admin = Admin( ) # Registers the views for each table -admin.add_view(JobsModerateView(name="Moderate Jobs", endpoint="jobs_moderation", category="Moderate")) admin.add_view(NewsModerateView(name="Moderate News", endpoint="news_moderation", category="Moderate")) admin.add_view(NewsEntry_Admin(NewsEntry)) -admin.add_view(JobPost_Admin(JobPost)) admin.add_view(SlugAdmin(Slug)) admin.add_view(CustomFileAdmin(config.IMAGES_PATH, "/images/", name="Images Files")) admin.add_view(NewAdminView(name="New Admin", endpoint="register_admin", category="Admin")) @@ -107,10 +101,7 @@ def get_slug_url(item): url_root = request.url_root slug = item.slug.where(Slug.canonical == True).first() # noqa if not slug: - if isinstance(item, JobPost): - return url_root[:-1] + "/emplois/" + str(item.id) - else: - return url_root[:-1] + "/actualites/" + str(item.id) + return url_root[:-1] + "/actualites/" + str(item.id) else: return url_root[:-1] + slug.url @@ -122,5 +113,3 @@ def slug_fallback(slug): abort(404) if slug.newsentry: return post_render(slug.newsentry.id) - elif slug.jobpost: - return jobs_render(slug.jobpost.id) diff --git a/afpy/forms/JobPost.py b/afpy/forms/JobPost.py deleted file mode 100644 index 1931d3e..0000000 --- a/afpy/forms/JobPost.py +++ /dev/null @@ -1,23 +0,0 @@ -from flask_pagedown.fields import PageDownField -from flask_wtf import FlaskForm -from wtforms import FileField -from wtforms import StringField -from wtforms import validators -from wtforms.validators import DataRequired - - -def validate_email_or_phone(form, field): - if not form.email.data and not form.phone.data: - raise validators.ValidationError("Must have phone or email") - - -class JobPostForm(FlaskForm): - title = StringField("Titre", validators=[DataRequired()]) - summary = StringField("Résumé (optionnel)") - content = PageDownField("Contenu de l'offre", validators=[DataRequired()]) - company = StringField("Entreprise", validators=[DataRequired()]) - location = StringField("Addresse", validators=[DataRequired()]) - contact_info = StringField("Personne à contacter", validators=[DataRequired()]) - email = StringField("Email", validators=[validate_email_or_phone]) - phone = StringField("Téléphone", validators=[validate_email_or_phone]) - image = FileField("Image (optionnel)") diff --git a/afpy/models/JobPost.py b/afpy/models/JobPost.py deleted file mode 100644 index 1dbe19e..0000000 --- a/afpy/models/JobPost.py +++ /dev/null @@ -1,111 +0,0 @@ -from datetime import datetime -from typing import Optional - -from flask_admin.contrib.peewee import ModelView -from flask_login import current_user -from peewee import CharField -from peewee import DateTimeField -from peewee import ForeignKeyField -from peewee import TextField - -from afpy.models import BaseModel -from afpy.models.AdminUser import AdminUser - - -class JobPost(BaseModel): - title = TextField(null=False, help_text="Title of the job post", verbose_name="Title") - summary = TextField(null=True, help_text="Summary of the job post", verbose_name="Summary") - content = TextField(null=False, help_text="Content of the job post", verbose_name="Content") - dt_submitted = DateTimeField( - null=False, - default=datetime.now, - help_text="When was the job post submitted", - verbose_name="Datetime Submitted", - index=True, - ) - dt_updated = DateTimeField( - null=False, default=datetime.now, help_text="When was the job post updated", verbose_name="Datetime Updated" - ) - dt_published = DateTimeField( - null=True, help_text="When was the job post published", verbose_name="Datetime Published" - ) - state = CharField( - null=False, - default="waiting", - choices=[("waiting", "waiting"), ("published", "published"), ("rejected", "rejected")], - help_text="Current state of the job post", - verbose_name="State", - ) - approved_by = ForeignKeyField( - AdminUser, - null=True, - default=None, - backref="adminuser", - help_text="Who approved the job post", - verbose_name="Approved by", - ) - - company = CharField(null=False, help_text="Company that posted the job", verbose_name="Company") - phone = CharField(null=True, help_text="Phone number to contact", verbose_name="Phone Number") - location = CharField(null=False, help_text="Where is the job located", verbose_name="Job Location") - email = CharField(null=True, help_text="Email to contact", verbose_name="Email Address") - contact_info = CharField(null=False, help_text="Person to contact", verbose_name="Contact info") - image_path = CharField(null=True, help_text="Image for the job post", verbose_name="Image Path in filesystem") - - @classmethod - def create( - cls, - title: str, - content: str, - company: str, - location: str, - contact_info: str, - email: Optional[str] = None, - phone: Optional[str] = None, - summary: Optional[str] = None, - dt_submitted: Optional[datetime] = None, - dt_updated: Optional[datetime] = None, - dt_published: Optional[datetime] = None, - state: str = "waiting", - approved_by: Optional[AdminUser] = None, - image_path: Optional[str] = None, - ): - if not dt_submitted: - dt_submitted = datetime.now() - if not dt_updated: - dt_updated = datetime.now() - - if not email and not phone: - raise ValueError("One of email or phone must be provided") - - new_job = super().create( - title=title, - content=content, - company=company, - location=location, - contact_info=contact_info, - email=email, - phone=phone, - summary=summary, - dt_submitted=dt_submitted, - dt_updated=dt_updated, - dt_published=dt_published, - state=state, - approved_by=approved_by, - image_path=image_path, - ) - new_job.save() - return new_job - - -class JobPost_Admin(ModelView): - model_class = JobPost - column_list = ("state", "title", "dt_published") - column_default_sort = ("id", True) - - def is_accessible(self): - return current_user.is_authenticated - - -if not JobPost.table_exists(): - JobPost.create_table() diff --git a/afpy/models/Slug.py b/afpy/models/Slug.py index 5ef164f..c57203d 100644 --- a/afpy/models/Slug.py +++ b/afpy/models/Slug.py @@ -5,13 +5,11 @@ from peewee import CharField from peewee import ForeignKeyField from afpy.models import BaseModel -from afpy.models.JobPost import JobPost from afpy.models.NewsEntry import NewsEntry class Slug(BaseModel): url = CharField(null=False, help_text="From URL", verbose_name="From URL", unique=True, index=True) - jobpost = ForeignKeyField(JobPost, backref="slug", null=True) newsentry = ForeignKeyField(NewsEntry, backref="slug", null=True) canonical = BooleanField(default=True) diff --git a/afpy/routes/admin.py b/afpy/routes/admin.py index 1141302..d9162bc 100644 --- a/afpy/routes/admin.py +++ b/afpy/routes/admin.py @@ -19,7 +19,6 @@ from afpy.forms.auth import ChangePasswordForm from afpy.forms.auth import LoginForm from afpy.forms.auth import RegistrationForm from afpy.models.AdminUser import AdminUser -from afpy.models.JobPost import JobPost from afpy.models.NewsEntry import NewsEntry @@ -129,11 +128,6 @@ class _ModerateView(admin.BaseView): return redirect(url_for(".moderate_view")) -class JobsModerateView(_ModerateView): - model = JobPost - edit_view = "jobpost.edit_view" - - class NewsModerateView(_ModerateView): model = NewsEntry edit_view = "newsentry.edit_view" diff --git a/afpy/routes/home.py b/afpy/routes/home.py index fc09d71..5b701d0 100644 --- a/afpy/routes/home.py +++ b/afpy/routes/home.py @@ -8,7 +8,6 @@ from flask import render_template from flask import send_from_directory from peewee import DoesNotExist -from afpy.models.JobPost import JobPost from afpy.models.NewsEntry import NewsEntry from afpy import config @@ -56,9 +55,6 @@ def status(): "actualites": { "waiting": NewsEntry.select().where(NewsEntry.state == "waiting").count(), }, - "emplois": { - "waiting": JobPost.select().where(JobPost.state == "waiting").count(), - }, } diff --git a/afpy/routes/jobs.py b/afpy/routes/jobs.py index 85eb730..02ce29b 100644 --- a/afpy/routes/jobs.py +++ b/afpy/routes/jobs.py @@ -18,33 +18,15 @@ jobs_bp = Blueprint("jobs", __name__) @jobs_bp.route("/emplois/") def jobs_render(post_id: int): - try: - job = JobPost.get_by_id(post_id) - except DoesNotExist: - abort(404) - return render_template("pages/job.html", body_id="emplois", job=job, name=job.title) + return redirect("https://discuss.afpy.org/c/emplois/14") @jobs_bp.route("/emplois") @jobs_bp.route("/emplois/page/") def jobs_page(current_page: int = 1): - total_pages = (JobPost.select().where(JobPost.state == "published").count() // config.NEWS_PER_PAGE) + 1 - jobs = ( - JobPost.select() - .where(JobPost.state == "published") - .order_by(JobPost.dt_submitted.desc()) - .paginate(current_page, config.NEWS_PER_PAGE) - ) - return render_template( - "pages/jobs.html", - body_id="emplois", - jobs=jobs, - title="Offres d'emploi", - current_page=current_page, - total_pages=total_pages, - ) + return redirect("https://discuss.afpy.org/c/emplois/14") @jobs_bp.route("/emplois/new", methods=["GET"]) def new_job(): - return render_template("pages/edit_job.html") + return redirect("https://discuss.afpy.org/c/emplois/14") diff --git a/afpy/routes/rss.py b/afpy/routes/rss.py index ba7613a..6b9bfea 100644 --- a/afpy/routes/rss.py +++ b/afpy/routes/rss.py @@ -6,8 +6,8 @@ from flask import abort from flask import Blueprint from flask import render_template from flask import url_for +from flask import redirect -from afpy.models.JobPost import JobPost from afpy.models.NewsEntry import NewsEntry from afpy import config @@ -20,8 +20,7 @@ def feed_rss(type): name = "" entries = [] if type == "emplois": - name = "Emplois" - entries = JobPost.select().where(JobPost.state == "published") + return redirect("https://discuss.afpy.org/c/emplois/14.rss") elif type == "actualites": name = "Actualités" entries = NewsEntry.select().where(NewsEntry.state == "published") diff --git a/afpy/templates/_parts/nav_menu.jinja2 b/afpy/templates/_parts/nav_menu.jinja2 index b82e8fb..b898d0d 100644 --- a/afpy/templates/_parts/nav_menu.jinja2 +++ b/afpy/templates/_parts/nav_menu.jinja2 @@ -4,7 +4,7 @@ (url_for('home.home_page'), 'index', 'Accueil'), (url_for('home.render_rest', name='a-propos'), 'a-propos', 'Qui sommes-nous ?'), (url_for('posts.posts_page'), 'actualites', 'Actualités'), - (url_for('jobs.jobs_page'), 'emplois', 'Offres d\'emplois'), + ("https://discuss.afpy.org/c/emplois/14", 'emplois', 'Offres d\'emplois'), (url_for('home.community_page'), 'communaute', 'Communauté'), ('https://discuss.afpy.org', 'discussion', 'Discussion'), ('https://www.afpy.org/discord', 'discord', 'Discord'), diff --git a/afpy/templates/admin/index.html b/afpy/templates/admin/index.html index 1e84d89..9b89b54 100644 --- a/afpy/templates/admin/index.html +++ b/afpy/templates/admin/index.html @@ -7,7 +7,7 @@ {% if current_user.is_authenticated %}

AFPy Backend Admin

- Bienvenue dans le backoffice de l'AFPy. Vous avez accès à la création, modification et suppression d'articles, jobs et admins, ainsi qu'aux tables.
+ Bienvenue dans le backoffice de l'AFPy. Vous avez accès à la création, modification et suppression d'articles et admins, ainsi qu'aux tables.
Ne touchez à rien si vous ne savez pas ce que vous faites.

{% else %} diff --git a/afpy/templates/pages/edit_job.html b/afpy/templates/pages/edit_job.html deleted file mode 100644 index 3cc694d..0000000 --- a/afpy/templates/pages/edit_job.html +++ /dev/null @@ -1,23 +0,0 @@ -{% extends '_parts/base.jinja2' %} - -{% block header %} -

Création d'un job

-{% endblock header %} - -{% block main %} - -
-

Pour plus de visibilité, la job board de l'AFPy bouge ici : https://discuss.afpy.org/c/emplois !

-

- Pour créer une offre d'emploi là bas, deux solutions :
-

    -
  • Envoyer un email à jobs at afpy point org, le titre de votre offre en sujet, le message de votre offre en corps de message, c'est tout.
  • -
  • Publier l'offre directement sur le forum, dans la catégorie « Offres d'emploi » en cliquant sur le bouton « Créer un sujet »
  • -
-

-

C'est quoi https://discuss.afpy.org?

-

- C'est une instance de Discourse, un forum open source qu'on héberge en france chez Gandi. -

-
-{% endblock main %} diff --git a/afpy/templates/pages/job.html b/afpy/templates/pages/job.html deleted file mode 100755 index b887f52..0000000 --- a/afpy/templates/pages/job.html +++ /dev/null @@ -1,51 +0,0 @@ -{% extends '_parts/base.jinja2' %} - -{% block header %} -

{{ job.title }}

-{% endblock header %} - -{% block main %} - - {% if preview %} - Retour à l'interface d'administration - {#

Edit

#} - {% endif %} - -
- {% if preview %} - - {% else %} - - {% endif %} -

- - {{ job.summary | safe if job.summary }} - -

- {% if job.image_path %} - {{ job.title }} - {% endif %} - {{ job.content | md2html | safe }} - -
-{% endblock main %} diff --git a/afpy/templates/pages/jobs.html b/afpy/templates/pages/jobs.html deleted file mode 100755 index f09e4f9..0000000 --- a/afpy/templates/pages/jobs.html +++ /dev/null @@ -1,41 +0,0 @@ -{% extends '_parts/base.jinja2' %} - -{% block header %} -

{{ title }}

-{% endblock header %} - -{% block main %} - - {% for job in jobs %} -
-

{{ job.title }}

- - {% if job.image_path %} - {{ job.title }} - {% endif %} - {% if job.summary %}{{ job.summary |safe }}{% else %}{{ job.content|truncate(50)|safe }}{% endif %} -

Lire la suite…

-
- {% endfor %} - - -{% endblock main %} diff --git a/afpy/templates/pages/post.html b/afpy/templates/pages/post.html index 64f13ef..10a282e 100755 --- a/afpy/templates/pages/post.html +++ b/afpy/templates/pages/post.html @@ -7,7 +7,6 @@ {% block main %} {% if preview %} Retour à l'interface d'administration - {#

Edit

#} {% endif %}
diff --git a/afpy/templates/pages/rss.xml b/afpy/templates/pages/rss.xml index fe4fa26..4c05b05 100755 --- a/afpy/templates/pages/rss.xml +++ b/afpy/templates/pages/rss.xml @@ -8,11 +8,7 @@ <![CDATA[ {{ entry.title | safe }} ]]> - {% if type == "emplois" %} - {{ url_for("jobs.jobs_render", post_id=entry.id, _external=True) }} - {% else %} - {{ url_for("posts.post_render", post_id=entry.id, _external=True) }} - {% endif %} + {{ url_for("posts.post_render", post_id=entry.id, _external=True) }} {{ entry.dt_published }} {% endfor %} diff --git a/xml2sql.py b/xml2sql.py index 05ac59d..14ba75d 100644 --- a/xml2sql.py +++ b/xml2sql.py @@ -8,16 +8,14 @@ from dateutil.parser import parse from html2text import html2text from afpy.models.AdminUser import AdminUser -from afpy.models.JobPost import JobPost from afpy.models.NewsEntry import NewsEntry from afpy.models.Slug import Slug PAGINATION = 12 CATEGORY_ACTUALITIES = "actualites" -CATEGORY_JOBS = "emplois" -CATEGORIES = {CATEGORY_ACTUALITIES: "Actualités", CATEGORY_JOBS: "Offres d’emploi"} +CATEGORIES = {CATEGORY_ACTUALITIES: "Actualités"} STATE_WAITING = "waiting" STATE_PUBLISHED = "published" @@ -110,30 +108,3 @@ if __name__ == "__main__": post_id = post.get("id") if post_id: Slug.create(url=post_id.split("afpy.org")[-1], newsentry=new_post) - else: - email = post.get("email", "") - phone = post.get("phone", "") - if not email and not phone: - phone = "(no phone)" - new_job = JobPost.create( - title=post.get("title", "(untitled)"), - summary=post.get("summary"), - content=html2text(post.get("content", "")), - company=post.get("company", ""), - email=email, - phone=phone, - location=post.get("address", ""), - contact_info=post.get("contact", ""), - dt_published=parse(post.get("published")).replace(tzinfo=None) - if state == "published" - else None, - dt_submitted=parse(post.get("published")).replace(tzinfo=None), - dt_updated=parse(post.get("published")).replace(tzinfo=None), - state=state, - approved_by=admin_1 if state == "published" or state == "rejected" else None, - image_path=post.get("image"), - ) - Slug.create(url=f"/posts/emplois/{post.get(FIELD_TIMESTAMP)}", jobpost=new_job) - post_id = post.get("id") - if post_id: - Slug.create(url=post_id.split("afpy.org")[-1], jobpost=new_job)