Skip to content

Fix(integration) zendesk articles#641

Merged
michnowak merged 4 commits intomainfrom
fix(integration)-zendesk-articles
Feb 5, 2026
Merged

Fix(integration) zendesk articles#641
michnowak merged 4 commits intomainfrom
fix(integration)-zendesk-articles

Conversation

@michnowak
Copy link
Copy Markdown
Contributor

@michnowak michnowak commented Feb 4, 2026

What does this PR do?

  • My bugfix

Related Ticket(s)

  • Notion Ticket

Key Changes

  • How does the code change address the issue? Describe, at a high level, what was done to affect change.
  • What side effects does this change have? This is the most important question to answer, as it can point out problems where you are making too many changes in one commit or branch. One or two bullet points for related changes may be okay, but five or six are likely indicators of a commit that is doing too many things.

How to test

  • Create a detailed description of what you need to do to set this PR up. ie: Does it need migrations? Do you need to install something?
  • Create a step by step list of what the engineer needs to do to test.

Media (Loom or gif)

  • Insert media here (if applicable)

Summary by CodeRabbit

  • New Features

    • Blocks and search can include a parent/basePath so CMS-configured base paths are applied to article and category URLs; search block exposes a parent prop.
  • Refactor

    • Slug/URL construction changed to return compact category/article slugs; full URLs are composed using the CMS base path.
    • Zendesk integration removed locale-specific base-path rewriting.
  • Documentation

    • Docs updated with new slug formats, examples, and guidance on configuring base paths.
  • Chores

    • Release changeset added.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Feb 4, 2026

Walkthrough

Slugs changed to category/article segment format (no locale/base). A CMS-configured basePath (parent.slug) is derived and threaded through frontend, services, and mappers to build full URLs; Zendesk mappers drop locale-based URL logic and now emit segment-only slugs.

Changes

Cohort / File(s) Summary
Page module
apps/api-harmonization/src/modules/page/page.mapper.ts, apps/api-harmonization/src/modules/page/page.service.ts
mapArticle/mapArticleBreadcrumbs accept basePath; page.service derives basePath from query.slug and passes it; breadcrumbs simplified to category + article entries using computed URLs.
Article search block
packages/blocks/article-search/src/api-harmonization/article-search.mapper.ts, packages/blocks/article-search/src/api-harmonization/article-search.model.ts, packages/blocks/article-search/src/api-harmonization/article-search.request.ts, packages/blocks/article-search/src/api-harmonization/article-search.service.ts, packages/blocks/article-search/src/frontend/ArticleSearch.client.tsx
Adds optional parent/parent.slug to block model and props; SearchArticlesQuery gains basePath?; mapArticles gains optional basePath and service/frontend pass parent?.slug.
Block mappers
packages/blocks/article-list/src/api-harmonization/article-list.mapper.ts, packages/blocks/category-list/src/api-harmonization/category-list.mapper.ts, packages/blocks/category/src/api-harmonization/category.mapper.ts
Derive basePath from cms.parent?.slug; prefix/normalize category and article slugs with basePath; mapArticle signatures updated to accept basePath.
Zendesk integration
packages/integrations/zendesk/src/modules/articles/zendesk-article.mapper.ts, packages/integrations/zendesk/src/modules/articles/zendesk-article.service.ts
Removed locale-based base path helpers and link transformation; mapper signatures drop locale; mappers emit segment-only slugs and higher-level callers assemble full URLs using configured basePath.
Documentation
apps/docs/docs/integrations/articles/zendesk/features.md, apps/docs/docs/integrations/articles/zendesk/usage.md
Docs updated to show new slug format (category/article segments without base path), examples revised, and notes that base path comes from CMS parent.slug.
Framework & mocks
packages/framework/src/modules/cms/models/blocks/article-search.model.ts, packages/integrations/mocked/src/modules/cms/mappers/blocks/cms.article-search.mapper.ts
Added optional parent: { slug: string } to ArticleSearchBlock model and updated mock ArticleSearchBlock locales to include parent.slug.
Release metadata
.changeset/smooth-mails-fall.md
Adds changeset noting zendesk feature removing hardcoded locale base paths and package version bumps.

Sequence Diagram(s)

