Skip to content

Add defaultStyling.json support for persistent per-type vertex and ed…#1

Open
jkemmererupgrade wants to merge 91 commits into
mainfrom
feature/default-styling-1265
Open

Add defaultStyling.json support for persistent per-type vertex and ed…#1
jkemmererupgrade wants to merge 91 commits into
mainfrom
feature/default-styling-1265

Conversation

@jkemmererupgrade
Copy link
Copy Markdown
Owner

@jkemmererupgrade jkemmererupgrade commented Mar 10, 2026

Description

Add support for a defaultStyling.json file that provides persistent per-type vertex and edge styling defaults. When mounted into the Docker container, the file's values are merged into the user styling
store on startup, giving teams a consistent visual baseline across non-persistent browser sessions (e.g., AWS WorkSpaces Web).

Key capabilities:

  • Docker mount: Place a defaultStyling.json at the configuration folder path to auto-apply styling on load
  • Lucide icon support: Reference icons by name (e.g., "icon": "user") — resolved to SVG data URIs at runtime
  • Import / Export / Reset UI: New controls in Settings to import a styling file, export current styling, and reset all styling to defaults
  • Per-type Reset to Default: Each node/edge type's style dialog has a "Reset to Default" button that restores the mounted file's values
  • Zod validation: Strict schema validation with clear error logging for malformed files

Validation

  • All 1365 tests pass (pnpm test)
  • pnpm checks passes (lint, format, types)
  • Docker tested with mounted defaultStyling.json — styling applied on startup, import/export/reset all functional
  • Incognito window testing confirmed clean-state behavior
  • New unit tests cover: Zod parsing, icon resolution, import/export hooks, merge logic, configuration integration
Screenshot 2026-03-10 at 2 09 40 PM Screenshot 2026-03-10 at 2 04 31 PM

Related Issues

Addresses aws#1265, aws#112, aws#173, aws#573, aws#689

Check List

  • I confirm that my contribution is made under the terms of the Apache 2.0 license.
  • I have run pnpm checks to ensure code compiles and meets standards.
  • I have run pnpm test to check if all tests are passing.
  • I have covered new added functionality with unit tests if necessary.
  • I have added an entry in the Changelog.md.

…#1573)

Move permissions to the workflow level with contents: read for all three
workflows. This follows the principle of least privilege and ensures any
future jobs inherit the restricted token by default.

- unit.yml: Add permissions (was missing entirely)
- build_docker.yml: Move from job level to workflow level
- test_build_docker.yml: Move from job level to workflow level
@jkemmererupgrade jkemmererupgrade force-pushed the feature/default-styling-1265 branch from 4ffcde2 to 44da021 Compare March 10, 2026 20:02
* Update all dependencies

* Remove overrides that are no longer necessary
* Move ECS Fargate docs

* Move Sagemaker docs

* Move troubleshooting to guides

* Move connections to individual guides

* Table of contents and update links
* Move minimum requirements to refs

* Move HTTPS to refs

* Move health check to refs

* Move logging to refs

* Move permissions to refs

* Move default connections to refs

* Move security to refs

* Add summary

* Fix broken links

* Update title

* Combine security, https, and permissions to one file
Copy link
Copy Markdown

@mmedeirosupgrade mmedeirosupgrade left a comment

Choose a reason for hiding this comment

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

LGTM!

…ge styling

Adds an optional defaultStyling.json file that can be mounted into the
Docker container to provide per-type vertex and edge styling defaults.
This addresses the need for persistent styling in environments where
browser storage is cleared between sessions (e.g., AWS WorkSpaces Web).

On startup, file values are merged into the user's per-type styling
preferences (IndexedDB). Default values fill in properties the user
hasn't explicitly set; existing user overrides are preserved. The file
also serves as a reference for per-type "Reset to Default" in the
Node/Edge Style dialogs.

The Settings page adds Export/Import/Reset All styling controls:
- Export: saves current styling as defaultStyling.json for sharing or
  Docker-mounting as team defaults
- Import: merges a defaultStyling.json into user styling and updates
  the reset reference so reset-after-import restores imported values
- Reset All: reverts all styling to defaults (from file or hardcoded)

Supports lucide icon names (resolved to SVG data URIs at runtime via
dynamic imports), custom icon URLs, colors, shapes, border styles, edge
line styles, and arrow styles. Includes Zod validation with strict type
checking for shapes and arrow styles.

Includes 58 new tests with 100% line coverage on new modules, example
file, and documentation.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@jkemmererupgrade jkemmererupgrade force-pushed the feature/default-styling-1265 branch from 44da021 to 89910a2 Compare March 12, 2026 14:33
jkemmererupgrade and others added 19 commits March 12, 2026 10:08
Adds a searchable icon browser popover alongside the existing Upload
button in the node style dialog. Users can browse ~1,900 Lucide icons
with search filtering, capped at 50 visible results for performance.
Icons are lazy-loaded using the existing lucideIconToDataUri helper.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add Lucide icon picker to node styling dialog
* Update github skill

