Skip to content

Commit 0d195e6

Browse files
authored
Merge pull request #745 from thoth-pub/feature/add-venda
Feature/add venda
2 parents e1c3fb0 + c0efb57 commit 0d195e6

16 files changed

Lines changed: 229 additions & 24 deletions

File tree

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
66

77
## [Unreleased]
88

9+
### Added
10+
- [745](https://github.com/thoth-pub/thoth/pull/745) - Add Venda locale support for titles/books with `ve` and `ve-ZA`
11+
- [745](https://github.com/thoth-pub/thoth/pull/745) - Implement markup support for series description
12+
913
## [[1.0.5]](https://github.com/thoth-pub/thoth/releases/tag/v1.0.5) - 2026-04-15
1014
### Added
1115
- Add `workStatuses` filtering to `subjects` and `subjectCount` queries
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
DO $$
2+
BEGIN
3+
IF EXISTS (
4+
SELECT
5+
1
6+
FROM
7+
(
8+
SELECT
9+
locale_code::text AS locale_code
10+
FROM
11+
public.abstract
12+
UNION ALL
13+
SELECT
14+
locale_code::text
15+
FROM
16+
public.biography
17+
UNION ALL
18+
SELECT
19+
default_locale::text
20+
FROM
21+
public.imprint
22+
WHERE
23+
default_locale IS NOT NULL
24+
UNION ALL
25+
SELECT
26+
locale_code::text
27+
FROM
28+
public.title
29+
) AS locale_codes
30+
WHERE
31+
locale_code IN ('ve', 've_za')
32+
) THEN
33+
RAISE EXCEPTION 'Cannot revert locale_code enum while ve/ve_za values are in use.';
34+
END IF;
35+
END
36+
$$;
37+
38+
ALTER TYPE public.locale_code
39+
RENAME TO locale_code_old;
40+
41+
DO $$
42+
DECLARE
43+
locale_enum_labels TEXT;
44+
BEGIN
45+
SELECT
46+
string_agg(quote_literal(enumlabel), ', ' ORDER BY enumsortorder)
47+
INTO locale_enum_labels
48+
FROM
49+
pg_enum
50+
WHERE
51+
enumtypid = 'public.locale_code_old'::regtype
52+
AND enumlabel NOT IN ('ve', 've_za');
53+
54+
EXECUTE 'CREATE TYPE public.locale_code AS ENUM (' || locale_enum_labels || ')';
55+
END
56+
$$;
57+
58+
ALTER TABLE public.abstract
59+
ALTER COLUMN locale_code TYPE public.locale_code
60+
USING locale_code::text::public.locale_code;
61+
62+
ALTER TABLE public.biography
63+
ALTER COLUMN locale_code TYPE public.locale_code
64+
USING locale_code::text::public.locale_code;
65+
66+
ALTER TABLE public.imprint
67+
ALTER COLUMN default_locale TYPE public.locale_code
68+
USING default_locale::text::public.locale_code;
69+
70+
ALTER TABLE public.title
71+
ALTER COLUMN locale_code TYPE public.locale_code
72+
USING locale_code::text::public.locale_code;
73+
74+
DROP TYPE public.locale_code_old;
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
ALTER TYPE public.locale_code
2+
ADD VALUE IF NOT EXISTS 've' BEFORE 'vi';
3+
4+
ALTER TYPE public.locale_code
5+
ADD VALUE IF NOT EXISTS 've_za' BEFORE 'vi';

thoth-api/src/graphql/model.rs

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1718,8 +1718,25 @@ impl Series {
17181718
}
17191719

17201720
#[graphql(description = "Description of the series")]
1721-
pub fn series_description(&self) -> Option<&String> {
1722-
self.series_description.as_ref()
1721+
pub fn series_description(
1722+
&self,
1723+
#[graphql(
1724+
default = MarkupFormat::JatsXml,
1725+
description = "Markup format used for rendering series description",
1726+
)]
1727+
markup_format: Option<MarkupFormat>,
1728+
) -> FieldResult<Option<String>> {
1729+
self.series_description
1730+
.as_ref()
1731+
.map(|series_description| {
1732+
convert_from_jats(
1733+
series_description,
1734+
markup_format.ok_or(ThothError::MissingMarkupFormat)?,
1735+
ConversionLimit::Abstract,
1736+
)
1737+
})
1738+
.transpose()
1739+
.map_err(Into::into)
17231740
}
17241741

17251742
#[graphql(description = "URL of the series' call for proposals page")]

thoth-api/src/graphql/mutation.rs

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -117,9 +117,20 @@ impl MutationRoot {
117117
#[graphql(description = "Create a new series with the specified values")]
118118
fn create_series(
119119
context: &Context,
120-
#[graphql(description = "Values for series to be created")] data: NewSeries,
120+
#[graphql(description = "The markup format of the series description")]
121+
markup_format: Option<MarkupFormat>,
122+
#[graphql(description = "Values for series to be created")] mut data: NewSeries,
121123
) -> FieldResult<Series> {
122124
SeriesPolicy::can_create(context, &data, ())?;
125+
126+
let markup = markup_format.unwrap_or(MarkupFormat::JatsXml);
127+
data.series_description = data
128+
.series_description
129+
.map(|series_description| {
130+
convert_to_jats(series_description, markup, ConversionLimit::Abstract)
131+
})
132+
.transpose()?;
133+
123134
Series::create(&context.db, &data).map_err(Into::into)
124135
}
125136

@@ -466,11 +477,21 @@ impl MutationRoot {
466477
#[graphql(description = "Update an existing series with the specified values")]
467478
fn update_series(
468479
context: &Context,
469-
#[graphql(description = "Values to apply to existing series")] data: PatchSeries,
480+
#[graphql(description = "The markup format of the series description")]
481+
markup_format: Option<MarkupFormat>,
482+
#[graphql(description = "Values to apply to existing series")] mut data: PatchSeries,
470483
) -> FieldResult<Series> {
471484
let series = context.load_current(&data.series_id)?;
472485
SeriesPolicy::can_update(context, &series, &data, ())?;
473486

487+
let markup = markup_format.unwrap_or(MarkupFormat::JatsXml);
488+
data.series_description = data
489+
.series_description
490+
.map(|series_description| {
491+
convert_to_jats(series_description, markup, ConversionLimit::Abstract)
492+
})
493+
.transpose()?;
494+
474495
series.update(context, &data).map_err(Into::into)
475496
}
476497

thoth-api/src/graphql/tests.rs

Lines changed: 79 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1509,8 +1509,11 @@ fn assert_series_resolvers(series: &Series, context: &Context) {
15091509
assert_eq!(series.issn_digital(), series.issn_digital.as_ref());
15101510
assert_eq!(series.series_url(), series.series_url.as_ref());
15111511
assert_eq!(
1512-
series.series_description(),
1513-
series.series_description.as_ref()
1512+
series
1513+
.series_description(Some(MarkupFormat::JatsXml))
1514+
.unwrap()
1515+
.as_ref(),
1516+
series.series_description.as_ref(),
15141517
);
15151518
assert_eq!(series.series_cfp_url(), series.series_cfp_url.as_ref());
15161519
assert_eq!(series.imprint_id(), series.imprint_id);
@@ -2369,6 +2372,80 @@ fn graphql_award_supports_role_prize_statement_and_new_fields() {
23692372
.contains("<bold>"));
23702373
}
23712374

2375+
#[test]
2376+
fn graphql_series_description_supports_markup_roundtrip() {
2377+
let (_guard, pool) = test_db::setup_test_db();
2378+
let schema = create_schema();
2379+
let superuser = test_db::test_superuser("user-series-markup");
2380+
let context = test_db::test_context_with_user(pool.clone(), superuser);
2381+
let seed = seed_data(&schema, &context);
2382+
2383+
let series = create_with_data_and_markup(
2384+
&schema,
2385+
&context,
2386+
"createSeries",
2387+
"NewSeries",
2388+
"seriesId seriesDescription(markupFormat: PLAIN_TEXT)",
2389+
NewSeries {
2390+
series_type: SeriesType::Journal,
2391+
series_name: unique("Series"),
2392+
issn_print: None,
2393+
issn_digital: None,
2394+
series_url: Some("https://example.com/series".to_string()),
2395+
series_description: Some("**Initial** description".to_string()),
2396+
series_cfp_url: Some("https://example.com/cfp".to_string()),
2397+
imprint_id: seed.imprint_id,
2398+
},
2399+
MarkupFormat::Markdown,
2400+
);
2401+
2402+
assert_eq!(
2403+
series["seriesDescription"].as_str(),
2404+
Some("Initial description")
2405+
);
2406+
2407+
let series_id = json_uuid(&series["seriesId"]);
2408+
let stored = Series::from_id(pool.as_ref(), &series_id).expect("Failed to fetch series");
2409+
assert!(stored
2410+
.series_description
2411+
.as_deref()
2412+
.unwrap_or_default()
2413+
.contains("<bold>"));
2414+
2415+
let updated = update_with_data_and_markup(
2416+
&schema,
2417+
&context,
2418+
"updateSeries",
2419+
"PatchSeries",
2420+
"seriesId seriesDescription(markupFormat: PLAIN_TEXT)",
2421+
PatchSeries {
2422+
series_id,
2423+
series_type: stored.series_type,
2424+
series_name: stored.series_name.clone(),
2425+
issn_print: stored.issn_print.clone(),
2426+
issn_digital: stored.issn_digital.clone(),
2427+
series_url: stored.series_url.clone(),
2428+
series_description: Some("_Updated_ description".to_string()),
2429+
series_cfp_url: stored.series_cfp_url.clone(),
2430+
imprint_id: stored.imprint_id,
2431+
},
2432+
MarkupFormat::Markdown,
2433+
);
2434+
2435+
assert_eq!(
2436+
updated["seriesDescription"].as_str(),
2437+
Some("Updated description")
2438+
);
2439+
2440+
let updated_stored =
2441+
Series::from_id(pool.as_ref(), &series_id).expect("Failed to fetch series");
2442+
assert!(updated_stored
2443+
.series_description
2444+
.as_deref()
2445+
.unwrap_or_default()
2446+
.contains("<italic>"));
2447+
}
2448+
23722449
#[test]
23732450
fn graphql_additional_resource_exposes_date() {
23742451
let (_guard, pool) = test_db::setup_test_db();

thoth-api/src/markup/ast.rs

Lines changed: 4 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1768,16 +1768,10 @@ mod tests {
17681768
// Check that we have a SmallCaps node somewhere in the AST
17691769
fn find_small_caps(node: &Node) -> bool {
17701770
match node {
1771-
Node::SmallCaps(children) => {
1772-
if children.len() == 1 {
1773-
match &children[0] {
1774-
Node::Text(content) => content == "Small caps text",
1775-
_ => false,
1776-
}
1777-
} else {
1778-
false
1779-
}
1780-
}
1771+
Node::SmallCaps(children) => match children.as_slice() {
1772+
[Node::Text(content)] => content == "Small caps text",
1773+
_ => false,
1774+
},
17811775
Node::Document(children) | Node::Paragraph(children) => {
17821776
children.iter().any(find_small_caps)
17831777
}

thoth-api/src/model/locale/mod.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1972,6 +1972,13 @@ pub enum LocaleCode {
19721972
graphql(description = "Valencian (Spain Catalan) (ca-ES-valencia)")
19731973
)]
19741974
CaEsValencia,
1975+
#[cfg_attr(feature = "backend", graphql(description = "Venda (ve)"))]
1976+
Ve,
1977+
#[cfg_attr(
1978+
feature = "backend",
1979+
graphql(description = "Venda (South Africa) (ve-ZA)")
1980+
)]
1981+
VeZa,
19751982
#[cfg_attr(feature = "backend", graphql(description = "Vietnamese (vi)"))]
19761983
Vi,
19771984
#[cfg_attr(
@@ -2384,6 +2391,7 @@ impl From<LocaleCode> for LanguageCode {
23842391
| LocaleCode::VaiLatnLr
23852392
| LocaleCode::VaiVaii
23862393
| LocaleCode::VaiVaiiLr => LanguageCode::Vai,
2394+
LocaleCode::Ve | LocaleCode::VeZa => LanguageCode::Ven,
23872395
LocaleCode::Vi | LocaleCode::ViVn => LanguageCode::Vie,
23882396
LocaleCode::Wo => LanguageCode::Wol,
23892397
LocaleCode::Xh => LanguageCode::Xho,

thoth-api/src/model/locale/tests.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,10 @@ mod conversions {
9696
assert_eq!(lang, LanguageCode::Tib); // Tibetan
9797
let lang: LanguageCode = LocaleCode::Si.into();
9898
assert_eq!(lang, LanguageCode::Sin); // Sinhala
99+
let lang: LanguageCode = LocaleCode::Ve.into();
100+
assert_eq!(lang, LanguageCode::Ven); // Venda
101+
let lang: LanguageCode = LocaleCode::VeZa.into();
102+
assert_eq!(lang, LanguageCode::Ven); // Venda (South Africa)
99103
}
100104

101105
#[test]

thoth-client/src/queries.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -761,6 +761,8 @@ impl From<work_query::LocaleCode> for LocaleCode {
761761
work_query::LocaleCode::VAL => LocaleCode::Val,
762762
work_query::LocaleCode::VAL_ES => LocaleCode::ValEs,
763763
work_query::LocaleCode::CA_ES_VALENCIA => LocaleCode::CaEsValencia,
764+
work_query::LocaleCode::VE => LocaleCode::Ve,
765+
work_query::LocaleCode::VE_ZA => LocaleCode::VeZa,
764766
work_query::LocaleCode::VI => LocaleCode::Vi,
765767
work_query::LocaleCode::VI_VN => LocaleCode::ViVn,
766768
work_query::LocaleCode::VUN => LocaleCode::Vun,

0 commit comments

Comments
 (0)