Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 13 additions & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -247,7 +247,19 @@ jobs:
cache: 'pnpm'

- name: Run security audit
run: pnpm audit --audit-level=high --prod
# The npm audit endpoint has intermittent outages (ERR_SOCKET_TIMEOUT).
# Treat registry connectivity failures as a warning instead of failing
# the build; real vulnerability findings still fail.
run: |
set +e
output=$(pnpm audit --audit-level=high --prod 2>&1)
exit_code=$?
echo "$output"
if [ $exit_code -ne 0 ] && echo "$output" | grep -qE 'ERR_SOCKET_TIMEOUT|ECONNRESET|ECONNREFUSED|ETIMEDOUT|ENOTFOUND|EAI_AGAIN|FetchError'; then
echo "::warning::npm audit registry endpoint unreachable — skipping audit (network error, not a vulnerability finding)"
exit 0
fi
exit $exit_code

- name: Run dependency license check
run: pnpm dlx license-checker --onlyAllow 'MIT;Apache-2.0;ISC;BSD;BSD-2-Clause;BSD-3-Clause;Apache;Unlicense'
92 changes: 90 additions & 2 deletions src/components/DataVisNITRO/DataVisNITRO.stories.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,25 @@
import { useContext, useState } from 'react';
import { useContext, useEffect, useMemo, useState } from 'react';
import type { Meta, StoryObj } from '@storybook/react-vite';
import { GridAssistant, type GridAssistantColumn } from '@mieweb/datavis';
import {
GridAssistant,
type GridAssistantColumn,
type PrefsInstance,
} from '@mieweb/datavis';
import { Prefs } from 'datavis-ace';
import {
DataVisNitroContext,
DataVisNitroGrid,
DataVisNitroSource,
} from './DataVisNITRO';

// datavis-ace is untyped JS (`Prefs` is built with a runtime `makeSubclass`
// helper), so give it an explicit constructor signature for use below.
const PrefsConstructor = Prefs as unknown as new (
name: string,
moduleBindings: unknown,
opts: Record<string, unknown>
) => PrefsInstance;

const meta: Meta<typeof DataVisNitroGrid> = {
title: 'Components/Text & Data Display/DataVis NITRO',
component: DataVisNitroGrid,
Expand Down Expand Up @@ -302,3 +315,78 @@ export const OzwellAssistant: Story = {
</DataVisNitroSource>
),
};

const PREFS_STORAGE_KEY = 'mieweb-ui-storybook:datavis-prefs';

/**
* Reads the shared view from DataVisNitroContext, binds a localStorage-backed
* Prefs module to it, and passes the module to the grid so the perspective
* toolbar ("Main Perspective" dropdown, save/reset/history buttons) renders.
*/
const PerspectivesGrid = () => {
const view = useContext(DataVisNitroContext);

const prefs = useMemo(() => {
if (!view) return null;

return new PrefsConstructor('mieweb-ui-storybook:employees', null, {
autoSave: true,
backend: {
type: 'localStorage',
localStorage: {
key: PREFS_STORAGE_KEY,
},
},
});
Comment thread
garrity-miepub marked this conversation as resolved.
}, [view]);

useEffect(() => {
if (!view || !prefs) return;
view.setPrefs(prefs);
prefs.prime?.();
}, [view, prefs]);

if (!prefs) return null;

return (
<DataVisNitroGrid
title="Employees"
columns={EMPLOYEE_COLUMNS}
prefs={prefs}
showControls
height="480px"
/>
);
};

export const WithPerspectives: Story = {
loaders: [
() => {
// Clear saved perspectives in automated runs (test runner, visual
// regression) so the story renders deterministically, while keeping
// localStorage persistence for normal browsing. localStorage access
// can throw in restricted contexts, so fall back to defaults quietly.
try {
if (typeof navigator !== 'undefined' && navigator.webdriver) {
window.localStorage.removeItem(PREFS_STORAGE_KEY);
}
} catch {
// Storage unavailable — the story just renders its defaults.
}
return {};
},
],
parameters: {
docs: {
description: {
story:
'Passing a `prefs` module (a `PrefsInstance` from `datavis-ace`) enables the perspective toolbar: the "Main Perspective" dropdown, save / save-as / reset buttons, and undo/redo history. Perspectives capture the grid configuration (sort, filter, group, pivot, aggregate, column layout) and here persist to `localStorage`. Create the `Prefs` instance, bind it to the shared view with `view.setPrefs(prefs)`, and pass it to `<DataVisNitroGrid prefs={…}>`. In minimal mode the same toolbar appears inside the hamburger menu.',
},
},
},
render: () => (
<DataVisNitroSource type="http" url="/sample-data.json">
<PerspectivesGrid />
</DataVisNitroSource>
),
};
Loading