@imposium-hub/components 2.15.0-3 → 2.16.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/components/app-wrapper/AppWrapper.d.ts +0 -1
- package/dist/cjs/components/app-wrapper/AppWrapper.js +1 -1
- package/dist/cjs/components/app-wrapper/AppWrapper.js.map +1 -1
- package/dist/cjs/components/assets/AssetsTypeIcon.js +2 -0
- package/dist/cjs/components/assets/AssetsTypeIcon.js.map +1 -1
- package/dist/cjs/components/change-report/ChangeReportTree.js +65 -10
- package/dist/cjs/components/change-report/ChangeReportTree.js.map +1 -1
- package/dist/cjs/components/number-field/NumberField.d.ts +2 -2
- package/dist/cjs/components/number-field/NumberField.js +7 -4
- package/dist/cjs/components/number-field/NumberField.js.map +1 -1
- package/dist/cjs/components/publish-wizard/PublishWizard.js +40 -39
- package/dist/cjs/components/publish-wizard/PublishWizard.js.map +1 -1
- package/dist/cjs/constants/copy.d.ts +1 -0
- package/dist/cjs/constants/copy.js +3 -2
- package/dist/cjs/constants/copy.js.map +1 -1
- package/dist/cjs/constants/icons.d.ts +5 -0
- package/dist/cjs/constants/icons.js +12 -2
- package/dist/cjs/constants/icons.js.map +1 -1
- package/dist/cjs/constants/snippets.d.ts +2 -0
- package/dist/cjs/redux/actions/publish.d.ts +1 -1
- package/dist/cjs/redux/actions/publish.js +2 -2
- package/dist/cjs/redux/actions/publish.js.map +1 -1
- package/dist/esm/components/app-wrapper/AppWrapper.d.ts +0 -1
- package/dist/esm/components/app-wrapper/AppWrapper.js +1 -1
- package/dist/esm/components/app-wrapper/AppWrapper.js.map +1 -1
- package/dist/esm/components/assets/AssetsTypeIcon.js +2 -0
- package/dist/esm/components/assets/AssetsTypeIcon.js.map +1 -1
- package/dist/esm/components/change-report/ChangeReportTree.js +64 -10
- package/dist/esm/components/change-report/ChangeReportTree.js.map +1 -1
- package/dist/esm/components/number-field/NumberField.d.ts +2 -2
- package/dist/esm/components/number-field/NumberField.js +5 -4
- package/dist/esm/components/number-field/NumberField.js.map +1 -1
- package/dist/esm/components/publish-wizard/PublishWizard.js +40 -39
- package/dist/esm/components/publish-wizard/PublishWizard.js.map +1 -1
- package/dist/esm/constants/copy.d.ts +1 -0
- package/dist/esm/constants/copy.js +3 -2
- package/dist/esm/constants/copy.js.map +1 -1
- package/dist/esm/constants/icons.d.ts +5 -0
- package/dist/esm/constants/icons.js +10 -0
- package/dist/esm/constants/icons.js.map +1 -1
- package/dist/esm/constants/snippets.d.ts +2 -0
- package/dist/esm/redux/actions/publish.d.ts +1 -1
- package/dist/esm/redux/actions/publish.js +2 -2
- package/dist/esm/redux/actions/publish.js.map +1 -1
- package/dist/styles.css +54 -10
- package/dist/styles.less +65 -13
- package/less/components/change-report.less +50 -9
- package/less/components/publish-wizard.less +15 -4
- package/package.json +5 -1
- package/src/components/advanced-number-field/AdvancedNumberField.test.tsx +724 -0
- package/src/components/anchor-field/AnchorField.test.tsx +130 -0
- package/src/components/app-wrapper/AppWrapper.tsx +1 -6
- package/src/components/asset-details/AssetDetails.test.tsx +494 -0
- package/src/components/assets/AssetField.test.tsx +449 -0
- package/src/components/assets/AssetsTableAssetIdCell.test.tsx +142 -0
- package/src/components/assets/AssetsTableAssetIdFilter.test.tsx +95 -0
- package/src/components/assets/AssetsTableComplexTagCell.test.tsx +161 -0
- package/src/components/assets/AssetsTableDateCell.test.tsx +106 -0
- package/src/components/assets/AssetsTableDropzone.test.tsx +132 -0
- package/src/components/assets/AssetsTableDurationCell.test.tsx +119 -0
- package/src/components/assets/AssetsTableGlobalCell.test.tsx +46 -0
- package/src/components/assets/AssetsTableNameCell.test.tsx +166 -0
- package/src/components/assets/AssetsTableNameFilter.test.tsx +95 -0
- package/src/components/assets/AssetsTablePreviewCell.test.tsx +191 -0
- package/src/components/assets/AssetsTableRateCell.test.tsx +87 -0
- package/src/components/assets/AssetsTableSelectCell.test.tsx +156 -0
- package/src/components/assets/AssetsTableSelectFilter.test.tsx +119 -0
- package/src/components/assets/AssetsTableStatusCell.test.tsx +60 -0
- package/src/components/assets/AssetsTypeIcon.tsx +2 -0
- package/src/components/change-report/ChangeReportTree.tsx +104 -16
- package/src/components/number-field/NumberField.test.tsx +383 -0
- package/src/components/number-field/NumberField.tsx +15 -9
- package/src/components/publish-wizard/PublishWizard.tsx +59 -54
- package/src/components/text-field/TextField.test.tsx +988 -0
- package/src/constants/copy.ts +3 -2
- package/src/constants/icons.tsx +10 -0
- package/src/constants/snippets.ts +2 -0
- package/src/redux/actions/publish.ts +7 -2
- package/src/test/setup.ts +91 -0
- package/src/test/utils.tsx +44 -0
- package/tsconfig.eslint.json +8 -0
- package/tsconfig.json +1 -1
- package/vitest.config.ts +31 -0
- package/src/components/service-icon/ServiceIcon.test.tsx +0 -0
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
import { describe, it, expect, vi } from 'vitest';
|
|
2
|
+
import React from 'react';
|
|
3
|
+
import { render, fireEvent } from '@testing-library/react';
|
|
4
|
+
import { Provider } from 'react-redux';
|
|
5
|
+
import { legacy_createStore as createStore } from 'redux';
|
|
6
|
+
|
|
7
|
+
vi.mock('../checkbox-field/CheckboxField', () => ({
|
|
8
|
+
default: ({ label, propagate, value, onChange }: any) => (
|
|
9
|
+
<div
|
|
10
|
+
data-testid='mock-checkbox-field'
|
|
11
|
+
data-label={label}
|
|
12
|
+
data-propagate={propagate}
|
|
13
|
+
data-value={value}>
|
|
14
|
+
<input
|
|
15
|
+
type='checkbox'
|
|
16
|
+
checked={value}
|
|
17
|
+
onChange={() => onChange()}
|
|
18
|
+
/>
|
|
19
|
+
</div>
|
|
20
|
+
)
|
|
21
|
+
}));
|
|
22
|
+
|
|
23
|
+
vi.mock('../../redux/actions/selected-assets', () => ({
|
|
24
|
+
selectAll: vi.fn(() => ({ type: 'selectedAssets/SELECT_ALL' })),
|
|
25
|
+
resetSelection: vi.fn(() => ({ type: 'selectedAssets/RESET' }))
|
|
26
|
+
}));
|
|
27
|
+
|
|
28
|
+
import AssetsTableSelectFilterMemoized from './AssetsTableSelectFilter';
|
|
29
|
+
|
|
30
|
+
const createMockStore = (selectedAssets: string[] = []) => {
|
|
31
|
+
const initialState = { selectedAssets };
|
|
32
|
+
return createStore((state: any = initialState, action: any) => {
|
|
33
|
+
switch (action.type) {
|
|
34
|
+
case 'selectedAssets/SELECT_ALL':
|
|
35
|
+
return {
|
|
36
|
+
...state,
|
|
37
|
+
selectedAssets: ['asset-1', 'asset-2', 'asset-3']
|
|
38
|
+
};
|
|
39
|
+
case 'selectedAssets/RESET':
|
|
40
|
+
return {
|
|
41
|
+
...state,
|
|
42
|
+
selectedAssets: []
|
|
43
|
+
};
|
|
44
|
+
default:
|
|
45
|
+
return state;
|
|
46
|
+
}
|
|
47
|
+
});
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
const renderComponent = (selectedAssets: string[] = []) => {
|
|
51
|
+
const store = createMockStore(selectedAssets);
|
|
52
|
+
|
|
53
|
+
const result = render(
|
|
54
|
+
<Provider store={store}>
|
|
55
|
+
<AssetsTableSelectFilterMemoized />
|
|
56
|
+
</Provider>
|
|
57
|
+
);
|
|
58
|
+
|
|
59
|
+
return { ...result, store };
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
describe('AssetsTableSelectFilter', () => {
|
|
63
|
+
it('renders CheckboxField with correct props when no assets are selected', () => {
|
|
64
|
+
const { getByTestId } = renderComponent();
|
|
65
|
+
const checkbox = getByTestId('mock-checkbox-field');
|
|
66
|
+
|
|
67
|
+
expect(checkbox.getAttribute('data-label')).toBe('');
|
|
68
|
+
expect(checkbox.getAttribute('data-propagate')).toBe('false');
|
|
69
|
+
expect(checkbox.getAttribute('data-value')).toBe('false');
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
it('renders CheckboxField as checked when assets are selected', () => {
|
|
73
|
+
const { getByTestId } = renderComponent(['asset-1', 'asset-2']);
|
|
74
|
+
const checkbox = getByTestId('mock-checkbox-field');
|
|
75
|
+
|
|
76
|
+
expect(checkbox.getAttribute('data-value')).toBe('true');
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
it('dispatches selectAll when checkbox is clicked and no assets are selected', () => {
|
|
80
|
+
const { getByRole, store } = renderComponent();
|
|
81
|
+
const checkboxInput = getByRole('checkbox');
|
|
82
|
+
|
|
83
|
+
fireEvent.click(checkboxInput);
|
|
84
|
+
|
|
85
|
+
const storeState = store.getState();
|
|
86
|
+
expect(storeState.selectedAssets).toEqual(['asset-1', 'asset-2', 'asset-3']);
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
it('dispatches resetSelection when checkbox is clicked and assets are selected', () => {
|
|
90
|
+
const { getByRole, store } = renderComponent(['asset-1', 'asset-2']);
|
|
91
|
+
const checkboxInput = getByRole('checkbox');
|
|
92
|
+
|
|
93
|
+
fireEvent.click(checkboxInput);
|
|
94
|
+
|
|
95
|
+
const storeState = store.getState();
|
|
96
|
+
expect(storeState.selectedAssets).toEqual([]);
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
it('shows unchecked state when selectedAssets array is empty', () => {
|
|
100
|
+
const { getByTestId } = renderComponent([]);
|
|
101
|
+
const checkbox = getByTestId('mock-checkbox-field');
|
|
102
|
+
|
|
103
|
+
expect(checkbox.getAttribute('data-value')).toBe('false');
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
it('shows checked state when selectedAssets array has one item', () => {
|
|
107
|
+
const { getByTestId } = renderComponent(['single-asset']);
|
|
108
|
+
const checkbox = getByTestId('mock-checkbox-field');
|
|
109
|
+
|
|
110
|
+
expect(checkbox.getAttribute('data-value')).toBe('true');
|
|
111
|
+
});
|
|
112
|
+
|
|
113
|
+
it('shows checked state when selectedAssets array has multiple items', () => {
|
|
114
|
+
const { getByTestId } = renderComponent(['asset-1', 'asset-2', 'asset-3']);
|
|
115
|
+
const checkbox = getByTestId('mock-checkbox-field');
|
|
116
|
+
|
|
117
|
+
expect(checkbox.getAttribute('data-value')).toBe('true');
|
|
118
|
+
});
|
|
119
|
+
});
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { describe, it, expect } from 'vitest';
|
|
2
|
+
import React from 'react';
|
|
3
|
+
import { render } from '@testing-library/react';
|
|
4
|
+
import AssetsTableStatusCellMemoized from './AssetsTableStatusCell';
|
|
5
|
+
|
|
6
|
+
const buildCellProp = (overrides: Record<string, any> = {}) => ({
|
|
7
|
+
row: {
|
|
8
|
+
original: {
|
|
9
|
+
processing: false,
|
|
10
|
+
...overrides
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
const renderComponent = (overrides: Record<string, any> = {}) => {
|
|
16
|
+
return render(<AssetsTableStatusCellMemoized cell={buildCellProp(overrides)} />);
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
describe('AssetsTableStatusCell', () => {
|
|
20
|
+
it('renders with complete status when processing is false', () => {
|
|
21
|
+
const { container } = renderComponent({ processing: false });
|
|
22
|
+
const statusCell = container.querySelector('.asset-status-cell');
|
|
23
|
+
const statusIndicator = container.querySelector('.status-indicator');
|
|
24
|
+
|
|
25
|
+
expect(statusCell).toBeTruthy();
|
|
26
|
+
expect(statusIndicator?.className).toBe('status-indicator complete');
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
it('renders with processing status when processing is true', () => {
|
|
30
|
+
const { container } = renderComponent({ processing: true });
|
|
31
|
+
const statusIndicator = container.querySelector('.status-indicator');
|
|
32
|
+
|
|
33
|
+
expect(statusIndicator?.className).toBe('status-indicator processing');
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
it('renders with complete status when processing is undefined', () => {
|
|
37
|
+
const { container } = renderComponent({ processing: undefined });
|
|
38
|
+
const statusIndicator = container.querySelector('.status-indicator');
|
|
39
|
+
|
|
40
|
+
expect(statusIndicator?.className).toBe('status-indicator complete');
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
it('renders with complete status when processing is null', () => {
|
|
44
|
+
const { container } = renderComponent({ processing: null });
|
|
45
|
+
const statusIndicator = container.querySelector('.status-indicator');
|
|
46
|
+
|
|
47
|
+
expect(statusIndicator?.className).toBe('status-indicator complete');
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
it('renders the correct DOM structure', () => {
|
|
51
|
+
const { container } = renderComponent();
|
|
52
|
+
const statusCell = container.querySelector('.asset-status-cell');
|
|
53
|
+
const statusIndicator = statusCell?.querySelector('.status-indicator');
|
|
54
|
+
|
|
55
|
+
expect(statusCell).toBeTruthy();
|
|
56
|
+
expect(statusIndicator).toBeTruthy();
|
|
57
|
+
expect(statusCell?.children).toHaveLength(1);
|
|
58
|
+
expect(statusCell?.firstChild).toEqual(statusIndicator);
|
|
59
|
+
});
|
|
60
|
+
});
|
|
@@ -1,6 +1,54 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
2
|
import { IChangeReportNode, IChangeReportSection } from '../../constants/snippets';
|
|
3
3
|
import * as copy from '../../constants/copy';
|
|
4
|
+
import {
|
|
5
|
+
ICON_IMAGE,
|
|
6
|
+
ICON_VIDEO,
|
|
7
|
+
ICON_LAYER_GROUP,
|
|
8
|
+
ICON_CODE,
|
|
9
|
+
ICON_FILE_ARCHIVE,
|
|
10
|
+
ICON_IMAGE_SEQ_TYPE,
|
|
11
|
+
ICON_FONT,
|
|
12
|
+
ICON_AUDIO_TYPE,
|
|
13
|
+
ICON_HASHTAG,
|
|
14
|
+
ICON_TOGGLE_ON,
|
|
15
|
+
ICON_BARS,
|
|
16
|
+
ICON_PALETTE,
|
|
17
|
+
ICON_QRCODE
|
|
18
|
+
} from '../../constants/icons';
|
|
19
|
+
|
|
20
|
+
const TYPE_ICONS: Record<string, React.ReactNode> = {
|
|
21
|
+
// Layer types
|
|
22
|
+
image: ICON_IMAGE,
|
|
23
|
+
video: ICON_VIDEO,
|
|
24
|
+
video_composition: ICON_LAYER_GROUP,
|
|
25
|
+
html: ICON_CODE,
|
|
26
|
+
template: ICON_FILE_ARCHIVE,
|
|
27
|
+
image_sequence: ICON_IMAGE_SEQ_TYPE,
|
|
28
|
+
text: ICON_FONT,
|
|
29
|
+
audio: ICON_AUDIO_TYPE,
|
|
30
|
+
solid: ICON_IMAGE,
|
|
31
|
+
after_effects: ICON_VIDEO,
|
|
32
|
+
// Variable types (matches getVariableIcon in Story Editor)
|
|
33
|
+
number: ICON_HASHTAG,
|
|
34
|
+
boolean: ICON_TOGGLE_ON,
|
|
35
|
+
enum: ICON_BARS,
|
|
36
|
+
color: ICON_PALETTE,
|
|
37
|
+
qr_code: ICON_QRCODE
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
const TYPE_COLORS: Record<string, string> = {
|
|
41
|
+
video: 'rgba(236, 22, 150, 1)',
|
|
42
|
+
image: 'rgba(241, 191, 21, 1)',
|
|
43
|
+
audio: 'rgba(72, 177, 222, 1)',
|
|
44
|
+
template: 'rgba(208, 80, 35, 1)',
|
|
45
|
+
video_composition: 'rgba(215, 22, 22, 1)',
|
|
46
|
+
text: 'rgba(71, 212, 125, 1)',
|
|
47
|
+
image_sequence: 'rgba(241, 191, 21, 1)',
|
|
48
|
+
html: '#ae6cff',
|
|
49
|
+
solid: '#AAAAAA',
|
|
50
|
+
after_effects: 'rgba(236, 22, 150, 1)'
|
|
51
|
+
};
|
|
4
52
|
|
|
5
53
|
interface IChangeReportTreeProps {
|
|
6
54
|
sections: IChangeReportSection[] | null;
|
|
@@ -15,6 +63,33 @@ interface IChangeReportNodeProps {
|
|
|
15
63
|
depth: number;
|
|
16
64
|
}
|
|
17
65
|
|
|
66
|
+
const isColorValue = (val: string): boolean => {
|
|
67
|
+
if (!val) return false;
|
|
68
|
+
return /^#[0-9a-fA-F]{3,8}$/.test(val) || /^rgba?\(/.test(val);
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
const ValueDisplay: React.FC<{ value: string }> = ({ value }) => {
|
|
72
|
+
if (value === '*default*' || value === '*empty*') {
|
|
73
|
+
// Check if this could be a transparent/default color
|
|
74
|
+
return <>{value}</>;
|
|
75
|
+
}
|
|
76
|
+
if (isColorValue(value)) {
|
|
77
|
+
return (
|
|
78
|
+
<>
|
|
79
|
+
<span className='change-report-color-chip-wrapper'>
|
|
80
|
+
<span className='change-report-color-chip-checkerboard' />
|
|
81
|
+
<span
|
|
82
|
+
className='change-report-color-chip-color'
|
|
83
|
+
style={{ backgroundColor: value }}
|
|
84
|
+
/>
|
|
85
|
+
</span>
|
|
86
|
+
{value}
|
|
87
|
+
</>
|
|
88
|
+
);
|
|
89
|
+
}
|
|
90
|
+
return <>{value}</>;
|
|
91
|
+
};
|
|
92
|
+
|
|
18
93
|
const STATUS_LABELS: Record<IChangeReportNode['status'], string> = {
|
|
19
94
|
added: copy.publish.statusAdded,
|
|
20
95
|
removed: copy.publish.statusRemoved,
|
|
@@ -25,16 +100,12 @@ const ChangeReportNode: React.FC<IChangeReportNodeProps> = ({ node, defaultExpan
|
|
|
25
100
|
const [expanded, setExpanded] = React.useState(defaultExpanded);
|
|
26
101
|
|
|
27
102
|
const hasChildren = node.children && node.children.length > 0;
|
|
28
|
-
const
|
|
103
|
+
const hasOldValue = node.oldValue !== undefined && node.oldValue !== null;
|
|
104
|
+
const hasNewValue = node.newValue !== undefined && node.newValue !== null;
|
|
105
|
+
const hasValues = hasOldValue || hasNewValue;
|
|
29
106
|
|
|
30
|
-
const oldDisplay =
|
|
31
|
-
|
|
32
|
-
? '*empty*'
|
|
33
|
-
: node.oldValue;
|
|
34
|
-
const newDisplay =
|
|
35
|
-
node.newValue === null || node.newValue === '' || node.newValue === undefined
|
|
36
|
-
? '*empty*'
|
|
37
|
-
: node.newValue;
|
|
107
|
+
const oldDisplay = !hasOldValue || node.oldValue === '' ? '*empty*' : node.oldValue;
|
|
108
|
+
const newDisplay = !hasNewValue || node.newValue === '' ? '*empty*' : node.newValue;
|
|
38
109
|
|
|
39
110
|
return (
|
|
40
111
|
<div
|
|
@@ -54,16 +125,33 @@ const ChangeReportNode: React.FC<IChangeReportNodeProps> = ({ node, defaultExpan
|
|
|
54
125
|
<span className={`change-report-status change-report-status--${node.status}`}>
|
|
55
126
|
{STATUS_LABELS[node.status]}
|
|
56
127
|
</span>
|
|
128
|
+
{(node.layerType || node.varType) && TYPE_ICONS[node.layerType || node.varType] && (
|
|
129
|
+
<span
|
|
130
|
+
className='change-report-layer-icon'
|
|
131
|
+
style={
|
|
132
|
+
TYPE_COLORS[node.layerType || node.varType]
|
|
133
|
+
? { color: TYPE_COLORS[node.layerType || node.varType] }
|
|
134
|
+
: undefined
|
|
135
|
+
}>
|
|
136
|
+
{TYPE_ICONS[node.layerType || node.varType]}
|
|
137
|
+
</span>
|
|
138
|
+
)}
|
|
57
139
|
<span className='change-report-label'>{node.label}</span>
|
|
58
140
|
{hasValues && (
|
|
59
141
|
<span className='change-report-values'>
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
142
|
+
{hasOldValue && (
|
|
143
|
+
<span className='change-report-value change-report-value--old'>
|
|
144
|
+
<ValueDisplay value={oldDisplay} />
|
|
145
|
+
</span>
|
|
146
|
+
)}
|
|
147
|
+
{hasOldValue && hasNewValue && (
|
|
148
|
+
<span className='change-report-value-arrow'>→</span>
|
|
149
|
+
)}
|
|
150
|
+
{hasNewValue && (
|
|
151
|
+
<span className='change-report-value change-report-value--new'>
|
|
152
|
+
<ValueDisplay value={newDisplay} />
|
|
153
|
+
</span>
|
|
154
|
+
)}
|
|
67
155
|
</span>
|
|
68
156
|
)}
|
|
69
157
|
</div>
|