Skip to content

Commit

Permalink
feat: add error markers to groups
Browse files Browse the repository at this point in the history
  • Loading branch information
marstamm committed Jul 12, 2023
1 parent 03827f1 commit d38815d
Show file tree
Hide file tree
Showing 7 changed files with 196 additions and 41 deletions.
9 changes: 9 additions & 0 deletions assets/properties-panel.css
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@
--arrow-hover-background-color: var(--color-grey-225-10-95);

--dot-color: var(--color-grey-225-10-35);
--dot-color-error: var(--color-red-360-100-45);

--list-badge-color: var(--color-white);
--list-badge-background-color: var(--color-grey-225-10-35);
Expand Down Expand Up @@ -355,6 +356,10 @@
background-color: var(--dot-color);
}

.bio-properties-panel-dot.error {
background-color: var(--dot-color-error);
}

/**
* Lists
*/
Expand Down Expand Up @@ -382,6 +387,10 @@
background-color: var(--list-badge-background-color);
}

.bio-properties-panel-list-badge.error {
background-color: var(--dot-color-error);
}

/**
* Basic entries
*/
Expand Down
35 changes: 29 additions & 6 deletions src/components/Group.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import {
} from 'min-dash';

import {
useErrors,
useLayoutState
} from '../hooks';

Expand Down Expand Up @@ -75,6 +76,10 @@ export default function Group(props) {
setEdited(hasOneEditedEntry);
}, [ entries ]);

// set error state depending on all entries
const allErrors = useErrors();
const hasErrors = entries.some(entry => allErrors[entry.id]);

// set css class when group is sticky to top
useStickyIntersectionObserver(groupRef, 'div.bio-properties-panel-scroll-container', setSticky);

Expand All @@ -88,14 +93,18 @@ export default function Group(props) {
'bio-properties-panel-group-header',
edited ? '' : 'empty',
open ? 'open' : '',
(sticky && open) ? 'sticky' : ''
(sticky && open) ? 'sticky' : '',
hasErrors ? 'error' : ''
) } onClick={ toggleOpen }>
<div title={ label } class="bio-properties-panel-group-header-title">
{ label }
</div>
<div class="bio-properties-panel-group-header-buttons">
{
edited && <DataMarker />
<DataMarker
edited={ edited }
hasErrors={ hasErrors }
/>
}
<button
title="Toggle section"
Expand Down Expand Up @@ -130,8 +139,22 @@ export default function Group(props) {
</div>;
}

