Skip to content

Commit e93fd22

Browse files
committed
Use rich text html for jobs listing
1 parent 05ae23f commit e93fd22

File tree

10 files changed

+110
-22
lines changed

10 files changed

+110
-22
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/job_board/admin.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
from django.contrib import admin
22
from ordered_model.admin import OrderedModelAdmin
3+
from custom_admin.widgets import RichEditorWidget
34

45
from .models import JobListing
56

@@ -9,3 +10,9 @@ class JobListingAdmin(OrderedModelAdmin):
910
model = JobListing
1011
list_display = ("title", "company", "conference", "move_up_down_links")
1112
list_filter = ("conference",)
13+
14+
def formfield_for_dbfield(self, db_field, **kwargs):
15+
if db_field.name == "description":
16+
kwargs["widget"] = RichEditorWidget()
17+
18+
return super().formfield_for_dbfield(db_field, **kwargs)
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+
]

backend/job_board/models.py

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,6 @@
88
from model_utils.models import TimeStampedModel
99
from ordered_model.models import OrderedModel, OrderedModelManager
1010

11-
from i18n.fields import I18nCharField, I18nTextField
12-
1311

1412
class JobListingManager(OrderedModelManager):
1513
def by_slug(self, slug):
@@ -22,14 +20,14 @@ def by_slug(self, slug):
2220

2321

2422
class JobListing(TimeStampedModel, OrderedModel):
25-
title = I18nCharField(_("title"), max_length=200)
26-
slug = I18nCharField(_("slug"), max_length=200, blank=True)
23+
title = models.TextField(_("title"), max_length=200)
24+
slug = models.SlugField(_("slug"), max_length=200, blank=True)
2725
company = models.CharField(_("company"), max_length=100)
2826
company_logo = models.ImageField(
2927
_("company logo"), null=True, blank=True, upload_to="job-listings"
3028
)
31-
description = I18nTextField(_("description"), blank=True)
32-
apply_url = models.TextField(_("URL where you can apply"), blank=True)
29+
description = models.TextField(_("description"), blank=True)
30+
apply_url = models.TextField(_("Where you can apply"), blank=True)
3331
conference = models.ForeignKey(
3432
"conferences.Conference",
3533
on_delete=models.CASCADE,

frontend/src/components/job-board-layout/index.tsx

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,13 @@ import {
77
Page,
88
Section,
99
Spacer,
10+
StyledHTMLText,
1011
Text,
1112
} from "@python-italia/pycon-styleguide";
1213
import React from "react";
1314
import { FormattedMessage } from "react-intl";
1415

1516
import { JobListingAccordion } from "~/components/job-listing-accordion";
16-
import { compile } from "~/helpers/markdown";
1717
import type { AllJobListingsQueryResult } from "~/types";
1818

1919
import { Article } from "../article";
@@ -63,22 +63,27 @@ export const JobBoardLayout = ({
6363
onMobileShowOnly === "jobListings" ? "desktop" : "mobile"
6464
}
6565
fullScreenHeight
66-
overflow="scroll"
6766
>
6867
<Heading size={2}>{jobListing.title}</Heading>
6968
<Spacer size="small" />
7069
<Text size={2} color="grey-500">
7170
{jobListing.company}
7271
</Text>
7372
<Spacer size="large" />
74-
<Article>{compile(jobListing.description).tree}</Article>
73+
<Article>
74+
<StyledHTMLText
75+
baseTextSize={2}
76+
text={jobListing.description}
77+
/>
78+
</Article>
7579
<Spacer size="xl" />
7680
{jobListing.applyUrl && (
7781
<Button href={jobListing.applyUrl} variant="secondary">
7882
<FormattedMessage id="jobboard.applyNow" />
7983
</Button>
8084
)}
8185
</LayoutContent>
86+
<Spacer size="medium" />
8287
</GridColumn>
8388
</Grid>
8489
</Section>

frontend/src/components/job-detail-page-handler/index.tsx

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,10 @@ export const JobDetailPageHandler = () => {
1111
const {
1212
query: { id },
1313
} = useRouter();
14-
const language = useCurrentLanguage();
1514
const {
1615
data: { jobListings },
1716
} = useAllJobListingsQuery({
1817
variables: {
19-
language,
2018
conference: process.env.conferenceCode,
2119
},
2220
});

frontend/src/components/job-page-handler/jobs-page.graphql

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
1-
query AllJobListings($language: String!, $conference: String!) {
1+
query AllJobListings($conference: String!) {
22
jobListings(conference: $conference) {
33
id
4-
slug(language: $language)
5-
title(language: $language)
6-
description(language: $language)
4+
slug
5+
title
6+
description
77
applyUrl
88
company
99
companyLogo

frontend/src/pages/jobs/index.tsx

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@ export const getStaticProps: GetStaticProps = async ({ locale }) => {
1010
await Promise.all([
1111
prefetchSharedQueries(client, locale),
1212
queryAllJobListings(client, {
13-
language: locale,
1413
conference: process.env.conferenceCode,
1514
}),
1615
]);

0 commit comments

Comments
 (0)