Ae glossary domain color picker#17838
Conversation
Introduce a modern color picker (Alchemy ColorPicker) for domains, glossary nodes, and glossary terms. Users can now choose a color when creating an entity and edit it later from the entity header. The picker shows the entity's saved color (or the deterministic palette color) so editing reflects current state. Frontend - Replace legacy color picker with Alchemy ColorPicker in IconColorPicker, CreateDomainModal, and CreateGlossaryEntityModal (V1 + V2). - Migrate easy antd usages to Alchemy (toast, Button, Input, Text, Modal) and replace antd icons with Phosphor (PencilSimple, SquaresFour, FileText, ListBullets, Columns, ArrowLineLeft/Right, CaretDown/Right, BookmarkSimple, BookmarksSimple). - DefaultEntityHeader: render DomainColoredIcon/GlossaryColoredIcon, use BookmarkSimple for terms and BookmarksSimple for nodes, prioritize displayProperties.colorHex with palette fallback, remove yellow ribbon. - Guard against persisting the default color when the user did not explicitly pick one (colorWasPicked flag in create modals). - Propagate term displayProperties through GlossaryEntitiesList / GlossaryEntityItem / GlossaryListCard, and prioritize own colorHex over inherited iconColor in NodeItem / TermItem. - Make GlossarySidebar collapsible (mirrors domain sidebar): grouped header actions, animated width, colored entity icons rendered when collapsed. - Set theme colorPickerDefault to violet500 (#533FD1). - Fix React hooks order violation in EntityPage by hoisting renderProfile outside the conditional branch. GraphQL - Add displayProperties to GlossaryTerm in entity.graphql. - Add displayProperties to childGlossaryTerm fragment, nested GlossaryNode layers in rootGlossaryNodeWithFourLayers, and GlossaryTerm in searchResultsWithoutSchemaField so sidebar/list views fetch color data. - Query displayProperties in getGlossaryTerm. Backend - entity-registry.yml: add displayProperties as a valid aspect on glossaryTerm. - GlossaryNodeType / GlossaryTermType: include DISPLAY_PROPERTIES_ASPECT_NAME in ASPECTS_TO_RESOLVE so GMS hydrates/persists displayProperties. - GlossaryTermMapper: map displayProperties onto GlossaryTerm. - UpdateDisplayPropertiesResolver: entity-aware authorization (canManageGlossaries for glossary terms/nodes, canManageDomains otherwise); fix SLF4J placeholder bug in error messages. - GmsGraphQLEngine: pass EntityClient to UpdateDisplayPropertiesResolver. Co-authored-by: Cursor <cursoragent@cursor.com>
- Rewrite NodeParentSelect on top of alchemy SimpleSelect with browse + search through useGlossaryTreeEntities; V1 re-exports V2 for a single source of truth - Default the color picker in the create modal to the selected parent's color, but lock to the user's choice once they pick one - Inline the documentation rich-text editor in the create modal instead of the modal-in-modal pattern; make parent selection optional - Route glossary term colors through getGlossaryTermColor everywhere (own colorHex -> root parent's -> palette of parent URN -> palette of term URN), fixing the sidebar/header color mismatch on term profile pages - Always render glossary nodes with BookmarksSimple (nested nodes were falling back to the term icon) - Query displayProperties on terms in autoComplete/facet/sidebar fragments so the inheritance chain has data to walk - Add i18n keys for color/icon/optional, the parent search placeholder, and the glossary sidebar expand/collapse tooltips Co-authored-by: Cursor <cursoragent@cursor.com>
…roll Aligns recent glossary/color-picker work to Chris Collins' conventions (toast + i18n error handling, no React.FC, testable helpers in sibling .ts files) and fixes a pre-existing sidebar layout bug. - IconColorPicker: drop React.FC for a function declaration, i18n the modal title and all toast strings, type catch as (e: unknown), and remove console.error noise (match EntityName.tsx). - CreateGlossaryEntityModal (V1 + V2): i18n the name-length validation string under the matching createModal/createGlossary namespaces. - NodeParentSelect: switch to styled-components/macro and extract filterResultsForMove into a sibling utils file so the .tsx exports only its component (fixes a react-refresh warning, follows Chris's pattern for test-exposed pure helpers). - GlossarySidebar: document why collapsed root-level items skip the full getGlossaryTermColor inheritance chain. - GlossaryBrowser: fix horizontal scrollbar caused by StyledDivider's width: calc(100% + 26px + depth*18px) / margin-left: calc(-13px - depth*18px) formula overshooting its container by 13px on the right. Replace with width: 100% and clamp BrowserWrapper to overflow-y only. Co-authored-by: Cursor <cursoragent@cursor.com>
Resolved conflicts from #17782 (i18n V1 entity dropdown keys deduplication): - entityV1.shared.entityDropdown.json: accept deletion (master removed the V1 namespace; our `createModal.nameMaxLengthError` migrated to `createGlossary.nameMaxLengthError` which the auto-merged V2 file already preserves). - entity/shared/EntityDropdown/CreateGlossaryEntityModal.tsx: keep our Alchemy rewrite (toast, ColorPicker, inline Editor, alchemy Modal/ Input/Text) and rename remaining `createModal.*` keys to the deduped `createGlossary.*` equivalents (including param rename `message` -> `errorMessage` on createGlossary.error). Co-authored-by: Cursor <cursoragent@cursor.com>
PR Title Check FailedYour PR title must follow the format: Examples:
See the Contributing Guide for allowed types and format details. |
❌ 4 Tests Failed:
View the top 3 failed test(s) by shortest run time
To view more test analytics, go to the Test Analytics Dashboard |
|
🔴 Meticulous spotted visual differences in 306 of 1304 screens tested: view and approve differences detected. Meticulous evaluated ~10 hours of user flows against your PR. Last updated for commit |
Bundle ReportChanges will increase total bundle size by 12.77kB (0.05%) ⬆️. This is within the configured threshold ✅ Detailed changes
Affected Assets, Files, and Routes:view changes for bundle: datahub-react-web-esmAssets Changed:
Files in
|
…r defaults - Add GlossaryEntityIcon wrapper that resolves color via the same chain the sidebar uses (own colorHex -> root parent -> deterministic palette) and pairs with the correct Phosphor icon by entity type. - Wire it through DefaultEntityIcon and SingleEntityIcon so autocomplete, home V3 modules, hierarchy tree, related terms, and entity filters render the same colored bookmark as the glossary sidebar. - Replace the diagonal ribbon decoration on glossary preview cards and home V2 entity links with the colored bookmark; delete the now-unused GlossaryPreviewCardDecoration component. - Default the create-modal color picker to the first palette swatch (violet600 / #533FD1) instead of the unrelated violet500 (#705EE4). - Fall through to the deterministic palette color when the selected parent has no explicit displayProperties.colorHex, so the picker pre-fills with the color the user actually sees on the parent. - Carry the picked color into the optimistic sidebar cache entry so newly created glossary nodes render with the right color from the first paint instead of flickering through the inherited parent color until the search refetch catches up. Co-authored-by: Cursor <cursoragent@cursor.com>
The sidebar create button only opened the term-group modal, which hid the ability to create root-level terms even though DataHub supports them. Wrap it in an Alchemy `Menu` that offers both options, using the same Phosphor icons the sidebar already uses to render each entity type (BookmarksSimple for groups, BookmarkSimple for terms). Reuses the existing `empty.addTerm` and `empty.addTermGroup` i18n keys. Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
GlossaryEntityItem was passing the useEntityData() wrapper (urn, entityType, entityData, loading) into GlossaryListCard's entityData prop, which expects the inner GenericEntityProperties. Color resolution therefore silently missed the parent's colorHex and fell through to a palette color derived from the child's URN, so children on the Contents tab disagreed with the sidebar and header. Destructure the inner entity at the caller and mirror the sidebar's cascade in GlossaryListCard: child colorHex > parent colorHex > palette(parentUrn || childUrn). Applies to both child terms and child nodes. Co-authored-by: Cursor <cursoragent@cursor.com>
After this PR moved the glossary modal toasts to alchemy `toast.*` and the
edit icon to phosphor `<PencilSimple>`, several Cypress and Playwright
helpers were still keyed off antd-era selectors.
- Playwright `ToastComponent`: match both `.ant-message` (antd `message.*`)
and the new alchemy toast container so glossary toast assertions pass
while the rest of the codebase finishes migrating away from antd.
- Alchemy `ToastContainer`: add `data-testid="toast-notification-container"`
as the stable hook the playwright helper looks for.
- Playwright domain `editDomainName`: assert on `aria-label` instead of
visible text — header chrome added by the color icon now causes the
name to ellipsize.
- Cypress `v2_glossary.js`: replace the `.ant-input-affix-wrapper` modal
driver (no longer present after the alchemy `<Input>` migration) with
the same `data-testid` pattern used by the other glossary specs.
- Cypress `v2_glossary{,Term,_navigation}.js`: swap `.anticon-edit` for
`.ant-typography-edit` — the inline-edit pencil icon was replaced but
the antd Typography editable wrapper class is stable.
- Cypress `clickOptionWithText`: filter to `:visible` matches first so a
link inside a hidden tab pane doesn't win the lookup and fail visibility.
Co-authored-by: Cursor <cursoragent@cursor.com>
…' into ae--glossary-domain-color-picker
Summary
Adds a modern color picker to domains and glossary entities (terms + nodes), modernizes the create/edit modals onto Alchemy, makes the glossary sidebar collapsible, and tightens the color-inheritance behavior so the icon you see on a term matches the icon on its profile header everywhere it appears.
What's changing
User-facing
ColorPicker). The default picker color isviolet500(#533FD1).GlossaryColoredIconconsumers.colorWasPickedflag) and won't shift if they change the parent.NodeParentSelectis rewritten on top of AlchemySimpleSelectwith tree-style browse + search (powered byuseGlossaryTreeEntities); V1 re-exports V2 so there's one source of truth.StyledDivider'swidth: calc(100% + 26px + depth*18px)paired withmargin-left: calc(-13px - depth*18px)overshot the sidebar by 13px on the right.Frontend (technical)
toast,Button,Input,Text,Modal,ColorPicker,SimpleSelect,Editor,Loader) and Phosphor icons (PencilSimple,BookmarkSimple,BookmarksSimple,CaretDown/Right,ArrowLineLeft/Right, etc.).DefaultEntityHeaderrendersDomainColoredIcon/GlossaryColoredIcon, prioritizesdisplayProperties.colorHexwith a palette fallback, and removes the legacy yellow ribbon.displayPropertiesthroughGlossaryEntitiesList/GlossaryEntityItem/GlossaryListCard, and prioritize owncolorHexover inheritediconColorinNodeItem/TermItem.BookmarksSimple(nested nodes were falling back to the term icon).colorWasPickedflag in create modals avoids persisting the gray placeholder default and overriding the deterministic palette color.getGlossaryTermColor,buildTermTreeOptions,filterResultsForMove) extracted into.tsfiles for direct unit testing.EntityPageby hoistingrenderProfileoutside the conditional branch.GraphQL
displayPropertiestoGlossaryTerminentity.graphql.displayPropertiestochildGlossaryTermfragment, nested layers inrootGlossaryNodeWithFourLayers, andGlossaryTerm/GlossaryNodeinsearchResultsWithoutSchemaFieldso sidebar / list / autocomplete views fetch color data.displayPropertiesingetGlossaryTerm.Backend
entity-registry.yml: adddisplayPropertiesas a valid aspect onglossaryTerm.GlossaryNodeType/GlossaryTermType: includeDISPLAY_PROPERTIES_ASPECT_NAMEinASPECTS_TO_RESOLVEso GMS hydrates/persistsdisplayProperties.GlossaryTermMapper: mapdisplayPropertiesontoGlossaryTerm.UpdateDisplayPropertiesResolver: entity-aware authorization (canManageGlossariesfor glossary terms/nodes,canManageDomainsotherwise); fix SLF4J placeholder bug in error messages.GmsGraphQLEngine: passEntityClienttoUpdateDisplayPropertiesResolver.Tests
getGlossaryTermColorprecedence rules (colorUtils.test.ts).useTermTreeOptionscolor inheritance (useTermTreeOptions.test.tsx).filterResultsForMovemove-mode filtering (NodeParentSelect.test.tsx).yarn type-check,yarn eslint --quiet, and the affected vitest suites (43/43) all pass.Checklist
docs/how/updating-datahub.md(not breaking — new aspect field is additive)