function DataMarker() {
return (
<div title="Section contains data" class="bio-properties-panel-dot"></div>
);
function DataMarker(props) {
const {
edited,
hasErrors
} = props;

if (hasErrors) {
return (
<div title="Section contains an error" class="bio-properties-panel-dot error"></div>
);
}

if (edited) {
return (
<div title="Section contains data" class="bio-properties-panel-dot"></div>
);
}
return null;
}
26 changes: 24 additions & 2 deletions src/components/ListGroup.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import {
} from 'min-dash';

import {
useErrors,
useLayoutState,
usePrevious
} from '../hooks';
Expand Down Expand Up @@ -170,13 +171,29 @@ export default function ListGroup(props) {
add(e);
};

const allErrors = useErrors();
const hasError = items.some(item => {
if (allErrors[item.id]) {
return true;
}

if (!item.entries) {
return;
}

// also check if the error is nested, e.g. for name-value entries
return item.entries.some(entry => allErrors[entry.id]);
}
);

return <div class="bio-properties-panel-group" data-group-id={ 'group-' + id } ref={ groupRef }>
<div
class={ classnames(
'bio-properties-panel-group-header',
hasItems ? '' : 'empty',
(hasItems && open) ? 'open' : '',
(sticky && open) ? 'sticky' : ''
(sticky && open) ? 'sticky' : '',
hasError ? 'error' : ''
) }
onClick={ hasItems ? toggleOpen : noop }>
<div
Expand Down Expand Up @@ -210,7 +227,12 @@ export default function ListGroup(props) {
? (
<div
title={ `List contains ${items.length} item${items.length != 1 ? 's' : ''}` }
class="bio-properties-panel-list-badge"
class={
classnames(
'bio-properties-panel-list-badge',
hasError ? 'error' : ''
)
}
>
{ items.length }
</div>
Expand Down
2 changes: 1 addition & 1 deletion src/hooks/index.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
export { useDescriptionContext } from './useDescriptionContext';
export { useError } from './useError';
export { useError, useErrors } from './useError';
export { useEvent } from './useEvent';
export { useKeyFactory } from './useKeyFactory';
export { useLayoutState } from './useLayoutState';
Expand Down
6 changes: 6 additions & 0 deletions src/hooks/useError.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,9 @@ export function useError(id) {

return errors[ id ];
}

export function useErrors() {
const { errors } = useContext(ErrorsContext);

return errors;
}
34 changes: 29 additions & 5 deletions test/spec/components/Group.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,10 @@ import {

import Group from 'src/components/Group';

import { PropertiesPanelContext } from 'src/context';
import {
PropertiesPanelContext,
ErrorsContext
} from 'src/context';
import { fireEvent } from '@testing-library/preact';
import { act } from 'preact/test-utils';

Expand Down Expand Up @@ -218,6 +221,24 @@ describe('<Group>', function() {
expect(dataMarker).to.exist;
});


it('should show error marker', function() {

// given
const entries = createEntries();
const errors = { 'entry-1': 'message' };

// when
const result = createGroup({ container, label: 'Group', entries, errors });

const header = domQuery('.bio-properties-panel-group-header', result.container);

const errorMarker = domQuery('.bio-properties-panel-dot.error', header);

// then
expect(errorMarker).to.exist;
});

});


Expand Down Expand Up @@ -305,14 +326,17 @@ function createEntries(options = {}) {

function createGroup(options = {}) {
const {
container
container,
errors = {}
} = options;


return render(
<MockLayout>
<Group id="Example" { ...options } />
</MockLayout>,
<ErrorsContext.Provider value={ { errors } }>
<MockLayout>
<Group id="Example" { ...options } />
</MockLayout>
</ErrorsContext.Provider>,
{
container
}
Expand Down
125 changes: 98 additions & 27 deletions test/spec/components/ListGroup.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import {
import ListGroup from 'src/components/ListGroup';

import { PropertiesPanelContext, LayoutContext } from 'src/context';
import { ErrorsContext } from '../../../src/context';

insertCoreStyles();

Expand Down Expand Up @@ -53,27 +54,92 @@ describe('<ListGroup>', function() {
});


it('should render item count', function() {
describe('header', function() {

// given
const items = [
{
id: 'item-1',
label: 'Item 1'
},
{
id: 'item-2',
label: 'Item 2'
}
];
it('should render item count', function() {

const { container } = createListGroup({ container: parentContainer, items });
// given
const items = [
{
id: 'item-1',
label: 'Item 1'
},
{
id: 'item-2',
label: 'Item 2'
}
];

const listBadge = domQuery('.bio-properties-panel-list-badge', container);
const { container } = createListGroup({ container: parentContainer, items });

const listBadge = domQuery('.bio-properties-panel-list-badge', container);

// then
expect(listBadge).to.exist;
expect(listBadge.innerText).to.eql('2');
});


it('should indicate error', function() {

// given
const items = [
{
id: 'item-1',
label: 'Item 1'
},
{
id: 'item-2',
label: 'Item 2'
}
];

const errors = {
'item-1': 'foo'
};

const { container } = createListGroup({ container: parentContainer, items, errors });

const errorBadge = domQuery('.bio-properties-panel-list-badge.error', container);

// then
expect(errorBadge).to.exist;
expect(errorBadge.innerText).to.eql('2');
});


it('should indicate error in nested entry', function() {

// given
const items = [
{
id: 'item-1',
label: 'Item 1',
entries: [
{
id: 'entry-1'
}
]
},
{
id: 'item-2',
label: 'Item 2'
}
];

const errors = {
'entry-1': 'foo'
};

const { container } = createListGroup({ container: parentContainer, items, errors });

const errorBadge = domQuery('.bio-properties-panel-list-badge.error', container);

// then
expect(errorBadge).to.exist;
expect(errorBadge.innerText).to.eql('2');
});

// then
expect(listBadge).to.exist;
expect(listBadge.innerText).to.eql('2');
});


Expand Down Expand Up @@ -1247,6 +1313,7 @@ describe('<ListGroup>', function() {
function TestGroup(props) {
const {
element = noopElement,
errors = {},
id = 'sampleId',
label = 'List',
items = [],
Expand All @@ -1256,22 +1323,25 @@ function TestGroup(props) {
} = props;

return (
<MockLayout>
<ListGroup
element={ element }
id={ id }
label={ label }
items={ items }
add={ add }
shouldSort={ shouldSort }
shouldOpen={ shouldOpen } />
</MockLayout>
<ErrorsContext.Provider value={ { errors } }>
<MockLayout>
<ListGroup
element={ element }
id={ id }
label={ label }
items={ items }
add={ add }
shouldSort={ shouldSort }
shouldOpen={ shouldOpen } />
</MockLayout>
</ErrorsContext.Provider>
);
}

function createListGroup(options = {}, renderFn = render) {
const {
element = noopElement,
errors,
id = 'sampleId',
label = 'List',
items = [],
Expand All @@ -1284,6 +1354,7 @@ function createListGroup(options = {}, renderFn = render) {
return renderFn(
<TestGroup
element={ element }
errors={ errors }
id={ id }
label={ label }
items={ items }
Expand Down

0 comments on commit d38815d

Please sign in to comment.