Skip to content

[Remove Vuetify from Studio] Add StudioContentNodeIcon to channel details Total resources (#5933) - #6379

Open
vtushar06 wants to merge 1 commit into
learningequality:unstablefrom
vtushar06:remove-vuetify-5933
Open

vtushar06 wants to merge 1 commit into
learningequality:unstablefrom
vtushar06:remove-vuetify-5933

Conversation

@vtushar06

@vtushar06 vtushar06 commented Nov 3, 2026 •

Copy link
Copy Markdown
Contributor

Summary

Removes the Vuetify dependency from the content kind icons in the channel details modal (Total resources section) by adding a Vuetify-free StudioContentNodeIcon, as a parallel to ContentNodeIcon.

Changes:

  • Added getContentKindColor in shared/utils/colors.js, mapping content kinds to KDS theme colors (tokens.watch / listen / read / practice / explore, and palette.grey.v_400 for folders and unknown kinds)
  • Added StudioContentNodeIcon (shared/views/StudioContentNodeIcon.vue), built on KIcon + getContentKindIcon from shared/utils/icons.js. Keeps capture-as-image so the PDF channel summary still rasterises the icons
  • Swapped ContentNodeIcon → StudioContentNodeIcon in StudioDetailsPanel Total resources only
  • ContentNodeIcon and shared/vuetify/theme.js are untouched; no other areas refactored

Notes / open questions:

  • shared/utils/icons.js has no h5p (or unsupported) mapping and throws for them, so StudioContentNodeIcon renders nothing for unmapped kinds instead of breaking the modal. Happy to map h5p → html5 if preferred
  • Only the kind and isEmpty props are carried over; includeText, showColor, fillWidth and small aren't used in the details panel so I left them out to keep scope tight. Can add them if wanted for future sub-issues

Screenshots:
Published Channel, dev server, [email protected]. Background colours match on both sides (exercise #6986f7, audio #ff7f8d, document #ff4324, HTML5 #ff7600, video #33acf5). The after chips use KDS icons at a 4px radius instead of Vuetify Material chips at 2px; the kinds, labels, and counts are the same. The clipped Arabic PDF layout is already present on unstable.

Before (unstable) After (remove-vuetify-5933)
Total resources, LTR Total resources on unstable, LTR Total resources after StudioContentNodeIcon, LTR
Channel summary PDF, LTR PDF summary on unstable, LTR PDF summary after StudioContentNodeIcon, LTR
Total resources, Arabic RTL Total resources on unstable, Arabic RTL Total resources after StudioContentNodeIcon, Arabic RTL
Channel summary PDF, Arabic RTL PDF summary on unstable, Arabic RTL PDF summary after StudioContentNodeIcon, Arabic RTL

References

Closes #5933
Sub-issue of #5060

Reviewer guidance

  • Run pnpm test colors StudioContentNodeIcon StudioDetailsPanel — 30 tests pass
  • Login as [email protected] / a → Channels > My Channels → info icon on the Published Channel card → check the Total resources icons
  • Download channel summary > Download PDF → icons should still appear in the PDF

AI usage

I used an AI assistant to help draft the helper, component and tests, following the existing ContentNodeIcon / StudioDetailsPanel patterns and the issue's scope. I reviewed the generated code, kept the change limited to the files in the issue, and ran the tests and linting locally.

@vtushar06
vtushar06 requested review from a team and leq-bot November 3, 2026 05:43
@learning-equality-bot

Copy link
Copy Markdown
Contributor

👋 Hi @vtushar06, thanks for contributing!

For the review process to begin, please verify that the following is satisfied:

  • Contribution is aligned with our contributing guidelines

  • Pull request description has correctly filled AI usage section & follows our AI guidance:

    AI guidance

    State explicitly whether you didn't use or used AI & how.

    If you used it, ensure that the PR is aligned with Using AI as well as our DEEP framework. DEEP asks you:

    • Disclose — Be open about when you've used AI for support.
    • Engage critically — Question what is generated. Review code for correctness and unnecessary complexity.
    • Edit — Review and refine AI output. Remove unnecessary code and verify it still works after your edits.
    • Process sharing — Explain how you used the AI so others can learn.

    Examples of good disclosures:

    "I used Claude Code to implement the component, prompting it to follow the pattern in ComponentX. I reviewed the generated code, removed unnecessary error handling, and verified the tests pass."

    "I brainstormed the approach with Gemini, then had it write failing tests for the feature. After reviewing the tests, I used Claude Code to generate the implementation. I refactored the output to reduce verbosity and ran the full test suite."

📢✨ Before we assign a reviewer:

  • @rtibblesbot will pre-review this pull request. Its comments are generated by an LLM, and should be evaluated accordingly.
  • We'll also invite community pre-review. See the community review guidance for both authors and reviewers.

Also check that issue requirements are satisfied & you ran pre-commit locally.

Pull requests that don't follow the guidelines will be closed.

Reviewer assignment can take up to 2 weeks.

@rtibblesbot

rtibblesbot commented Nov 3, 2026 •

Copy link
Copy Markdown
Contributor

🟡 Waiting for changes

Outcome: reviewed 7221562

Last updated: 2026-11-03 05:53 UTC

@rtibblesbot rtibblesbot left a comment

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.

PR #6379: H5P rows lose their icon, and the PR has no screenshots. The component and color helper otherwise follow the spec.

CI passing. Tests not run locally. Manual QA did not run.

  • blocking: H5P rows render without an icon (inline).
  • blocking: Screenshots are missing, and the AC requires them. The issue also asks for a PDF export check. Add before/after screenshots of the modal and the generated PDF, in LTR and RTL.
  • suggestion: Chip size may differ from base (inline).
  • suggestion: Tests would still pass if the swap regressed (inline).
  • nitpick: Docstring restates the code (inline).

Next step: Needs a full code review by a human engineer, then manual QA once that reviewer sets Needs QA.

  • The author is outside the team: confirm this should be built at all.
  • User-visible files changed: contentcuration/contentcuration/frontend/shared/utils/colors.js, contentcuration/contentcuration/frontend/shared/views/StudioContentNodeIcon.vue, contentcuration/contentcuration/frontend/shared/views/details/StudioDetailsPanel.vue.
  • Choose the H5P icon; the issue left it open.
  • Compare the modal chips and PDF export against base in LTR and RTL.

Written by rtibblesbot, an LLM-based coding agent.

icon() {
try {
return getContentKindIcon(this.kind, this.isEmpty);
} catch (e) {

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.

blocking: H5P rows lose their icon, and this catch hides it.

  • shared/utils/icons.js has no h5p entry, so the lookup throws.
  • This catch returns null, so the H5P row in Total resources shows a label with no icon.
  • Base falls back to 'error_outline' (shared/vuetify/icons.js:28).
  • The AC rules out visual changes beyond the listed ones.
  • The H5P entry in getContentKindColor is dead code as a result.

Give h5p an icon, then drop the catch so a missing mapping fails loudly. html5 fits, since the label already says "HTML5 App".

:style="{ backgroundColor: backgroundColor }"
capture-as-image
>
<KIcon

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.

suggestion: This chip's size likely differs from base. Base is a Vuetify small chip with 22px content height and 0 5px padding. Here KIcon uses its default size with 2px 5px padding. Set an explicit size, or show in screenshots that it matches.

},
loading: false,
});
expect(screen.getByText('Video')).toBeInTheDocument();

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.

suggestion: This test doesn't cover the icon swap: it passes unchanged on base. '30'/'12' can also match any text on the page. Scope each row with within(...), assert the icon renders, and add an h5p row.

'renders an icon for %s',
kind => {
const { container } = renderComponent({ kind });
expect(container.querySelector('svg')).toBeInTheDocument();

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.

suggestion: This test can't catch a wrong icon or background: it only checks that an svg exists. Assert the background from getContentKindColor and something icon-specific per kind. Add h5p to the list.

import { ContentKindsNames } from 'shared/leUtils/ContentKinds';

/**
* Returns the KDS background color for a content node kind.

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.

nitpick: This docstring restates the code. The summary repeats the function name. The fallback line repeats line 25. @param/@returns add nothing the keys on lines 15–23 don't show. Delete lines 4–10.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Remove Vuetify from Studio] Create StudioContentNodeIcon and use it channel details modal

2 participants