mirror of
https://github.com/qlik-oss/nebula.js.git
synced 2026-05-24 07:00:27 -04:00
chore(deps): update material-ui monorepo to v7 (major) (#1598)
* fix(deps): update dependency webpack-cli to v7 (#1935) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> * fix(deps): update minor and patch (#1934) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> * chore: re-run spec (#1938) * Potential fix for code scanning alert no. 98: Overly permissive regular expression range (#1936) Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com> * fix: align requirements better with client (#1937) * fix: aline requirements better with client * fix: remove comment * chore: fix for empty dims * fix: prototype pollution vulnerabilities in json-patch.js (#1941) * Initial plan * Fix prototype pollution security vulnerabilities in json-patch.js Co-authored-by: Caele <6318307+Caele@users.noreply.github.com> --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: Caele <6318307+Caele@users.noreply.github.com> * chore: normalize yarn resolutions for renovate compatibility (#1943) * chore: avoid renovate resolution lookup warnings * chore: dedupe yarn resolutions and normalize ranges Signed-off-by: Johan Enell <johan.enell@qlik.com> --------- Signed-off-by: Johan Enell <johan.enell@qlik.com> * fix(deps): update dependency puppeteer to v24.40.0 (#1947) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> * chore(deps): update material-ui monorepo to v7 * chore: perfrom mui v7 migration * chore: store test results * chore: adjust artifact storage * chore: fix lint * chore: fix report folder * chore: fix classnames --------- Signed-off-by: Johan Enell <johan.enell@qlik.com> Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> Co-authored-by: Tobias Åström <tsm@qlik.com> Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com> Co-authored-by: Copilot <198982749+Copilot@users.noreply.github.com> Co-authored-by: Caele <6318307+Caele@users.noreply.github.com> Co-authored-by: Johan Enell <johan.enell@qlik.com>
This commit is contained in:
51
.github/workflows/ci.yml
vendored
51
.github/workflows/ci.yml
vendored
@@ -34,6 +34,9 @@ jobs:
|
||||
validate:
|
||||
runs-on: ubuntu-latest
|
||||
needs: build
|
||||
permissions:
|
||||
contents: read
|
||||
checks: write
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- name: Enable Corepack
|
||||
@@ -58,14 +61,26 @@ jobs:
|
||||
JEST_JUNIT_OUTPUT_DIR: ./coverage/junit/
|
||||
run: yarn test:unit --coverage
|
||||
- name: Store junit results
|
||||
if: always()
|
||||
uses: actions/upload-artifact@v7
|
||||
with:
|
||||
name: junit
|
||||
path: coverage/junit
|
||||
- name: Publish junit test report
|
||||
if: ${{ always() && hashFiles('coverage/junit/*.xml') != '' }}
|
||||
uses: dorny/test-reporter@v2
|
||||
with:
|
||||
name: Unit Tests
|
||||
path: coverage/junit/*.xml
|
||||
reporter: jest-junit
|
||||
fail-on-error: false
|
||||
|
||||
test-integration:
|
||||
runs-on: ubuntu-latest
|
||||
needs: build
|
||||
permissions:
|
||||
contents: read
|
||||
checks: write
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- name: Enable Corepack
|
||||
@@ -84,7 +99,17 @@ jobs:
|
||||
- name: Install Playwright Browsers
|
||||
run: npx playwright install --with-deps
|
||||
- name: Test component
|
||||
env:
|
||||
PLAYWRIGHT_JUNIT_OUTPUT_NAME: component-junit.xml
|
||||
run: yarn run test:component
|
||||
- name: Publish component test report
|
||||
if: ${{ always() && hashFiles('test-results/component-junit.xml') != '' }}
|
||||
uses: dorny/test-reporter@v2
|
||||
with:
|
||||
name: Component Tests
|
||||
path: test-results/component-junit.xml
|
||||
reporter: jest-junit
|
||||
fail-on-error: false
|
||||
- name: Test mashup
|
||||
run: yarn run test:mashup
|
||||
- name: Store mashup artifacts
|
||||
@@ -93,8 +118,26 @@ jobs:
|
||||
with:
|
||||
name: mashup
|
||||
path: ./test/mashup
|
||||
- name: Publish mashup test report
|
||||
if: ${{ always() && hashFiles('test/mashup/reports/xml/*.xml') != '' }}
|
||||
uses: dorny/test-reporter@v2
|
||||
with:
|
||||
name: Mashup Tests
|
||||
path: test/mashup/reports/xml/*.xml
|
||||
reporter: jest-junit
|
||||
fail-on-error: false
|
||||
- name: Test integration
|
||||
env:
|
||||
PLAYWRIGHT_JUNIT_OUTPUT_NAME: integration-junit.xml
|
||||
run: yarn run test:integration
|
||||
- name: Publish integration test report
|
||||
if: ${{ always() && hashFiles('test-results/integration-junit.xml') != '' }}
|
||||
uses: dorny/test-reporter@v2
|
||||
with:
|
||||
name: Integration Tests
|
||||
path: test-results/integration-junit.xml
|
||||
reporter: jest-junit
|
||||
fail-on-error: false
|
||||
- name: Test rendering
|
||||
run: yarn run test:rendering
|
||||
- name: Store rendering artifacts
|
||||
@@ -103,6 +146,14 @@ jobs:
|
||||
with:
|
||||
name: rendering
|
||||
path: ./test/rendering
|
||||
- name: Publish rendering test report
|
||||
if: ${{ always() && hashFiles('test/rendering/reports/xml/*.xml') != '' }}
|
||||
uses: dorny/test-reporter@v2
|
||||
with:
|
||||
name: Rendering Tests
|
||||
path: test/rendering/reports/xml/*.xml
|
||||
reporter: jest-junit
|
||||
fail-on-error: false
|
||||
|
||||
test-create:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
@@ -6,14 +6,14 @@
|
||||
"devDependencies": {
|
||||
"@emotion/react": "^11.14.0",
|
||||
"@emotion/styled": "^11.14.1",
|
||||
"@mui/icons-material": "^6.5.0",
|
||||
"@mui/material": "^6.5.0",
|
||||
"@mui/icons-material": "^7.3.9",
|
||||
"@mui/material": "^7.3.9",
|
||||
"@nebula.js/conversion": "^6.7.0",
|
||||
"@nebula.js/locale": "^6.7.0",
|
||||
"@nebula.js/supernova": "^6.7.0",
|
||||
"@nebula.js/theme": "^6.7.0",
|
||||
"@nebula.js/ui": "^6.7.0",
|
||||
"@qlik/api": "2.4.1",
|
||||
"@qlik/api": "2.5.0",
|
||||
"@testing-library/dom": "^10.4.1",
|
||||
"@testing-library/react": "^16.3.2",
|
||||
"extend": "3.0.2",
|
||||
|
||||
@@ -38,9 +38,9 @@ const ActionToolbarElement = {
|
||||
|
||||
const ActionsGroup = React.forwardRef(({ className, actions = [], addAnchor = false, isRtl = false }, ref) =>
|
||||
actions.length > 0 ? (
|
||||
<Grid item container gap={0} flexDirection={isRtl ? 'row-reverse' : 'row'} wrap="nowrap" className={className}>
|
||||
<Grid container gap={0} flexDirection={isRtl ? 'row-reverse' : 'row'} wrap="nowrap" className={className}>
|
||||
{actions.map((e, ix) => (
|
||||
<Grid item key={e.key} className={`${classes.itemSpacing} ${classes.item}`}>
|
||||
<Grid key={e.key} className={`${classes.itemSpacing} ${classes.item}`}>
|
||||
<Item key={e.key} item={e} ref={ix === 0 ? ref : null} addAnchor={addAnchor} />
|
||||
</Grid>
|
||||
))}
|
||||
@@ -192,7 +192,7 @@ function ActionsToolbar({
|
||||
/>
|
||||
)}
|
||||
{showDivider && (
|
||||
<Grid item className={classes.itemSpacing} style={dividerStyle}>
|
||||
<Grid className={classes.itemSpacing} style={dividerStyle}>
|
||||
<Divider orientation="vertical" />
|
||||
</Grid>
|
||||
)}
|
||||
|
||||
@@ -142,9 +142,10 @@ const handleModal = ({ sn, layout, model }) => {
|
||||
};
|
||||
|
||||
const filterData = (d) => (d.qError ? d.qError.qErrorCode === 7005 : true);
|
||||
const hasError = (e) => e && e.qError && e.qError.qErrorCode !== 7005;
|
||||
|
||||
const validateInfo = (min, info, getDescription, translatedError, translatedCalcCond) =>
|
||||
[...Array(min).keys()].map((i) => {
|
||||
[...Array(Math.max(min, info.length)).keys()].map((i) => {
|
||||
const exists = !!(info && info[i]);
|
||||
const softError = exists && info[i].qError && info[i].qError.qErrorCode === 7005;
|
||||
const error = exists && !softError && info[i].qError;
|
||||
@@ -173,14 +174,14 @@ const validateTarget = (translator, layout, properties, def) => {
|
||||
const reqDimErrors = validateInfo(
|
||||
minD,
|
||||
getInfo(c.qDimensionInfo || c.qItems),
|
||||
(i) => def.dimensions.description(properties, i),
|
||||
(i) => def.dimensions.description(properties, i, {}),
|
||||
translator.get('Visualization.Invalid.Dimension'),
|
||||
translator.get('Visualization.UnfulfilledCalculationCondition')
|
||||
);
|
||||
const reqMeasErrors = validateInfo(
|
||||
minM,
|
||||
getInfo(c.qMeasureInfo),
|
||||
(i) => def.measures.description(properties, i),
|
||||
(i) => def.measures.description(properties, i, {}),
|
||||
translator.get('Visualization.Invalid.Measure'),
|
||||
translator.get('Visualization.UnfulfilledCalculationCondition')
|
||||
);
|
||||
@@ -197,18 +198,29 @@ const validateCubes = (translator, targets, layout) => {
|
||||
let hasLayoutErrors = false;
|
||||
let hasLayoutUnfulfilledCalculcationCondition = false;
|
||||
const layoutErrors = [];
|
||||
|
||||
for (let i = 0; i < targets.length; ++i) {
|
||||
const def = targets[i];
|
||||
|
||||
const minD = def.dimensions.min();
|
||||
const minM = def.measures.min();
|
||||
|
||||
const c = def.resolveLayout(layout);
|
||||
const d = getInfo(c.qDimensionInfo || c.qItems).filter(filterData); // Filter out optional calc conditions
|
||||
const m = getInfo(c.qMeasureInfo).filter(filterData); // Filter out optional calc conditions
|
||||
|
||||
const dims = getInfo(c.qDimensionInfo || c.qItems);
|
||||
const meas = getInfo(c.qMeasureInfo);
|
||||
|
||||
const d = dims.filter(filterData); // Filter out optional calc conditions
|
||||
const m = meas.filter(filterData); // Filter out optional calc conditions
|
||||
aggMinD += minD;
|
||||
aggMinM += minM;
|
||||
if (d.length < minD || m.length < minM) {
|
||||
hasUnfulfilledErrors = true;
|
||||
}
|
||||
|
||||
// Check for all non-calc-cond errors
|
||||
hasUnfulfilledErrors = hasUnfulfilledErrors || dims.some(hasError) || meas.some(hasError);
|
||||
|
||||
if (c.qError) {
|
||||
hasLayoutErrors = true;
|
||||
hasLayoutUnfulfilledCalculcationCondition = c.qError.qErrorCode === 7005;
|
||||
@@ -683,8 +695,7 @@ const Cell = forwardRef(
|
||||
<Grid
|
||||
tabIndex={keyboardNavigation && !externalFocusManagement ? 0 : -1}
|
||||
onKeyDown={keyboardNavigation && !externalFocusManagement ? handleKeyDown : null}
|
||||
item
|
||||
xs
|
||||
size="grow"
|
||||
className={CellBody.className}
|
||||
style={{
|
||||
height: '100%',
|
||||
|
||||
@@ -22,9 +22,9 @@ function DescriptionRow({ d }) {
|
||||
</Typography>
|
||||
);
|
||||
return (
|
||||
<Grid item container alignItems="center" wrap="nowrap">
|
||||
<Grid item>{WrappedIcon}</Grid>
|
||||
<Grid container item zeroMinWidth wrap="nowrap">
|
||||
<Grid container alignItems="center" wrap="nowrap">
|
||||
<Grid>{WrappedIcon}</Grid>
|
||||
<Grid container sx={{ minWidth: 0 }} wrap="nowrap">
|
||||
<Typography noWrap component="p">
|
||||
<Typography component="span" variant="subtitle2" color={color}>
|
||||
{d.description}
|
||||
@@ -47,14 +47,13 @@ function DescriptionRow({ d }) {
|
||||
function Descriptions({ data }) {
|
||||
const theme = useTheme();
|
||||
return (
|
||||
<Grid container item style={{ maxWidth: '300px', overflow: 'hidden' }}>
|
||||
<Grid container style={{ maxWidth: '300px', overflow: 'hidden' }}>
|
||||
{data.map((e, ix) => {
|
||||
const Rows = e.descriptions.map((d, dix) => <DescriptionRow d={d} key={dix} />);
|
||||
return (
|
||||
Rows.length > 0 && (
|
||||
<Grid
|
||||
container
|
||||
item
|
||||
key={ix}
|
||||
direction="column"
|
||||
style={{
|
||||
@@ -82,15 +81,15 @@ export default function Error({ title = 'Error', message = '', data = [] }) {
|
||||
justifyContent="center"
|
||||
style={{ position: 'relative', height: '100%', width: '100%' }}
|
||||
>
|
||||
<Grid item>
|
||||
<Grid>
|
||||
<WarningTriangle style={{ fontSize: '38px' }} />
|
||||
</Grid>
|
||||
<Grid item>
|
||||
<Grid>
|
||||
<Typography variant="h6" align="center" data-tid="error-title">
|
||||
{title}
|
||||
</Typography>
|
||||
</Grid>
|
||||
<Grid item>
|
||||
<Grid>
|
||||
<Typography variant="subtitle1" align="center" data-tid="error-message">
|
||||
{message}
|
||||
</Typography>
|
||||
|
||||
@@ -40,7 +40,6 @@ function Footer({ layout, titleStyles = {}, translator, flags, isCardTheme, isRt
|
||||
return layout && layout.showTitles && (layout.footnote || showFilters) ? (
|
||||
<StyledGrid container>
|
||||
<Grid
|
||||
item
|
||||
className={classes.itemStyle}
|
||||
data-testid={CellFooter.className}
|
||||
sx={{ paddingTop: (theme) => (themePaddingEnabled ? paddingTop : theme.spacing(1)) }}
|
||||
|
||||
@@ -78,8 +78,8 @@ function Header({ id, layout, sn, anchorEl, hovering, focusHandler, titleStyles
|
||||
/>
|
||||
);
|
||||
return (
|
||||
<StyledGrid item container wrap="nowrap" className={cls.join(' ')}>
|
||||
<Grid item zeroMinWidth xs dir={isRtl ? 'rtl' : 'ltr'}>
|
||||
<StyledGrid container wrap="nowrap" className={cls.join(' ')}>
|
||||
<Grid size="grow" sx={{ minWidth: 0 }} dir={isRtl ? 'rtl' : 'ltr'}>
|
||||
<Grid container wrap="nowrap" direction="column">
|
||||
{showTitle ? (
|
||||
<Tooltip title={layout.title}>
|
||||
@@ -109,7 +109,7 @@ function Header({ id, layout, sn, anchorEl, hovering, focusHandler, titleStyles
|
||||
)}
|
||||
</Grid>
|
||||
</Grid>
|
||||
<Grid item>{Toolbar}</Grid>
|
||||
<Grid>{Toolbar}</Grid>
|
||||
</StyledGrid>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -33,17 +33,17 @@ const StyledGrid = styled(Grid)(() => ({
|
||||
export function Cancel({ cancel, translator, ...props }) {
|
||||
return (
|
||||
<>
|
||||
<StyledGrid container item direction="column" alignItems="center" gap={2}>
|
||||
<Grid item>
|
||||
<StyledGrid container direction="column" alignItems="center" gap={2}>
|
||||
<Grid>
|
||||
<Progress />
|
||||
</Grid>
|
||||
<Grid item>
|
||||
<Grid>
|
||||
<Typography variant="h6" align="center" data-tid="update-active">
|
||||
{translator.get('Object.Update.Active')}
|
||||
</Typography>
|
||||
</Grid>
|
||||
</StyledGrid>
|
||||
<Grid item {...props}>
|
||||
<Grid {...props}>
|
||||
<Button variant="contained" onClick={cancel}>
|
||||
{translator.get('Cancel')}
|
||||
</Button>
|
||||
@@ -55,15 +55,15 @@ export function Cancel({ cancel, translator, ...props }) {
|
||||
export function Retry({ retry, translator, ...props }) {
|
||||
return (
|
||||
<>
|
||||
<Grid item>
|
||||
<Grid>
|
||||
<WarningTriangle style={{ fontSize: '38px' }} />
|
||||
</Grid>
|
||||
<Grid item>
|
||||
<Grid>
|
||||
<Typography variant="h6" align="center" data-tid="update-cancelled">
|
||||
{translator.get('Object.Update.Cancelled')}
|
||||
</Typography>
|
||||
</Grid>
|
||||
<Grid item>
|
||||
<Grid>
|
||||
<Button variant="contained" onClick={retry} {...props}>
|
||||
{translator.get('Retry')}
|
||||
</Button>
|
||||
|
||||
@@ -395,6 +395,98 @@ describe('<Cell />', () => {
|
||||
expect(ftypes[0].props.title).toBe('Visualization.Incomplete');
|
||||
});
|
||||
|
||||
test('should not render requirements', async () => {
|
||||
const localLayout = { visualization: 'sn', title: 'foo', foo: { qDimensionInfo: [{}], qMeasureInfo: [{}] } };
|
||||
const sn = {
|
||||
generator: {
|
||||
qae: {
|
||||
data: {
|
||||
targets: [
|
||||
{
|
||||
resolveLayout: () => localLayout.foo,
|
||||
dimensions: {
|
||||
min: () => 1,
|
||||
max: () => 1,
|
||||
description: (_properties, ix) =>
|
||||
ix === 0
|
||||
? 'Column'
|
||||
: 'Cells - dkslfjd dkslfjd dkslfjd dkslfjd dkslfjd dkslfjd dkslfjd dkslfjd dkslfjd dkslfjd dkslfjd dkslfjd dkslfjd dkslfjd ',
|
||||
},
|
||||
measures: {
|
||||
min: () => 1,
|
||||
max: () => 1,
|
||||
description: () => 'Size',
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
const types = {
|
||||
get: jest.fn().mockReturnValue({
|
||||
supernova: async () => ({ create: () => sn }),
|
||||
}),
|
||||
getSupportedVersion: jest.fn().mockReturnValue('1.0.0'),
|
||||
};
|
||||
const model = {
|
||||
getProperties: async () => {},
|
||||
};
|
||||
await render({ types, model });
|
||||
|
||||
const ftypes = renderer.root.findAllByType(CError);
|
||||
expect(ftypes).toHaveLength(0);
|
||||
const renderedSn = renderer.root.findByType(Supernova);
|
||||
expect(renderedSn.props.sn).toEqual(sn);
|
||||
});
|
||||
|
||||
test('should render requirements for dim error', async () => {
|
||||
const localLayout = {
|
||||
visualization: 'sn',
|
||||
foo: { qDimensionInfo: [{}, { qError: { qErrorCode: 7000 } }], qMeasureInfo: [{}] },
|
||||
};
|
||||
const sn = {
|
||||
generator: {
|
||||
qae: {
|
||||
data: {
|
||||
targets: [
|
||||
{
|
||||
resolveLayout: () => localLayout.foo,
|
||||
dimensions: {
|
||||
min: () => 1,
|
||||
max: () => 2,
|
||||
description: (_properties, ix) =>
|
||||
ix === 0
|
||||
? 'Column'
|
||||
: 'Cells - dkslfjd dkslfjd dkslfjd dkslfjd dkslfjd dkslfjd dkslfjd dkslfjd dkslfjd dkslfjd dkslfjd dkslfjd dkslfjd dkslfjd ',
|
||||
},
|
||||
measures: {
|
||||
min: () => 1,
|
||||
max: () => 1,
|
||||
description: () => 'Size',
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
const types = {
|
||||
get: jest.fn().mockReturnValue({
|
||||
supernova: async () => ({ create: () => sn }),
|
||||
}),
|
||||
getSupportedVersion: jest.fn().mockReturnValue('1.0.0'),
|
||||
};
|
||||
const model = {
|
||||
getProperties: async () => {},
|
||||
};
|
||||
await render({ types, model });
|
||||
|
||||
const ftypes = renderer.root.findAllByType(CError);
|
||||
expect(ftypes).toHaveLength(1);
|
||||
expect(ftypes[0].props.title).toBe('Visualization.Incomplete');
|
||||
});
|
||||
|
||||
test('should render requirements for multiple cubes', async () => {
|
||||
const localLayout = { visualization: 'sn', foo: { qDimensionInfo: [], qMeasureInfo: [] } };
|
||||
const sn = {
|
||||
|
||||
@@ -294,7 +294,6 @@ function ListBoxInline({ options, layout }) {
|
||||
/>
|
||||
{showAttachedToolbar && listBoxHeader}
|
||||
<Grid
|
||||
item
|
||||
container
|
||||
direction="column"
|
||||
height="100%"
|
||||
@@ -303,7 +302,7 @@ function ListBoxInline({ options, layout }) {
|
||||
aria-label={translator.get('Listbox.ResultFilterLabel')}
|
||||
ref={listboxChildRef}
|
||||
>
|
||||
<Grid item>
|
||||
<Grid>
|
||||
<ListBoxSearch
|
||||
ref={searchInputRef}
|
||||
selections={selections}
|
||||
@@ -322,7 +321,7 @@ function ListBoxInline({ options, layout }) {
|
||||
styles={styles}
|
||||
/>
|
||||
</Grid>
|
||||
<Grid item xs className={classes.listboxWrapper}>
|
||||
<Grid size="grow" className={classes.listboxWrapper}>
|
||||
{isInvalid ? (
|
||||
<ListBoxError text={errorText} />
|
||||
) : (
|
||||
|
||||
@@ -157,8 +157,8 @@ export default function ListBoxPopover({
|
||||
direction={direction}
|
||||
>
|
||||
<Grid container direction="column" gap={0} ref={containerRef}>
|
||||
<Grid item container style={{ direction, padding: theme.spacing(1) }}>
|
||||
<Grid item>
|
||||
<Grid container style={{ direction, padding: theme.spacing(1) }}>
|
||||
<Grid>
|
||||
{isLocked ? (
|
||||
<IconButton
|
||||
onClick={unlock}
|
||||
@@ -181,8 +181,8 @@ export default function ListBoxPopover({
|
||||
</IconButton>
|
||||
)}
|
||||
</Grid>
|
||||
<Grid item xs />
|
||||
<Grid item>
|
||||
<Grid size="grow" />
|
||||
<Grid>
|
||||
<ActionsToolbar
|
||||
layout={layout}
|
||||
more={{
|
||||
@@ -206,9 +206,9 @@ export default function ListBoxPopover({
|
||||
/>
|
||||
</Grid>
|
||||
</Grid>
|
||||
<Grid item xs>
|
||||
<Grid size="grow">
|
||||
<div ref={moreAlignTo} />
|
||||
<Grid item>
|
||||
<Grid>
|
||||
<ListBoxSearch
|
||||
ref={searchInputRef}
|
||||
popoverOpen={open}
|
||||
|
||||
@@ -240,7 +240,7 @@ export default function ListBoxHeader({
|
||||
/>
|
||||
)}
|
||||
{showLeftIcon && (
|
||||
<Grid item container alignItems="center" width={iconsWidth} className="header-action-container">
|
||||
<Grid container alignItems="center" width={iconsWidth} className="header-action-container">
|
||||
{lockedIconComp || (showSearchIcon && searchIconComp)}
|
||||
<DimensionIcon
|
||||
iconData={iconData}
|
||||
@@ -252,9 +252,8 @@ export default function ListBoxHeader({
|
||||
</Grid>
|
||||
)}
|
||||
<Grid
|
||||
item
|
||||
xs
|
||||
minWidth={0} // needed to text-overflow see: https://css-tricks.com/flexbox-truncated-text/
|
||||
size="grow"
|
||||
sx={{ minWidth: 0 }} // needed to text-overflow see: https://css-tricks.com/flexbox-truncated-text/
|
||||
justifyContent={isRtl ? 'flex-end' : 'flex-start'}
|
||||
className={classes.listBoxHeader}
|
||||
>
|
||||
@@ -262,9 +261,7 @@ export default function ListBoxHeader({
|
||||
{layout.title}
|
||||
</HeaderTitle>
|
||||
</Grid>
|
||||
<Grid item display="flex">
|
||||
{actionsToolbar}
|
||||
</Grid>
|
||||
<Grid display="flex">{actionsToolbar}</Grid>
|
||||
</StyledGridHeader>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -222,10 +222,7 @@ function RowColumn({ index, rowIndex, columnIndex, style, data }) {
|
||||
layoutOrder={layoutOrder}
|
||||
itemPadding={itemPadding}
|
||||
gap={0}
|
||||
className={joinClassNames(['value', ...classArr])}
|
||||
classes={{
|
||||
root: classes.fieldRoot,
|
||||
}}
|
||||
className={joinClassNames(['value', classes.fieldRoot, ...classArr])}
|
||||
onClick={onClick}
|
||||
onMouseDown={onMouseDown}
|
||||
onMouseUp={onMouseUp}
|
||||
@@ -248,12 +245,7 @@ function RowColumn({ index, rowIndex, columnIndex, style, data }) {
|
||||
frequencyMax={frequencyMax}
|
||||
/>
|
||||
)}
|
||||
<Grid
|
||||
item
|
||||
style={cellStyle}
|
||||
className={joinClassNames([classes.cell, classes.selectedCell])}
|
||||
title={`${label}`}
|
||||
>
|
||||
<Grid style={cellStyle} className={joinClassNames([classes.cell, classes.selectedCell])} title={`${label}`}>
|
||||
{labels ? (
|
||||
<FieldWithRanges
|
||||
onChange={onChange}
|
||||
@@ -290,7 +282,7 @@ function RowColumn({ index, rowIndex, columnIndex, style, data }) {
|
||||
{freqIsAllowed && <Frequency cell={cell} checkboxes={checkboxes} dense={dense} showGray={showGray} />}
|
||||
|
||||
{showAnyIcon && (
|
||||
<Grid item className={classes.icon}>
|
||||
<Grid className={classes.icon}>
|
||||
{showLockIcon && <Lock style={iconStyles} size="small" />}
|
||||
{showTickIcon && <Tick style={iconStyles} size="small" />}
|
||||
</Grid>
|
||||
|
||||
@@ -8,7 +8,6 @@ function Frequency({ cell, checkboxes, dense, showGray }) {
|
||||
const frequencyText = getFrequencyText(cell?.qFrequency);
|
||||
return (
|
||||
<Grid
|
||||
item
|
||||
style={{ display: 'flex', alignItems: 'center' }}
|
||||
className={classes.frequencyCount}
|
||||
aria-label={frequencyText}
|
||||
|
||||
@@ -25,14 +25,13 @@ function AppSelections({ app }) {
|
||||
}}
|
||||
>
|
||||
<Grid
|
||||
item
|
||||
style={{
|
||||
borderRight: `1px solid ${theme.palette.divider}`,
|
||||
}}
|
||||
>
|
||||
<Nav api={appSelections} app={app} />
|
||||
</Grid>
|
||||
<Grid item xs style={{ backgroundColor: theme.palette.background.darker, overflow: 'hidden' }}>
|
||||
<Grid size="grow" style={{ backgroundColor: theme.palette.background.darker, overflow: 'hidden' }}>
|
||||
<SelectedFields api={appSelections} app={app} />
|
||||
</Grid>
|
||||
</Grid>
|
||||
|
||||
@@ -80,7 +80,7 @@ export default function More({ items = [], api }) {
|
||||
|
||||
return (
|
||||
<StyledGrid container gap={0} className={classes.item} onClick={handleShowMoreItems}>
|
||||
<Grid item>
|
||||
<Grid>
|
||||
<Box
|
||||
borderRadius={theme.shape.borderRadius}
|
||||
style={{
|
||||
@@ -94,7 +94,7 @@ export default function More({ items = [], api }) {
|
||||
</Typography>
|
||||
</Box>
|
||||
</Grid>
|
||||
<Grid item>
|
||||
<Grid>
|
||||
<IconButton size="large">
|
||||
<DownArrow />
|
||||
</IconButton>
|
||||
|
||||
@@ -71,17 +71,17 @@ export default function MultiState({ field, api, moreAlignTo = null, onClose = (
|
||||
if (!moreAlignTo) {
|
||||
Header = (
|
||||
<>
|
||||
<Grid item xs zeroMinWidth>
|
||||
<Grid sx={{ minWidth: 0, flexGrow: 1 }}>
|
||||
<Badge style={{ padding: '0px 8px' }} color="secondary" badgeContent={field.states.length}>
|
||||
<Typography component="span" noWrap style={{ fontSize: '12px', lineHeight: '16px', fontWeight: 600 }}>
|
||||
{field.label}
|
||||
</Typography>
|
||||
</Badge>
|
||||
</Grid>
|
||||
<Grid item>
|
||||
<Grid>
|
||||
<div style={{ width: '12px' }} />
|
||||
</Grid>
|
||||
<Grid item>
|
||||
<Grid>
|
||||
<IconButton size="large">
|
||||
<DownArrow />
|
||||
</IconButton>
|
||||
|
||||
@@ -23,7 +23,7 @@ export default function Nav({ api, app }) {
|
||||
padding: '0 8px',
|
||||
}}
|
||||
>
|
||||
<Grid item>
|
||||
<Grid>
|
||||
<IconButton
|
||||
style={{ marginRight: '8px' }}
|
||||
disabled={!navState || !navState.canGoBack}
|
||||
@@ -34,7 +34,7 @@ export default function Nav({ api, app }) {
|
||||
<SelectionsBack />
|
||||
</IconButton>
|
||||
</Grid>
|
||||
<Grid item>
|
||||
<Grid>
|
||||
<IconButton
|
||||
style={{ marginRight: '8px' }}
|
||||
disabled={!navState || !navState.canGoForward}
|
||||
@@ -45,7 +45,7 @@ export default function Nav({ api, app }) {
|
||||
<SelectionsForward />
|
||||
</IconButton>
|
||||
</Grid>
|
||||
<Grid item>
|
||||
<Grid>
|
||||
<IconButton
|
||||
disabled={!navState || !navState.canClear}
|
||||
title={translator.get('Selection.ClearAll')}
|
||||
|
||||
@@ -90,7 +90,7 @@ export default function OneField({
|
||||
let SegmentsIndicator = null;
|
||||
if (!moreAlignTo) {
|
||||
Header = (
|
||||
<Grid item xs style={{ minWidth: 0, flexGrow: 1, opacity: selection.qLocked ? '0.3' : '' }}>
|
||||
<Grid style={{ minWidth: 0, flexGrow: 1, opacity: selection.qLocked ? '0.3' : '' }}>
|
||||
<Typography noWrap style={{ fontSize: '12px', lineHeight: '16px', fontWeight: 600 }}>
|
||||
{field.label}
|
||||
</Typography>
|
||||
@@ -102,7 +102,7 @@ export default function OneField({
|
||||
|
||||
if (selection.qLocked) {
|
||||
Icon = (
|
||||
<Grid item>
|
||||
<Grid>
|
||||
<IconButton size="large">
|
||||
<Lock />
|
||||
</IconButton>
|
||||
@@ -110,7 +110,7 @@ export default function OneField({
|
||||
);
|
||||
} else if (!selection.qOneAndOnlyOne) {
|
||||
Icon = (
|
||||
<Grid item>
|
||||
<Grid>
|
||||
<IconButton
|
||||
title={translator.get('Selection.Clear')}
|
||||
onClick={(e) => {
|
||||
|
||||
@@ -128,7 +128,6 @@ export default function SelectedFields({ api, app }) {
|
||||
<Grid ref={containerRef} container gap={0} wrap="nowrap" style={{ height: '100%' }}>
|
||||
{more.length > 0 && (
|
||||
<Grid
|
||||
item
|
||||
style={{
|
||||
position: 'relative',
|
||||
maxWidth: '98px',
|
||||
@@ -142,7 +141,6 @@ export default function SelectedFields({ api, app }) {
|
||||
)}
|
||||
{items.map((s, index) => (
|
||||
<Grid
|
||||
item
|
||||
// eslint-disable-next-line react/no-array-index-key
|
||||
key={`${s.states.join('::')}::${s.qField ?? s.name}${index}`}
|
||||
style={{
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"scriptappy": "1.1.0",
|
||||
"scriptappy": "1.1.3",
|
||||
"info": {
|
||||
"name": "@nebula.js/stardust:listbox",
|
||||
"description": "nebula listbox properties definition",
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"scriptappy": "1.1.0",
|
||||
"scriptappy": "1.1.3",
|
||||
"info": {
|
||||
"name": "@nebula.js/stardust",
|
||||
"description": "Product and framework agnostic integration API for Qlik's Associative Engine",
|
||||
@@ -673,6 +673,84 @@
|
||||
}
|
||||
},
|
||||
"definitions": {
|
||||
"Translator": {
|
||||
"kind": "class",
|
||||
"constructor": {
|
||||
"kind": "function",
|
||||
"params": []
|
||||
},
|
||||
"entries": {
|
||||
"language": {
|
||||
"description": "Returns current locale.",
|
||||
"kind": "function",
|
||||
"params": [
|
||||
{
|
||||
"name": "lang",
|
||||
"description": "language Locale to updated the currentLocale value",
|
||||
"optional": true,
|
||||
"type": "string"
|
||||
}
|
||||
],
|
||||
"returns": {
|
||||
"description": "current locale.",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"add": {
|
||||
"description": "Registers a string in multiple locales",
|
||||
"kind": "function",
|
||||
"params": [
|
||||
{
|
||||
"name": "item",
|
||||
"kind": "object",
|
||||
"entries": {
|
||||
"id": {
|
||||
"type": "string"
|
||||
},
|
||||
"locale": {
|
||||
"type": "object",
|
||||
"generics": [
|
||||
{
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"type": "string"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"examples": [
|
||||
"translator.add({\n id: 'company.hello_user',\n locale: {\n 'en-US': 'Hello {0}',\n 'sv-SE': 'Hej {0}'\n }\n});\ntranslator.get('company.hello_user', ['John']); // Hello John"
|
||||
]
|
||||
},
|
||||
"get": {
|
||||
"description": "Translates a string for current locale.",
|
||||
"kind": "function",
|
||||
"params": [
|
||||
{
|
||||
"name": "str",
|
||||
"description": "ID of the registered string.",
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"name": "args",
|
||||
"description": "Values passed down for string interpolation.",
|
||||
"optional": true,
|
||||
"kind": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
],
|
||||
"returns": {
|
||||
"description": "The translated string.",
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"Component": {
|
||||
"kind": "interface",
|
||||
"entries": {
|
||||
@@ -1486,6 +1564,167 @@
|
||||
"const viz = await embed(app).render({\n element,\n type: 'barchart'\n});\nviz.destroy();"
|
||||
]
|
||||
},
|
||||
"ActionToolbarElement": {
|
||||
"availability": {
|
||||
"since": "2.1.0"
|
||||
},
|
||||
"extends": [
|
||||
{
|
||||
"type": "HTMLElement"
|
||||
}
|
||||
],
|
||||
"kind": "interface",
|
||||
"entries": {
|
||||
"className": {
|
||||
"value": "'njs-action-toolbar-popover'",
|
||||
"kind": "literal"
|
||||
}
|
||||
}
|
||||
},
|
||||
"ActionElement": {
|
||||
"availability": {
|
||||
"since": "2.0.0"
|
||||
},
|
||||
"extends": [
|
||||
{
|
||||
"type": "HTMLElement"
|
||||
}
|
||||
],
|
||||
"kind": "interface",
|
||||
"entries": {
|
||||
"className": {
|
||||
"value": "'njs-cell-action'",
|
||||
"kind": "literal"
|
||||
}
|
||||
}
|
||||
},
|
||||
"CellElement": {
|
||||
"extends": [
|
||||
{
|
||||
"type": "HTMLElement"
|
||||
}
|
||||
],
|
||||
"kind": "interface",
|
||||
"entries": {
|
||||
"className": {
|
||||
"value": "'njs-cell'",
|
||||
"kind": "literal"
|
||||
}
|
||||
}
|
||||
},
|
||||
"CellBody": {
|
||||
"extends": [
|
||||
{
|
||||
"type": "HTMLElement"
|
||||
}
|
||||
],
|
||||
"kind": "interface",
|
||||
"entries": {
|
||||
"className": {
|
||||
"value": "'njs-cell-body'",
|
||||
"kind": "literal"
|
||||
}
|
||||
}
|
||||
},
|
||||
"CellFooter": {
|
||||
"availability": {
|
||||
"since": "2.0.0"
|
||||
},
|
||||
"extends": [
|
||||
{
|
||||
"type": "HTMLElement"
|
||||
}
|
||||
],
|
||||
"kind": "interface",
|
||||
"entries": {
|
||||
"className": {
|
||||
"value": "'njs-cell-footer'",
|
||||
"kind": "literal"
|
||||
}
|
||||
}
|
||||
},
|
||||
"CellTitle": {
|
||||
"availability": {
|
||||
"since": "2.0.0"
|
||||
},
|
||||
"extends": [
|
||||
{
|
||||
"type": "HTMLElement"
|
||||
}
|
||||
],
|
||||
"kind": "interface",
|
||||
"entries": {
|
||||
"className": {
|
||||
"value": "'njs-cell-title'",
|
||||
"kind": "literal"
|
||||
}
|
||||
}
|
||||
},
|
||||
"CellSubTitle": {
|
||||
"availability": {
|
||||
"since": "2.0.0"
|
||||
},
|
||||
"extends": [
|
||||
{
|
||||
"type": "HTMLElement"
|
||||
}
|
||||
],
|
||||
"kind": "interface",
|
||||
"entries": {
|
||||
"className": {
|
||||
"value": "'njs-cell-sub-title'",
|
||||
"kind": "literal"
|
||||
}
|
||||
}
|
||||
},
|
||||
"SheetElement": {
|
||||
"stability": "experimental",
|
||||
"availability": {
|
||||
"since": "3.1.0"
|
||||
},
|
||||
"extends": [
|
||||
{
|
||||
"type": "HTMLElement"
|
||||
}
|
||||
],
|
||||
"kind": "interface",
|
||||
"entries": {
|
||||
"className": {
|
||||
"value": "'njs-sheet'",
|
||||
"kind": "literal"
|
||||
}
|
||||
}
|
||||
},
|
||||
"VizElementAttributes": {
|
||||
"extends": [
|
||||
{
|
||||
"type": "NamedNodeMap"
|
||||
}
|
||||
],
|
||||
"kind": "interface",
|
||||
"entries": {
|
||||
"data-render-count": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"VizElement": {
|
||||
"extends": [
|
||||
{
|
||||
"type": "HTMLElement"
|
||||
}
|
||||
],
|
||||
"kind": "interface",
|
||||
"entries": {
|
||||
"attributes": {
|
||||
"type": "#/definitions/VizElementAttributes"
|
||||
},
|
||||
"className": {
|
||||
"value": "'njs-viz'",
|
||||
"kind": "literal"
|
||||
}
|
||||
}
|
||||
},
|
||||
"Flags": {
|
||||
"kind": "interface",
|
||||
"entries": {
|
||||
@@ -2056,167 +2295,6 @@
|
||||
"const navigation = useNavigation();\n//...\nuseEffect(() => {\n const onSheetChanged = () => {\n // do something\n };\n if (navigation?.addListener) {\n navigation.addListener(\"sheetChanged\", onSheetChanged);\n }\n return () => {\n if (navigation?.removeListener) {\n navigation.removeListener(\"sheetChanged\", onSheetChanged);\n }\n };\n}, [navigation]);\n\nconst onSheetClick = (sheetId: string) => {\n navigation?.goToSheet(sheetId);\n};"
|
||||
]
|
||||
},
|
||||
"ActionToolbarElement": {
|
||||
"availability": {
|
||||
"since": "2.1.0"
|
||||
},
|
||||
"extends": [
|
||||
{
|
||||
"type": "HTMLElement"
|
||||
}
|
||||
],
|
||||
"kind": "interface",
|
||||
"entries": {
|
||||
"className": {
|
||||
"value": "'njs-action-toolbar-popover'",
|
||||
"kind": "literal"
|
||||
}
|
||||
}
|
||||
},
|
||||
"ActionElement": {
|
||||
"availability": {
|
||||
"since": "2.0.0"
|
||||
},
|
||||
"extends": [
|
||||
{
|
||||
"type": "HTMLElement"
|
||||
}
|
||||
],
|
||||
"kind": "interface",
|
||||
"entries": {
|
||||
"className": {
|
||||
"value": "'njs-cell-action'",
|
||||
"kind": "literal"
|
||||
}
|
||||
}
|
||||
},
|
||||
"CellElement": {
|
||||
"extends": [
|
||||
{
|
||||
"type": "HTMLElement"
|
||||
}
|
||||
],
|
||||
"kind": "interface",
|
||||
"entries": {
|
||||
"className": {
|
||||
"value": "'njs-cell'",
|
||||
"kind": "literal"
|
||||
}
|
||||
}
|
||||
},
|
||||
"CellBody": {
|
||||
"extends": [
|
||||
{
|
||||
"type": "HTMLElement"
|
||||
}
|
||||
],
|
||||
"kind": "interface",
|
||||
"entries": {
|
||||
"className": {
|
||||
"value": "'njs-cell-body'",
|
||||
"kind": "literal"
|
||||
}
|
||||
}
|
||||
},
|
||||
"CellFooter": {
|
||||
"availability": {
|
||||
"since": "2.0.0"
|
||||
},
|
||||
"extends": [
|
||||
{
|
||||
"type": "HTMLElement"
|
||||
}
|
||||
],
|
||||
"kind": "interface",
|
||||
"entries": {
|
||||
"className": {
|
||||
"value": "'njs-cell-footer'",
|
||||
"kind": "literal"
|
||||
}
|
||||
}
|
||||
},
|
||||
"CellTitle": {
|
||||
"availability": {
|
||||
"since": "2.0.0"
|
||||
},
|
||||
"extends": [
|
||||
{
|
||||
"type": "HTMLElement"
|
||||
}
|
||||
],
|
||||
"kind": "interface",
|
||||
"entries": {
|
||||
"className": {
|
||||
"value": "'njs-cell-title'",
|
||||
"kind": "literal"
|
||||
}
|
||||
}
|
||||
},
|
||||
"CellSubTitle": {
|
||||
"availability": {
|
||||
"since": "2.0.0"
|
||||
},
|
||||
"extends": [
|
||||
{
|
||||
"type": "HTMLElement"
|
||||
}
|
||||
],
|
||||
"kind": "interface",
|
||||
"entries": {
|
||||
"className": {
|
||||
"value": "'njs-cell-sub-title'",
|
||||
"kind": "literal"
|
||||
}
|
||||
}
|
||||
},
|
||||
"SheetElement": {
|
||||
"stability": "experimental",
|
||||
"availability": {
|
||||
"since": "3.1.0"
|
||||
},
|
||||
"extends": [
|
||||
{
|
||||
"type": "HTMLElement"
|
||||
}
|
||||
],
|
||||
"kind": "interface",
|
||||
"entries": {
|
||||
"className": {
|
||||
"value": "'njs-sheet'",
|
||||
"kind": "literal"
|
||||
}
|
||||
}
|
||||
},
|
||||
"VizElementAttributes": {
|
||||
"extends": [
|
||||
{
|
||||
"type": "NamedNodeMap"
|
||||
}
|
||||
],
|
||||
"kind": "interface",
|
||||
"entries": {
|
||||
"data-render-count": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"VizElement": {
|
||||
"extends": [
|
||||
{
|
||||
"type": "HTMLElement"
|
||||
}
|
||||
],
|
||||
"kind": "interface",
|
||||
"entries": {
|
||||
"attributes": {
|
||||
"type": "#/definitions/VizElementAttributes"
|
||||
},
|
||||
"className": {
|
||||
"value": "'njs-viz'",
|
||||
"kind": "literal"
|
||||
}
|
||||
}
|
||||
},
|
||||
"Visualization": {
|
||||
"description": "The entry point for defining a visualization.",
|
||||
"kind": "interface",
|
||||
@@ -2749,84 +2827,6 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"Translator": {
|
||||
"kind": "class",
|
||||
"constructor": {
|
||||
"kind": "function",
|
||||
"params": []
|
||||
},
|
||||
"entries": {
|
||||
"language": {
|
||||
"description": "Returns current locale.",
|
||||
"kind": "function",
|
||||
"params": [
|
||||
{
|
||||
"name": "lang",
|
||||
"description": "language Locale to updated the currentLocale value",
|
||||
"optional": true,
|
||||
"type": "string"
|
||||
}
|
||||
],
|
||||
"returns": {
|
||||
"description": "current locale.",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"add": {
|
||||
"description": "Registers a string in multiple locales",
|
||||
"kind": "function",
|
||||
"params": [
|
||||
{
|
||||
"name": "item",
|
||||
"kind": "object",
|
||||
"entries": {
|
||||
"id": {
|
||||
"type": "string"
|
||||
},
|
||||
"locale": {
|
||||
"type": "object",
|
||||
"generics": [
|
||||
{
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"type": "string"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"examples": [
|
||||
"translator.add({\n id: 'company.hello_user',\n locale: {\n 'en-US': 'Hello {0}',\n 'sv-SE': 'Hej {0}'\n }\n});\ntranslator.get('company.hello_user', ['John']); // Hello John"
|
||||
]
|
||||
},
|
||||
"get": {
|
||||
"description": "Translates a string for current locale.",
|
||||
"kind": "function",
|
||||
"params": [
|
||||
{
|
||||
"name": "str",
|
||||
"description": "ID of the registered string.",
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"name": "args",
|
||||
"description": "Values passed down for string interpolation.",
|
||||
"optional": true,
|
||||
"kind": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
],
|
||||
"returns": {
|
||||
"description": "The translated string.",
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"Theme": {
|
||||
"kind": "class",
|
||||
"constructor": {
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
{
|
||||
"module": "esm/index.js",
|
||||
"peerDependencies": {
|
||||
"@mui/material": "^6.5.0",
|
||||
"@mui/icons-material": "^6.5.0",
|
||||
"@mui/material": "^7.3.9",
|
||||
"@mui/icons-material": "^7.3.9",
|
||||
"@emotion/react": "^11.14.0",
|
||||
"@emotion/styled": "^11.14.1",
|
||||
"react": "^17.0.2 || ^18.1.0",
|
||||
|
||||
@@ -43,8 +43,8 @@
|
||||
"devDependencies": {
|
||||
"@emotion/react": "^11.14.0",
|
||||
"@emotion/styled": "^11.14.1",
|
||||
"@mui/icons-material": "^6.5.0",
|
||||
"@mui/material": "^6.5.0",
|
||||
"@mui/icons-material": "^7.3.9",
|
||||
"@mui/material": "^7.3.9",
|
||||
"@nebula.js/conversion": "^6.7.0",
|
||||
"@nebula.js/enigma-mocker": "^6.7.0",
|
||||
"@nebula.js/locale": "^6.7.0",
|
||||
@@ -52,9 +52,9 @@
|
||||
"@nebula.js/supernova": "^6.7.0",
|
||||
"@nebula.js/theme": "^6.7.0",
|
||||
"@nebula.js/ui": "^6.7.0",
|
||||
"@qlik/api": "2.4.1",
|
||||
"@scriptappy/cli": "0.10.1",
|
||||
"@scriptappy/from-jsdoc": "0.19.1",
|
||||
"@qlik/api": "2.5.0",
|
||||
"@scriptappy/cli": "0.10.4",
|
||||
"@scriptappy/from-jsdoc": "0.19.4",
|
||||
"@scriptappy/to-dts": "1.0.0",
|
||||
"extend": "3.0.2",
|
||||
"node-event-emitter": "0.0.1",
|
||||
|
||||
136
apis/stardust/types/index.d.ts
vendored
136
apis/stardust/types/index.d.ts
vendored
@@ -243,6 +243,33 @@ export namespace EnigmaMocker {
|
||||
}
|
||||
|
||||
declare namespace stardust {
|
||||
class Translator {
|
||||
constructor();
|
||||
|
||||
/**
|
||||
* Returns current locale.
|
||||
* @param lang language Locale to updated the currentLocale value
|
||||
*/
|
||||
language(lang?: string): string;
|
||||
|
||||
/**
|
||||
* Registers a string in multiple locales
|
||||
* @param item
|
||||
*/
|
||||
add(item: {
|
||||
id: string;
|
||||
locale: object;
|
||||
}): void;
|
||||
|
||||
/**
|
||||
* Translates a string for current locale.
|
||||
* @param str ID of the registered string.
|
||||
* @param args Values passed down for string interpolation.
|
||||
*/
|
||||
get(str: string, args?: string[]): string;
|
||||
|
||||
}
|
||||
|
||||
interface Component {
|
||||
key: string;
|
||||
}
|
||||
@@ -478,6 +505,47 @@ declare namespace stardust {
|
||||
|
||||
}
|
||||
|
||||
interface ActionToolbarElement extends HTMLElement{
|
||||
className: "njs-action-toolbar-popover";
|
||||
}
|
||||
|
||||
interface ActionElement extends HTMLElement{
|
||||
className: "njs-cell-action";
|
||||
}
|
||||
|
||||
interface CellElement extends HTMLElement{
|
||||
className: "njs-cell";
|
||||
}
|
||||
|
||||
interface CellBody extends HTMLElement{
|
||||
className: "njs-cell-body";
|
||||
}
|
||||
|
||||
interface CellFooter extends HTMLElement{
|
||||
className: "njs-cell-footer";
|
||||
}
|
||||
|
||||
interface CellTitle extends HTMLElement{
|
||||
className: "njs-cell-title";
|
||||
}
|
||||
|
||||
interface CellSubTitle extends HTMLElement{
|
||||
className: "njs-cell-sub-title";
|
||||
}
|
||||
|
||||
interface SheetElement extends HTMLElement{
|
||||
className: "njs-sheet";
|
||||
}
|
||||
|
||||
interface VizElementAttributes extends NamedNodeMap{
|
||||
"data-render-count": string;
|
||||
}
|
||||
|
||||
interface VizElement extends HTMLElement{
|
||||
attributes: stardust.VizElementAttributes;
|
||||
className: "njs-viz";
|
||||
}
|
||||
|
||||
interface Flags {
|
||||
/**
|
||||
* Checks whether the specified flag is enabled.
|
||||
@@ -650,47 +718,6 @@ declare namespace stardust {
|
||||
|
||||
}
|
||||
|
||||
interface ActionToolbarElement extends HTMLElement{
|
||||
className: "njs-action-toolbar-popover";
|
||||
}
|
||||
|
||||
interface ActionElement extends HTMLElement{
|
||||
className: "njs-cell-action";
|
||||
}
|
||||
|
||||
interface CellElement extends HTMLElement{
|
||||
className: "njs-cell";
|
||||
}
|
||||
|
||||
interface CellBody extends HTMLElement{
|
||||
className: "njs-cell-body";
|
||||
}
|
||||
|
||||
interface CellFooter extends HTMLElement{
|
||||
className: "njs-cell-footer";
|
||||
}
|
||||
|
||||
interface CellTitle extends HTMLElement{
|
||||
className: "njs-cell-title";
|
||||
}
|
||||
|
||||
interface CellSubTitle extends HTMLElement{
|
||||
className: "njs-cell-sub-title";
|
||||
}
|
||||
|
||||
interface SheetElement extends HTMLElement{
|
||||
className: "njs-sheet";
|
||||
}
|
||||
|
||||
interface VizElementAttributes extends NamedNodeMap{
|
||||
"data-render-count": string;
|
||||
}
|
||||
|
||||
interface VizElement extends HTMLElement{
|
||||
attributes: stardust.VizElementAttributes;
|
||||
className: "njs-viz";
|
||||
}
|
||||
|
||||
/**
|
||||
* The entry point for defining a visualization.
|
||||
*/
|
||||
@@ -837,33 +864,6 @@ declare namespace stardust {
|
||||
removed?: stardust.fieldTargetRemovedCallback<T>;
|
||||
}
|
||||
|
||||
class Translator {
|
||||
constructor();
|
||||
|
||||
/**
|
||||
* Returns current locale.
|
||||
* @param lang language Locale to updated the currentLocale value
|
||||
*/
|
||||
language(lang?: string): string;
|
||||
|
||||
/**
|
||||
* Registers a string in multiple locales
|
||||
* @param item
|
||||
*/
|
||||
add(item: {
|
||||
id: string;
|
||||
locale: object;
|
||||
}): void;
|
||||
|
||||
/**
|
||||
* Translates a string for current locale.
|
||||
* @param str ID of the registered string.
|
||||
* @param args Values passed down for string interpolation.
|
||||
*/
|
||||
get(str: string, args?: string[]): string;
|
||||
|
||||
}
|
||||
|
||||
class Theme {
|
||||
constructor();
|
||||
|
||||
|
||||
@@ -232,4 +232,43 @@ describe('JSON-Patch', () => {
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('Security - Prototype Pollution', () => {
|
||||
test('apply throws for __proto__ as the final key', () => {
|
||||
const patches = [{ op: 'add', path: '/__proto__', value: { polluted: true } }];
|
||||
expect(() => JSONPatch.apply(patchee, patches)).toThrow();
|
||||
expect({}.polluted).toBeUndefined();
|
||||
});
|
||||
|
||||
test('apply throws for constructor as the final key', () => {
|
||||
const patches = [{ op: 'add', path: '/constructor', value: { polluted: true } }];
|
||||
expect(() => JSONPatch.apply(patchee, patches)).toThrow();
|
||||
});
|
||||
|
||||
test('apply throws for prototype as the final key', () => {
|
||||
const patches = [{ op: 'add', path: '/prototype', value: { polluted: true } }];
|
||||
expect(() => JSONPatch.apply(patchee, patches)).toThrow();
|
||||
});
|
||||
|
||||
test('apply throws for __proto__ in the middle of a path', () => {
|
||||
const patches = [{ op: 'add', path: '/__proto__/polluted', value: true }];
|
||||
expect(() => JSONPatch.apply(patchee, patches)).toThrow();
|
||||
expect({}.polluted).toBeUndefined();
|
||||
});
|
||||
|
||||
test('apply throws for __proto__ in move patch from path', () => {
|
||||
const patches = [{ op: 'move', path: '/simpleString', from: '/__proto__' }];
|
||||
expect(() => JSONPatch.apply(patchee, patches)).toThrow();
|
||||
});
|
||||
|
||||
test('apply does not pollute Object.prototype via __proto__ path', () => {
|
||||
const before = Object.prototype.polluted;
|
||||
try {
|
||||
JSONPatch.apply(patchee, [{ op: 'add', path: '/__proto__', value: { polluted: true } }]);
|
||||
} catch (e) {
|
||||
// expected to throw
|
||||
}
|
||||
expect(Object.prototype.polluted).toBe(before);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -41,6 +41,18 @@ function isSpecialProperty(obj, key) {
|
||||
return isFunction(obj[key]) || key.substring(0, 2) === '$$' || key.substring(0, 1) === '_';
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether a key is safe to use as a property name to prevent
|
||||
* prototype pollution attacks.
|
||||
*
|
||||
* @private
|
||||
* @param {String} key The key to check
|
||||
* @returns {Boolean} Whether the key is safe to use
|
||||
*/
|
||||
function isSafeKey(key) {
|
||||
return key !== '__proto__' && key !== 'constructor' && key !== 'prototype';
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds the parent object from a JSON-Pointer ("/foo/bar/baz" = "bar" is "baz" parent),
|
||||
* also creates the object structure needed.
|
||||
@@ -55,9 +67,9 @@ function getParent(data, str) {
|
||||
const parts = str.substring(1).split(seperator).slice(0, -1);
|
||||
let numPart;
|
||||
|
||||
parts.forEach((part, i) => {
|
||||
if (i === parts.length) {
|
||||
return;
|
||||
parts.forEach((part) => {
|
||||
if (!isSafeKey(part)) {
|
||||
throw new Error(`Unsafe key in path: ${part}`);
|
||||
}
|
||||
numPart = +part;
|
||||
const newPart = !isNaN(numPart) ? [] : {};
|
||||
@@ -274,6 +286,11 @@ JSONPatch.apply = function apply(original, patches) {
|
||||
let target = key && isNaN(+key) ? parent[key] : parent[+key] || parent;
|
||||
const from = patch.from ? patch.from.split('/').splice(-1)[0] : null;
|
||||
|
||||
if (!isSafeKey(key) || (from !== null && !isSafeKey(from))) {
|
||||
const unsafeKey = !isSafeKey(key) ? key : from;
|
||||
throw new Error(`Unsafe key in patch path: ${unsafeKey}`);
|
||||
}
|
||||
|
||||
if (patch.path === '/') {
|
||||
parent = null;
|
||||
target = original;
|
||||
|
||||
@@ -17,8 +17,8 @@ import CSSColors from './css-colors';
|
||||
// color formats
|
||||
const rgb = /^rgb\((\d{1,3}),(\d{1,3}),(\d{1,3})\)$/i;
|
||||
const rgba = /^rgba\((\d{1,3}),(\d{1,3}),(\d{1,3}),(\d(\.\d+)?)\)$/i;
|
||||
const hex = /^#([A-f0-9]{2})([A-f0-9]{2})([A-f0-9]{2})$/i;
|
||||
const hexShort = /^#([A-f0-9])([A-f0-9])([A-f0-9])$/i;
|
||||
const hex = /^#([A-F0-9]{2})([A-F0-9]{2})([A-F0-9]{2})$/i;
|
||||
const hexShort = /^#([A-F0-9])([A-F0-9])([A-F0-9])$/i;
|
||||
const hsl = /^hsl\(\s*(\d+(\.\d+)?)\s*,\s*(\d+(\.\d+)?%?)\s*,\s*(\d+(\.\d+)?%?)\s*\)$/i;
|
||||
const hsla = /^hsla\(\s*(\d+(\.\d+)?)\s*,\s*(\d+(\.\d+)?%?)\s*,\s*(\d+(\.\d+)?%?)\s*,(\d(\.\d+)?)\)$/i;
|
||||
const { floor } = Math;
|
||||
@@ -825,11 +825,11 @@ export default class Color {
|
||||
r = parseInt(matches[1], 10);
|
||||
g = parseInt(matches[2], 10);
|
||||
b = parseInt(matches[3], 10);
|
||||
} else if ((matches = /^#([A-f0-9]{2})([A-f0-9]{2})([A-f0-9]{2})$/i.exec(colorString))) {
|
||||
} else if ((matches = /^#([A-F0-9]{2})([A-F0-9]{2})([A-F0-9]{2})$/i.exec(colorString))) {
|
||||
r = parseInt(matches[1], 16);
|
||||
g = parseInt(matches[2], 16);
|
||||
b = parseInt(matches[3], 16);
|
||||
} else if ((matches = /^#([A-f0-9])([A-f0-9])([A-f0-9])$/i.exec(colorString))) {
|
||||
} else if ((matches = /^#([A-F0-9])([A-F0-9])([A-F0-9])$/i.exec(colorString))) {
|
||||
r = parseInt(matches[1] + matches[1], 16);
|
||||
g = parseInt(matches[2] + matches[2], 16);
|
||||
b = parseInt(matches[3] + matches[3], 16);
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
"dependencies": {
|
||||
"@babel/cli": "7.28.6",
|
||||
"@babel/core": "7.29.0",
|
||||
"@babel/preset-env": "7.29.0",
|
||||
"@babel/preset-env": "7.29.2",
|
||||
"@babel/preset-react": "7.28.5",
|
||||
"@babel/preset-typescript": "7.28.5",
|
||||
"@qlik/browserslist-config": "^3.0.0",
|
||||
|
||||
@@ -30,7 +30,7 @@
|
||||
"dependencies": {
|
||||
"@babel/cli": "7.28.6",
|
||||
"@babel/core": "7.29.0",
|
||||
"@babel/preset-env": "7.29.0",
|
||||
"@babel/preset-env": "7.29.2",
|
||||
"@nebula.js/stardust": "^6.7.0",
|
||||
"@rollup/plugin-babel": "7.0.0",
|
||||
"@rollup/plugin-commonjs": "29.0.2",
|
||||
|
||||
@@ -46,28 +46,28 @@
|
||||
"extend": "3.0.2",
|
||||
"html-webpack-plugin": "5.6.6",
|
||||
"portfinder": "1.0.38",
|
||||
"puppeteer": "24.38.0",
|
||||
"puppeteer": "24.40.0",
|
||||
"regenerator-runtime": "0.14.1",
|
||||
"source-map-loader": "5.0.0",
|
||||
"webpack": "5.105.4",
|
||||
"webpack-cli": "6.0.1",
|
||||
"webpack-cli": "7.0.2",
|
||||
"webpack-dev-server": "5.2.3",
|
||||
"ws": "8.19.0",
|
||||
"yargs": "18.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/core": "7.29.0",
|
||||
"@babel/preset-env": "7.29.0",
|
||||
"@babel/preset-env": "7.29.2",
|
||||
"@babel/preset-react": "7.28.5",
|
||||
"@mui/material": "^6.5.0",
|
||||
"@mui/system": "^6.5.0",
|
||||
"@mui/material": "^7.3.9",
|
||||
"@mui/system": "^7.3.9",
|
||||
"@nebula.js/enigma-mocker": "^6.7.0",
|
||||
"@nebula.js/nucleus": "^6.7.0",
|
||||
"@nebula.js/snapshooter": "^6.7.0",
|
||||
"@nebula.js/stardust": "^6.7.0",
|
||||
"@nebula.js/ui": "^6.7.0",
|
||||
"autosuggest-highlight": "3.3.4",
|
||||
"babel-loader": "10.1.0",
|
||||
"babel-loader": "10.1.1",
|
||||
"d3-require": "1.3.0",
|
||||
"enigma.js": "2.14.0",
|
||||
"eslint-import-resolver-alias": "1.1.2",
|
||||
|
||||
36
package.json
36
package.json
@@ -39,10 +39,10 @@
|
||||
"@babel/helper-plugin-utils": "7.28.6",
|
||||
"@babel/plugin-proposal-object-rest-spread": "7.20.7",
|
||||
"@babel/plugin-transform-react-jsx": "7.28.6",
|
||||
"@babel/preset-env": "7.29.0",
|
||||
"@babel/preset-env": "7.29.2",
|
||||
"@babel/preset-react": "7.28.5",
|
||||
"@commitlint/cli": "20.4.3",
|
||||
"@commitlint/config-conventional": "20.4.3",
|
||||
"@commitlint/cli": "20.5.0",
|
||||
"@commitlint/config-conventional": "20.5.0",
|
||||
"@jest/globals": "^30.3.0",
|
||||
"@playwright/test": "1.58.2",
|
||||
"@rollup/plugin-babel": "7.0.0",
|
||||
@@ -55,7 +55,7 @@
|
||||
"@testing-library/jest-dom": "^6.9.1",
|
||||
"@testing-library/react": "^16.3.2",
|
||||
"@testing-library/user-event": "^14.6.1",
|
||||
"babel-loader": "10.1.0",
|
||||
"babel-loader": "10.1.1",
|
||||
"babel-plugin-istanbul": "7.0.1",
|
||||
"body-parser": "2.2.2",
|
||||
"cross-env": "10.1.0",
|
||||
@@ -78,13 +78,13 @@
|
||||
"jest-junit": "^16.0.0",
|
||||
"jest-location-mock": "^3.0.0",
|
||||
"jimp": "^1.6.0",
|
||||
"lerna": "9.0.5",
|
||||
"lint-staged": "^16.3.2",
|
||||
"lerna": "9.0.7",
|
||||
"lint-staged": "^16.4.0",
|
||||
"mocha-junit-reporter": "2.2.1",
|
||||
"picasso-plugin-q": "2.10.0",
|
||||
"picasso.js": "2.10.0",
|
||||
"prettier": "3.8.1",
|
||||
"puppeteer": "24.38.0",
|
||||
"puppeteer": "24.40.0",
|
||||
"qix-faker": "0.3.0",
|
||||
"react-is": "18.3.1",
|
||||
"rollup": "4.59.0",
|
||||
@@ -94,24 +94,18 @@
|
||||
"yargs": "18.0.0"
|
||||
},
|
||||
"resolutions": {
|
||||
"caniuse-lite": "1.0.30001777",
|
||||
"caniuse-lite": "1.0.30001780",
|
||||
"react": "18.3.1",
|
||||
"react-dom": "18.3.1",
|
||||
"react-is": "18.3.1",
|
||||
"@playwright/test": "1.58.2",
|
||||
"minimatch@3.x": "^3.1.5",
|
||||
"minimatch@5.x": "^5.1.9",
|
||||
"minimatch@9.x": "^9.0.7",
|
||||
"minimatch@10.x": "^10.2.4",
|
||||
"minimatch@npm:3.1.4": "^3.1.5",
|
||||
"minimatch@npm:9.0.3": "^9.0.7",
|
||||
"tar@7.x": "^7.5.11",
|
||||
"tar@npm:7.4.3": "^7.5.11",
|
||||
"tar@npm:7.5.8": "^7.5.11",
|
||||
"glob@10.x": "^10.5.0",
|
||||
"glob@11.x": "^11.1.0",
|
||||
"glob@npm:^10.2.2": "^10.5.0",
|
||||
"glob@npm:^11.0.3": "^11.1.0"
|
||||
"minimatch@npm:^3.0.0": "^3.1.5",
|
||||
"minimatch@npm:^5.0.0": "^5.1.9",
|
||||
"minimatch@npm:^9.0.0": "^9.0.7",
|
||||
"minimatch@npm:^10.0.0": "^10.2.4",
|
||||
"tar@npm:^7.0.0": "^7.5.11",
|
||||
"glob@npm:^10.0.0": "^10.5.0",
|
||||
"glob@npm:^11.0.0": "^11.1.0"
|
||||
},
|
||||
"workspaces": [
|
||||
"packages/*",
|
||||
|
||||
@@ -9,16 +9,16 @@
|
||||
"peerDependencies": {
|
||||
"@emotion/react": "^11.14.0",
|
||||
"@emotion/styled": "^11.14.1",
|
||||
"@mui/icons-material": "^6.5.0",
|
||||
"@mui/material": "^6.5.0",
|
||||
"@mui/icons-material": "^7.3.9",
|
||||
"@mui/material": "^7.3.9",
|
||||
"react": "^18.3.1",
|
||||
"react-dom": "^18.3.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@emotion/react": "^11.14.0",
|
||||
"@emotion/styled": "^11.14.1",
|
||||
"@mui/icons-material": "^6.5.0",
|
||||
"@mui/material": "^6.5.0",
|
||||
"@mui/icons-material": "^7.3.9",
|
||||
"@mui/material": "^7.3.9",
|
||||
"react": "18.3.1",
|
||||
"react-dom": "18.3.1"
|
||||
}
|
||||
|
||||
@@ -6,4 +6,8 @@ module.exports = {
|
||||
headless: true,
|
||||
},
|
||||
testDir: './test',
|
||||
reporter: [
|
||||
['html'],
|
||||
['junit', { outputFile: `./test-results/${process.env.PLAYWRIGHT_JUNIT_OUTPUT_NAME || 'junit.xml'}` }],
|
||||
],
|
||||
};
|
||||
|
||||
@@ -4,7 +4,7 @@ export default defineConfig({
|
||||
reporter: [
|
||||
['dot'],
|
||||
['html', { outputFolder: './reports/html' }],
|
||||
['junit', { outputFile: './test/mashup/reports/xml/report.xml' }],
|
||||
['junit', { outputFile: './reports/xml/report.xml' }],
|
||||
],
|
||||
testDir: './',
|
||||
globalSetup: './setup.cjs',
|
||||
|
||||
@@ -4,7 +4,7 @@ export default defineConfig({
|
||||
reporter: [
|
||||
['dot'],
|
||||
['html', { outputFolder: './reports/html' }],
|
||||
['junit', { outputFile: './test/rendering/reports/xml/report.xml' }],
|
||||
['junit', { outputFile: './reports/xml/report.xml' }],
|
||||
],
|
||||
testDir: './',
|
||||
forbidOnly: !!process.env.CI,
|
||||
|
||||
Reference in New Issue
Block a user