* Disable blank issues

* Update issue templates
… config directory (aws#1598)

* fix: use CONFIGURATION_FOLDER_PATH in docker-entrypoint.sh for custom config

* clean up entrypoint grep path

---------

Co-authored-by: Neel Shah <neeljs@amazon.com>
- Bump @aws-sdk/credential-providers from ^3.1005.0 to ^3.1015.0
- Replace fast-xml-parser override with flatted override for eslint chain
* Remove leftover corepack cache from Docker image

* Add Trivy vulnerability scan to Docker test build
schemaSyncQuery now accepts an options object with a hasConnection flag
that gates the enabled option. When no active connection is configured,
both schema discovery and edge connection queries stay idle, preventing
unnecessary network calls.
…e' (aws#1611)

When no connections are configured, views now show a 'No Connection' empty
state with a link to the Connections page instead of 'No Schema Available'.
The Connections page shows an empty state with add/import buttons instead
of auto-opening the create dialog. Dialog state is now owned by
AvailableConnections using Radix DialogTrigger.
* Add tests for process-environment.sh

* Use proper posix compliant printf

* Verify custom config path by checking file existence at both paths
* Extract createApp from node-server.ts with comprehensive tests

* Extract createServer for testable HTTP/HTTPS decision

* Extract resolveServerConfig with buildBaseUrl and tests
- Move cert generation and validation from docker-entrypoint.sh to setup-ssl.sh
- Accept CERT_DIR and HOST as environment variables
- Use absolute paths with CERT_DIR instead of cd + relative paths
- Use portable sed pattern matching instead of hardcoded line numbers
- Preserve existing behavior including known bugs (duplicate rootCA.crt check)
- Add 7 tests documenting current behavior including bug test case
kmcginnes and others added 30 commits April 23, 2026 17:02
Add a toggle in General Settings that enables verbose console logging
at runtime, even in production builds. The setting is persisted to
IndexedDB and synced to the logger utility via a React effect.

Resolves aws#1705
- Add coverage thresholds to root vitest config based on current levels
- Enable autoUpdate to ratchet thresholds up as coverage improves
- Remove broken Codecov upload step from CI workflow
- Remove unused coverage reporters and reportsDirectory defaults
- Update AGENTS.md to use pnpm coverage instead of pnpm test

Fixes aws#1704
* Switch proxy server imports to .ts extensions

Change all local imports from .js to .ts extensions in the proxy
server package. Add rewriteRelativeImportExtensions to tsconfig.base
so tsc --build rewrites them back to .js in output. Add
erasableSyntaxOnly to the proxy server tsconfig to prevent future
use of non-erasable TypeScript syntax.

These changes prepare for running .ts files directly with Node's
native type stripping.

* Run proxy server .ts files directly with Node

Remove tsx and rimraf dependencies, the build script, and
tsconfig.build.json. Update dev script to use node --watch and start
script to run src/node-server.ts directly using Node's native type
stripping. Update docker-entrypoint.sh to match.

* Add container health check to Docker CI workflow

Start the container and poll GET /status to verify the server is
running and responding inside the Docker image.

* Move erasableSyntaxOnly to base tsconfig

Replace angle-bracket type assertions with as-assertions in the
frontend and convert the TableId enum to a const object. This
allows erasableSyntaxOnly to be enforced across all packages.

* Polish: trap container cleanup, remove unnecessary cast

* Replace rewriteRelativeImportExtensions with allowImportingTsExtensions

rewriteRelativeImportExtensions is only needed when tsc emits .js
files. Since the build step was removed, use allowImportingTsExtensions
directly to permit .ts import paths with noEmit.

* Scope allowImportingTsExtensions to proxy server, remove main field

Move allowImportingTsExtensions from the base tsconfig to the proxy
server tsconfig to prevent the frontend from adopting .ts import
extensions unintentionally. Remove the unused main field from the
proxy server package.json since it is a standalone server, not an
importable package.
* Speed up test suite by removing vi.resetModules() and using thread pool

- Remove vi.resetModules() from setupTests beforeEach which was invalidating
  the module cache before every test, forcing 1618 re-imports
- Simplify mock cleanup to just vi.clearAllMocks()
- Move Intl stub into beforeEach so it survives vi.unstubAllGlobals()
- Switch both packages to pool: threads for lower startup overhead
- Set TZ=UTC at process level for reliable timezone in worker threads

Reduces total test duration from ~120s to ~70s (42% faster).

* Remove core-js iterator polyfill from test setup

Node 24 has native iterator helpers, so the polyfill is unnecessary
in the test environment. Keeps the polyfill in index.tsx for browser
compatibility.

* Default test environment to node, move mock config to vitest config

- Change default environment from happy-dom to node (vitest default)
- Add // @vitest-environment happy-dom to 43 test files that need DOM
- Move clearMocks, restoreMocks, unstubEnvs, unstubGlobals to vitest config
- Remove redundant cleanup from setupTests.ts beforeEach/afterEach
- Add vi.resetModules() to logger.test.ts for vi.doMock support
- Move TZ=UTC to globalSetup so it runs before worker threads spawn

* Add resetMocks to config and document vi.doMock pattern

- Add resetMocks: true to vitest config for full mock isolation
- Document vi.resetModules() requirement for vi.doMock in testing SKILL.md

* Add tests for uncovered logic and adjust coverage thresholds

- Add tests for emptyExplorer, LoggerConnector, fileData, featureFlags,
  normalizeConnection, and getDefault type config functions
- Lower coverage thresholds to match the new measurement baseline after
  switching default test environment from happy-dom to node (v8 coverage
  instruments differently across environments)
* Create consolidated configuration reference

* Fix heading levels, typos, and grammar in docs
- Resolved Changelog.md conflict: kept Unreleased section above new Release 3.0.2
- Resolved docs/references/README.md conflict: kept Default Connection and Default Styling links
- Resolved SettingsGeneral.tsx conflict: kept both defaultStylingAtom and diagnosticLoggingAtom imports
- Added @vitest-environment happy-dom to PR test files that use browser globals
- Added eslint-disable comments for react-hooks/set-state-in-effect in useInitCytoscape.tsx
  and Tabular.tsx (pre-existing intentional patterns, flagged by react-hooks v7)
- All 1709 tests pass, TypeScript checks clean

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* Add feature highlights to the features page

* Clarify proxy server role as SigV4 signing, not authentication

* Consolidate feature highlights and add Save & Load Graph

* Remove incorrect styling persistence claim
* Restructure getting-started page into a hands-on tutorial

* Replace repositioning tip with more useful canvas interactions

* Clarify double-click expansion behavior and neighbor count badge

* Move Table View into its own section near Entities Filter

* Fix landing page claim, sidebar order, and README description

* Fix prettier-ignore, pre-selected dropdown, and toolbar location

* Add features link to next steps and update docs index description

* Remove incorrect landing page reference from Connections description

* Details panel auto-opens on selection by default

* Use consistent Filters terminology

* Lead Style Nodes with display name and description before color
* Rewrite schema merge for referential equality

* Return discovered IRIs from merge functions to simplify mergePrefixes

* Hoist attributesFromProperties, narrow newIris to only new attrs, add no-churn test, use Object.keys
* docs: add architecture section and fix documentation inaccuracies (aws#1159)

- Add Architecture section to development.md covering system overview
  with Mermaid diagram, monorepo structure, key libraries with rationale,
  and the connector/explorer pattern
- Fix incorrect Build for Production section that claimed two dist folders
  (proxy server has no build step since migrating to native type stripping)
- Fix dangling 'See below' reference in deploy-with-docker.md, now links
  to the connections feature page

* Split architecture into its own documentation page
…v mode (aws#1738)

Change the CORS default from origin:true (allow all) to origin:false
(block cross-origin). The proxy server serves both the API and UI from
the same origin in all production deployments, so CORS is unnecessary.

Expand the Vite dev proxy to forward all API routes to the Express
server, keeping dev mode same-origin so the secure default works
everywhere without extra configuration.
* Break circular dependency in storageAtoms barrel import

storageAtoms.ts imported defaultUserLayout from ./index, which triggered
loading all barrel re-exports. Several of those modules import storage
atoms back through @/core, creating a circular dependency. Because
storageAtoms uses top-level await, the atoms were undefined when the
circular modules evaluated.

Replace the barrel import with direct imports from source modules.
Type-only imports go to their source files; the sole runtime import
(defaultUserLayout) goes directly to ./userLayout.

Fixes 6 flaky test failures in userLayout.test.ts that depended on
module loading order.

* Extract userLayoutDefaults and add storageAtoms tests

Move types and default values from userLayout.ts into a new
userLayoutDefaults.ts to fully decouple storageAtoms from userLayout.
This eliminates the remaining mutual dependency between the two modules.

Add tests for storageAtoms that verify all atoms are defined, have
correct default values, and support write/read roundtrips.

Also fix pre-existing issues in userLayout.ts caught during review:
- Use ?? instead of || for tableView height (0 is a valid height)
- Remove unnecessary || {} guard when spreading tableView
- Fix typo in JSDoc (with -> width)
- Export UserLayout type from userLayoutDefaults
- Remove redundant re-export block from userLayout.ts
* Update air routes sample to TinkerPop 3.8.1

Pin Gremlin Server to 3.8.1 and use TinkerFactory.createAirRoutes()
instead of loading a bundled GraphML file. This uses the full air
routes dataset (3,619 vertices, 50,148 edges) built into TinkerPop
3.8 and removes the small subset GraphML file from the repo.

Closes aws#1734

* Removed node and edge counts

* Use 3.8 minor tag instead of pinning to 3.8.1
…#1744)

- Add vertexPreferencesAtom and edgePreferencesAtom with .get(type)
  accessor that returns resolved preferences via O(1) Map lookup
- Simplify vertexPreferenceByTypeAtom/edgePreferenceByTypeAtom to
  delegate to the new Map atoms
- Simplify useAllVertexPreferences/useAllEdgePreferences by removing
  intermediate useStoredGraphPreferences wrapper
- Pre-index vertex, edge, and preference arrays into Maps in
  mergeConfiguration, converting O(n²) .find() calls to O(1) lookups
- Convert mergeAttributes to use Map-based lookups
- Replace lodash cloneDeep with destructuring spread in
  patchToRemoveDisplayLabel, avoiding 70k deep clones
- Replace lodash uniq() with native Set for deduplication
- Fix circular import in storageAtoms.ts
- Add tests for new atoms and patchToRemoveDisplayLabel immutability

Part of aws#1678
- Replace prettier and prettier-plugin-tailwindcss with oxfmt
- Add .oxfmtrc.jsonc matching existing Prettier config (printWidth: 80,
  arrowParens: avoid, Tailwind class sorting for cva/cn)
- Delete .prettierrc and .prettierignore (ignore patterns moved to config)
- Update format/check:format scripts to use oxfmt
- Update lint-staged in root and packages/graph-explorer
- Update VS Code and Zed editor configs for oxfmt
- Update AGENTS.md with parameterized format/lint examples
- Remove stale prettier-ignore comments from markdown files
- Fix broken blockquote syntax in deploy-to-ec2.md

Zero source code formatting changes. Package.json key reordering is from
oxfmt's built-in sortPackageJson (enabled by default).

Benchmarks (median of 3 runs, 806 files):
  Check: Prettier 5.65s -> oxfmt 0.78s (~7x faster)
  Write: Prettier 6.19s -> oxfmt 0.88s (~7x faster)
updateSchemaFromEntities now accepts an optional vertexLookup parameter
to infer EdgeConnection entries from edges and their endpoint vertex
types. This makes the Schema Explorer show relationships discovered
through exploration without waiting for the database summary API.

Closes aws#1720
)

The proxy server used absolute paths in new URL() calls which replaced
the entire base URL path. This broke databases with non-root endpoints
like BlazeGraph (/blazegraph/namespace/kb/sparql).

Extract resolveEndpointUrl helper that ensures a trailing slash on the
base URL before resolving relative endpoint paths. Add tests for path
preservation across proxy, client-side URL construction, connection
normalization, and environment variable parsing.

Fixes aws#1752
* Add domain glossary and agent skill configuration

Bootstrap CONTEXT.md with the project's core domain vocabulary and
add agent skill docs (issue tracker, triage labels, domain layout) to
support engineering skills like triage, to-issues, and diagnose.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* Add .claude/ to gitignore, oxlint, and oxfmt ignore lists

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* feat: support ?s ?p ?o shorthand in SPARQL query results

Fixes aws#1766

- Modifies sparqlQuadBindingSchema in types.ts to support shorthand aliases natively
- Transforms validated shorthand schema structures back to canonical form
- Updates rawQuery and parseAndMapQuads test cases to validate new schema mapping behaviors

* chore: apply oxfmt formatting
…n conventions

Merge from aws/graph-explorer main (includes PR 1738 and other recent changes).

Conflict resolutions:
- Changelog.md: kept Unreleased feature section alongside new Release 3.0.3 section
- useTabular.ts: took mains oxlint disable comments for react-table v7 patterns
- configuration.ts: kept HEAD comments about defaultStyling.json; removed defensive spreads
- userPreferences.ts: kept mergeDefaultsIntoUserStyling; dropped obsolete useStoredGraphPreferences

Post-merge adaptations (adapt feature branch to new main conventions):
- defaultStyling.test.ts, configuration.test.ts: replace if(result) guards with assert()
  to satisfy new oxlint no-conditional-expect rule
- vite.config.ts: add custom-icons and defaultStyling to Vite dev proxy whitelist regex
  (PR 1738 introduced explicit whitelist; without these paths the features Express static
  routes 404 in dev mode)
- packages/graph-explorer/package.json: remove redundant nested lint-staged config block
  (oxlint was not installed; root package.json lint-staged already covers all TS/JS files;
  the nested block caused lint-staged v16 to invoke oxlint from the package subdirectory
  where it treats the root .oxlintrc.json as a non-root config, triggering a typeAware error)
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.

6 participants