sequenceDiagram
  participant Frontend
  participant CMS
  participant SDK
  participant Service
  participant Mapper

  Frontend->>CMS: read block parent.slug (optional)
  Frontend->>SDK: request.searchArticles({ basePath: parent?.slug })
  SDK->>Service: searchArticles(query with basePath)
  Service->>Mapper: mapArticles(articles, basePath)
  Mapper->>Mapper: prefix slugs with basePath -> produce full URLs
  Mapper-->>Service: Article payloads (slug/url)
  Service-->>Frontend: response (blocks with parent & URLs)
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

Suggested reviewers

  • marcinkrasowski

Poem

🐰 I hopped slugs into tidy two-part song,

CMS seeds the path I carry along,
Mappers stitch segments into a trail,
Breadcrumbs whisper the simplified tale,
A rabbit's hop — URLs now sing along.

🚥 Pre-merge checks | ✅ 1 | ❌ 2
❌ Failed checks (2 warnings)
Check name Status Explanation Resolution
Description check ⚠️ Warning The PR description is entirely a template with placeholder text and contains no concrete information about the changes, related tickets, key changes, testing steps, or any actual implementation details. Replace template placeholders with actual information: explain what was changed (removal of locale base paths from slugs), link the actual Notion ticket, describe side effects, and provide specific testing instructions.
Docstring Coverage ⚠️ Warning Docstring coverage is 50.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (1 passed)
Check name Status Explanation
Title check ✅ Passed The title 'Fix(integration) zendesk articles' directly relates to the main changes in the PR, which involve refactoring Zendesk article integration to remove locale-based slug handling.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch fix(integration)-zendesk-articles

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
packages/blocks/category/src/api-harmonization/category.mapper.ts (1)

13-58: ⚠️ Potential issue | 🟠 Major

Normalize basePath/slug joins to prevent malformed slugs.

basePath can be empty or already include slashes, causing /slug or //slug. This is a routing/slug-matching risk across category/article pages.

🛠️ Proposed fix (shared join helper)
 export const mapCategory = (
@@
-    const basePath = cms.parent?.slug ?? '';
+    const basePath = cms.parent?.slug?.replace(/^\/+|\/+$/g, '') ?? '';
@@
-                data: articles.data.map((article) => mapArticle(article, cms, _locale, basePath)),
+                data: articles.data.map((article) => mapArticle(article, cms, _locale, basePath)),
             },
         },
     };
 };
@@
 export const mapCategoryArticles = (
@@
-    const basePath = cms.parent?.slug ?? '';
+    const basePath = cms.parent?.slug?.replace(/^\/+|\/+$/g, '') ?? '';
@@
-            data: articles.data.map((article) => mapArticle(article, cms, _locale, basePath)),
+            data: articles.data.map((article) => mapArticle(article, cms, _locale, basePath)),
         },
     };
 };
@@
 const mapArticle = (
@@
-    basePath: string,
+    basePath: string,
 ) => {
     return {
         ...article,
-        slug: `${basePath}/${article.slug}`,
+        slug: basePath ? `${basePath}/${article.slug.replace(/^\/+/, '')}` : article.slug.replace(/^\/+/, ''),
         createdAt: Utils.Date.formatDateRelative(article.createdAt, _locale, cms.labels.today, cms.labels.yesterday),
         updatedAt: Utils.Date.formatDateRelative(article.updatedAt, _locale, cms.labels.today, cms.labels.yesterday),
     };
 };
packages/integrations/zendesk/src/modules/articles/zendesk-article.service.ts (1)

224-259: ⚠️ Potential issue | 🟠 Major

Normalize category slugs before comparison (basePath-aware).

If the UI now passes basePath-prefixed slugs (e.g., help/category-slug), mapCategory(cat).slug === options.id (and resolveCategoryId comparisons) will never match, breaking category pages and filters.

