Skip to content

Commit 88d1243

Browse files
authored
Use rich text html for jobs listing (#4402)
1 parent 05ae23f commit 88d1243

File tree

18 files changed

+204
-57
lines changed

18 files changed

+204
-57
lines changed

backend/api/job_board/schema.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,9 @@ class JobBoardQuery:
1111
def job_listings(self, conference: str) -> list[JobListingType]:
1212
return [
1313
JobListingType.from_django_model(listing)
14-
for listing in JobListing.objects.filter(conference__code=conference).all()
14+
for listing in JobListing.objects.filter(conference__code=conference)
15+
.order_by("order")
16+
.all()
1517
]
1618

1719
@strawberry.field

backend/api/job_board/types.py

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,13 @@
22

33
import strawberry
44

5-
from ..helpers.i18n import make_localized_resolver
6-
75

86
@strawberry.type
97
class JobListing:
108
id: strawberry.ID
11-
title: str = strawberry.field(resolver=make_localized_resolver("title"))
12-
slug: str = strawberry.field(resolver=make_localized_resolver("slug"))
13-
description: str = strawberry.field(resolver=make_localized_resolver("description"))
9+
title: str
10+
slug: str
11+
description: str
1412
company: str
1513
company_logo_url: strawberry.Private[Optional[str]]
1614
apply_url: str

backend/api/tests/test_job_board.py

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
from pytest import mark
44

55
from helpers.tests import get_image_url_from_request
6-
from i18n.strings import LazyI18nString
76

87

98
def _query_job_board(client, conference):
@@ -50,7 +49,7 @@ def test_query_job_board(rf, graphql_client):
5049
@mark.django_db
5150
def test_query_single_job_listing(rf, graphql_client):
5251
listing = JobListingFactory(
53-
slug=LazyI18nString({"en": "demo", "it": "esempio"}),
52+
slug="demo",
5453
company_logo=None,
5554
)
5655

@@ -92,15 +91,15 @@ def test_query_single_job_listing(rf, graphql_client):
9291
@mark.django_db
9392
def test_passing_language(graphql_client):
9493
JobListingFactory(
95-
title=LazyI18nString({"en": "this is a test", "it": "diventa una lumaca"}),
96-
slug=LazyI18nString({"en": "slug", "it": "lumaca"}),
94+
title="diventa una lumaca",
95+
slug="lumaca",
9796
)
9897

9998
resp = graphql_client.query(
10099
"""query {
101-
jobListing(slug: "slug") {
102-
title(language: "it")
103-
slug(language: "it")
100+
jobListing(slug: "lumaca") {
101+
title
102+
slug
104103
}
105104
} """
106105
)

backend/cms/components/page/tasks.py

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@ def revalidate_vercel_frontend_task(page_id):
1414

1515
settings = VercelFrontendSettings.for_site(site)
1616

17-
site_name = site.site_name
1817
hostname = site.hostname
1918

2019
url = settings.revalidate_url
@@ -48,6 +47,15 @@ def revalidate_vercel_frontend_task(page_id):
4847
else:
4948
path = f"/{language_code}{page_path}"
5049

50+
execute_frontend_revalidate(
51+
url=url,
52+
path=path,
53+
secret=secret,
54+
)
55+
56+
57+
@app.task
58+
def execute_frontend_revalidate(url: str, path: str, secret: str):
5159
try:
5260
response = requests.post(
5361
url,
@@ -59,7 +67,7 @@ def revalidate_vercel_frontend_task(page_id):
5967
)
6068
response.raise_for_status()
6169
except Exception as e:
62-
logger.error(f"Error while revalidating {path} on {site_name}: {e}")
70+
logger.error(f"Error while revalidating {path}: {e}")
6371
return
6472

65-
logger.info(f"Revalidated {path} on {site_name}")
73+
logger.info(f"Revalidated {path}")

backend/conferences/admin/conference.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,15 @@ class ConferenceAdmin(
162162
)
163163
},
164164
),
165+
(
166+
"Frontend Settings",
167+
{
168+
"fields": (
169+
"frontend_revalidate_url",
170+
"frontend_revalidate_secret",
171+
)
172+
},
173+
),
165174
(
166175
"Conference",
167176
{
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
# Generated by Django 5.1.4 on 2025-04-13 18:06
2+
3+
from django.db import migrations, models
4+
5+
6+
class Migration(migrations.Migration):
7+
8+
dependencies = [
9+
('conferences', '0053_conference_slack_new_invitation_letter_request_channel_id'),
10+
]
11+
12+
operations = [
13+
migrations.AddField(
14+
model_name='conference',
15+
name='frontend_revalidate_secret',
16+
field=models.CharField(blank=True, default='', max_length=32224),
17+
),
18+
migrations.AddField(
19+
model_name='conference',
20+
name='frontend_revalidate_url',
21+
field=models.URLField(blank=True, default=''),
22+
),
23+
]

backend/conferences/models/conference.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,16 @@ class Conference(GeoLocalizedModel, TimeFramedModel, TimeStampedModel):
148148
blank=True,
149149
)
150150

151+
frontend_revalidate_url = models.URLField(
152+
default="",
153+
blank=True,
154+
)
155+
frontend_revalidate_secret = models.CharField(
156+
default="",
157+
blank=True,
158+
max_length=32224,
159+
)
160+
151161
def get_slack_oauth_token(self):
152162
return self.organizer.slack_oauth_bot_token
153163

backend/job_board/admin.py

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
from django.contrib import admin
2+
from cms.components.page.tasks import execute_frontend_revalidate
23
from ordered_model.admin import OrderedModelAdmin
4+
from custom_admin.widgets import RichEditorWidget
35

46
from .models import JobListing
57

@@ -9,3 +11,28 @@ class JobListingAdmin(OrderedModelAdmin):
911
model = JobListing
1012
list_display = ("title", "company", "conference", "move_up_down_links")
1113
list_filter = ("conference",)
14+
15+
def formfield_for_dbfield(self, db_field, **kwargs):
16+
if db_field.name == "description":
17+
kwargs["widget"] = RichEditorWidget()
18+
19+
return super().formfield_for_dbfield(db_field, **kwargs)
20+
21+
def save_model(self, request, obj, form, change):
22+
super().save_model(request, obj, form, change)
23+
conference = obj.conference
24+
25+
if not conference.frontend_revalidate_url:
26+
return
27+
28+
for locale in ["en", "it"]:
29+
execute_frontend_revalidate.delay(
30+
url=conference.frontend_revalidate_url,
31+
path=f"/{locale}/jobs/",
32+
secret=conference.frontend_revalidate_secret,
33+
)
34+
execute_frontend_revalidate.delay(
35+
url=conference.frontend_revalidate_url,
36+
path=f"/{locale}/jobs/{obj.id}",
37+
secret=conference.frontend_revalidate_secret,
38+
)
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
# Generated by Django 5.1.4 on 2025-04-13 16:00
2+
3+
from django.db import migrations, models
4+
5+
6+
def fix_data(apps, schema_editor):
7+
JobListing = apps.get_model('job_board', 'JobListing')
8+
for job_listing in JobListing.objects.all():
9+
if job_listing.slug:
10+
slug = job_listing.slug.localize('en')
11+
assert slug
12+
job_listing.slug = slug
13+
if job_listing.title:
14+
title = job_listing.title.localize('en')
15+
assert title
16+
job_listing.title = title
17+
if job_listing.description:
18+
description = job_listing.description.localize('en')
19+
assert description
20+
job_listing.description = description
21+
job_listing.save()
22+
23+
class Migration(migrations.Migration):
24+
25+
dependencies = [
26+
('job_board', '0005_connect_job_listings_to_a_conf'),
27+
]
28+
29+
operations = [
30+
migrations.RunPython(fix_data, migrations.RunPython.noop),
31+
migrations.AlterField(
32+
model_name='joblisting',
33+
name='apply_url',
34+
field=models.TextField(blank=True, verbose_name='Where you can apply'),
35+
),
36+
migrations.AlterField(
37+
model_name='joblisting',
38+
name='description',
39+
field=models.TextField(blank=True, verbose_name='description'),
40+
),
41+
migrations.AlterField(
42+
model_name='joblisting',
43+
name='slug',
44+
field=models.SlugField(blank=True, max_length=200, verbose_name='slug'),
45+
),
46+
migrations.AlterField(
47+
model_name='joblisting',
48+
name='title',
49+
field=models.TextField(max_length=200, verbose_name='title'),
50+
),
51+
]
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
# Generated by Django 5.1.4 on 2025-04-13 16:08
2+
3+
from django.db import migrations
4+
5+
def fix_quotes(apps, schema_editor):
6+
JobListing = apps.get_model('job_board', 'JobListing')
7+
for job_listing in JobListing.objects.all():
8+
if job_listing.title:
9+
title = job_listing.title.replace('"', "")
10+
assert title
11+
job_listing.title = title
12+
if job_listing.description:
13+
description = job_listing.description.replace('"', "")
14+
assert description
15+
job_listing.description = description
16+
if job_listing.slug:
17+
slug = job_listing.slug.replace('"', "")
18+
assert slug
19+
job_listing.slug = slug
20+
job_listing.save()
21+
22+
class Migration(migrations.Migration):
23+
24+
dependencies = [
25+
('job_board', '0006_alter_joblisting_apply_url_and_more'),
26+
]
27+
28+
operations = [
29+
migrations.RunPython(fix_quotes, migrations.RunPython.noop),
30+
]

0 commit comments

Comments
 (0)