🛠️ Proposed fix (normalize to last path segment)
+    private normalizeSlug(slug: string): string {
+        const segments = slug.split('/').filter(Boolean);
+        return segments[segments.length - 1] ?? slug;
+    }
@@
-        const categoryId = Number(options.id);
+        const normalizedId = this.normalizeSlug(options.id);
+        const categoryId = Number(normalizedId);
@@
-                const category = categories.find((cat) => {
-                    const mapped = mapCategory(cat);
-                    return mapped.slug === options.id || mapped.id === options.id;
-                });
+                const category = categories.find((cat) => {
+                    const mapped = mapCategory(cat);
+                    return mapped.slug === normalizedId || mapped.id === normalizedId;
+                });
@@
-                return mapCategory(category);
+                return mapCategory(category);
             }),
@@
-    private resolveCategoryId(categoryIdOrSlug: string, zendeskLocale: string): Observable<number | undefined> {
+    private resolveCategoryId(categoryIdOrSlug: string, zendeskLocale: string): Observable<number | undefined> {
+        const normalized = this.normalizeSlug(categoryIdOrSlug);
         // If it's already a numeric ID, return it
-        const numericId = Number(categoryIdOrSlug);
+        const numericId = Number(normalized);
         if (!isNaN(numericId)) {
             return of(numericId);
         }
@@
-                    const mapped = mapCategory(category);
-                    if (mapped.slug === categoryIdOrSlug || mapped.id === categoryIdOrSlug) {
+                    const mapped = mapCategory(category);
+                    if (mapped.slug === normalized || mapped.id === normalized) {
                         return category.id;
                     }

Also applies to: 442-455

🤖 Fix all issues with AI agents
In `@apps/api-harmonization/src/modules/page/page.mapper.ts`:
- Around line 118-120: The breadcrumb URL construction using basePath is
creating double slashes when basePath is "/" or has a trailing slash; update the
logic that builds categoryUrl and articleUrl in page.mapper.ts to normalize
basePath first (e.g., compute a normalizedBasePath by removing a trailing slash
unless basePath === "/"), then use `${normalizedBasePath}/${category.slug}` and
`${normalizedBasePath}/${category.slug}/${article.slug}` (or the existing
categoryUrl/articleUrl variables) so URLs never contain duplicate slashes;
ensure normalization is applied wherever basePath is used to build routes.

In `@apps/docs/docs/integrations/articles/zendesk/features.md`:
- Around line 147-172: The two fenced code blocks under "Article slug format:"
and "Category slug format:" in features.md are missing language identifiers,
causing markdownlint MD040; update both fences to include a language (e.g.,
change the three-backtick openings for the article slug and the category slug
blocks to use ```text) so the slug examples like
"{category-id}-{category-name}/{article-id}-{article-title}" and
"{category-id}-{category-name}" are marked as text.

In `@packages/blocks/category-list/src/api-harmonization/category-list.mapper.ts`:
- Around line 10-20: The slug join in the CategoryListBlock mapping can produce
leading or double slashes because basePath (from cms.parent?.slug) may be empty
or end with a slash; update the items mapping in the function that builds the
CategoryListBlock so it sanitizes basePath and category.slug and conditionally
joins them (e.g., trim trailing slash from basePath, trim leading slash from
category.slug, and if basePath is empty return category.slug only) before
assigning slug, ensuring the resulting slug has a single slash separator and no
leading double slashes.
🧹 Nitpick comments (2)
packages/blocks/article-search/src/api-harmonization/article-search.mapper.ts (1)

20-26: Potential URL format inconsistency with other mappers.

When basePath is falsy, the URL becomes just article.slug (e.g., "some-article"). However, in article-list.mapper.ts, the pattern ${basePath}/${article.slug} with empty basePath produces "/some-article" (with leading slash).

Consider aligning the behavior for consistency:

♻️ Optional: Consistent URL handling
 export const mapArticles = (articles: Articles.Model.Articles, basePath?: string): ArticleList => {
     return {
         articles: articles.data.map((article) => ({
             label: article.title,
-            url: basePath ? `${basePath}/${article.slug}` : article.slug,
+            url: `${basePath ?? ''}/${article.slug}`,
         })),
     };
 };
apps/docs/docs/integrations/articles/zendesk/usage.md (1)

276-278: Add language specification to fenced code block.

The code block showing the slug format template should have a language specified for consistency and to satisfy linting rules.

📝 Proposed fix
-```
+```text
 {category-id}-{category-name}/{article-id}-{article-title}

</details>

</blockquote></details>

</blockquote></details>

<!-- This is an auto-generated comment by CodeRabbit for review status -->

Comment thread apps/api-harmonization/src/modules/page/page.mapper.ts Outdated
Comment thread apps/docs/docs/integrations/articles/zendesk/features.md
Comment on lines +10 to +20
const basePath = cms.parent?.slug ?? '';

return {
__typename: 'CategoryListBlock',
id: cms.id,
title: cms.title,
description: cms.description,
items: categories,
items: categories.map((category) => ({
...category,
slug: `${basePath}/${category.slug}`,
})),
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Normalize basePath/slug joins to avoid leading or double slashes.

When cms.parent?.slug is empty or already contains a trailing slash, ${basePath}/${category.slug} yields /slug or //slug, which can break slug matching and routing.

🛠️ Proposed fix (sanitize + conditional join)
-    const basePath = cms.parent?.slug ?? '';
+    const basePath = cms.parent?.slug?.replace(/^\/+|\/+$/g, '') ?? '';
 
     return {
@@
-        items: categories.map((category) => ({
-            ...category,
-            slug: `${basePath}/${category.slug}`,
-        })),
+        items: categories.map((category) => {
+            const categorySlug = category.slug.replace(/^\/+/, '');
+            return {
+                ...category,
+                slug: basePath ? `${basePath}/${categorySlug}` : categorySlug,
+            };
+        }),
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const basePath = cms.parent?.slug ?? '';
return {
__typename: 'CategoryListBlock',
id: cms.id,
title: cms.title,
description: cms.description,
items: categories,
items: categories.map((category) => ({
...category,
slug: `${basePath}/${category.slug}`,
})),
const basePath = cms.parent?.slug?.replace(/^\/+|\/+$/g, '') ?? '';
return {
__typename: 'CategoryListBlock',
id: cms.id,
title: cms.title,
description: cms.description,
items: categories.map((category) => {
const categorySlug = category.slug.replace(/^\/+/, '');
return {
...category,
slug: basePath ? `${basePath}/${categorySlug}` : categorySlug,
};
}),
🤖 Prompt for AI Agents
In `@packages/blocks/category-list/src/api-harmonization/category-list.mapper.ts`
around lines 10 - 20, The slug join in the CategoryListBlock mapping can produce
leading or double slashes because basePath (from cms.parent?.slug) may be empty
or end with a slash; update the items mapping in the function that builds the
CategoryListBlock so it sanitizes basePath and category.slug and conditionally
joins them (e.g., trim trailing slash from basePath, trim leading slash from
category.slug, and if basePath is empty return category.slug only) before
assigning slug, ensuring the resulting slug has a single slash separator and no
leading double slashes.

@vercel
Copy link
Copy Markdown

vercel Bot commented Feb 5, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

1 Skipped Deployment
Project Deployment Actions Updated (UTC)
o2s-docs Skipped Skipped Feb 5, 2026 9:38am

Request Review

@vercel vercel Bot temporarily deployed to Preview – o2s-docs February 5, 2026 09:38 Inactive
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Feb 5, 2026

Coverage Report for packages/configs/vitest-config

Status Category Percentage Covered / Total
🔵 Lines 82.26% 700 / 851
🔵 Statements 82.15% 732 / 891
🔵 Functions 78.46% 255 / 325
🔵 Branches 72.97% 602 / 825
File Coverage
File Stmts Branches Functions Lines Uncovered Lines
Changed Files
apps/api-harmonization/src/modules/page/page.mapper.ts 63.88% 36.36% 60% 60.6% 92-99, 150-176
apps/api-harmonization/src/modules/page/page.service.ts 75.51% 70% 70% 77.77% 26-39, 124
packages/blocks/article-list/src/api-harmonization/article-list.mapper.ts 100% 100% 100% 100%
packages/blocks/category/src/api-harmonization/category.mapper.ts 100% 100% 100% 100%
Generated in workflow #217 for commit f3dda28 by the Vitest Coverage Report Action

@michnowak michnowak merged commit 8702f91 into main Feb 5, 2026
13 checks passed
@michnowak michnowak deleted the fix(integration)-zendesk-articles branch February 5, 2026 12:10
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants