Skip to content

Commit

Permalink
fix: various bug fixes (#269)
Browse files Browse the repository at this point in the history
* feat: collection field can be edited properly WIP

* feat: added dropdown for collections WIP

* feat: added dropdown for licenses WIP

* test: added tests WIP

* test: upped coverage in components package WIP

* test: updated coverage for manage

* fix: removed old form field

* feat: changed input to textarea for descriptions

* fix: fixed broken styling on form element icons

* fix: added default values for required fields

* fix: selected item now changes with scroll

* fix: only show validation results for dirty form elements

* fix: typo

* fix: fixed styling for search bar
  • Loading branch information
lem-onade authored Jun 4, 2021
1 parent 215970d commit c4326b1
Show file tree
Hide file tree
Showing 12 changed files with 209 additions and 128 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,22 @@ describe('FormElementComponent', () => {

});

it('should allow slotted textarea field', async () => {

component.field = 'description';
const select = window.document.createElement('textarea');
select.slot = 'input';
select.innerText = 'test description';
component.appendChild(select);
component.removeChild(input);

window.document.body.appendChild(component);
await component.updateComplete;

expect((window.document.body.getElementsByTagName('nde-form-element')[0].shadowRoot.querySelector<HTMLSlotElement>('.field slot').assignedElements()[0] as HTMLSelectElement).innerText).toEqual(select.innerText);

});

it('should send SUBMITTED event when enter keypress', async (done) => {

machine.onEvent(((event) => {
Expand Down
15 changes: 13 additions & 2 deletions packages/solid-crs-components/lib/forms/form-element.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -176,7 +176,9 @@ export class FormElementComponent<T> extends RxLitElement {
}

this.inputs = slot.assignedNodes({ flatten: true })?.filter(
(element) => element instanceof HTMLInputElement || element instanceof HTMLSelectElement
(element) => element instanceof HTMLInputElement ||
element instanceof HTMLSelectElement ||
element instanceof HTMLTextAreaElement
).map((element) => element as HTMLInputElement);

this.inputs?.forEach((element) => {
Expand Down Expand Up @@ -303,11 +305,20 @@ export class FormElementComponent<T> extends RxLitElement {
flex: 1 0;
border: var(--border-normal) solid var(--colors-foreground-normal);
}
.form-element .content .field ::slotted(input), .form-element .content .field ::slotted(select) {
.form-element .content .field ::slotted(*) {
padding: 0 var(--gap-normal);
flex: 1 0;
height: 44px;
}
.form-element .content .field ::slotted(input),
.form-element .content .field ::slotted(select),
.form-element .content .field ::slotted(textarea) {
box-sizing: border-box;
}
.form-element .content .field ::slotted(textarea) {
padding: var(--gap-normal);
height: 132px;
}
.form-element .content .field .icon {
height: 100%;
display: flex;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,9 @@ export class SidebarItemComponent extends RxLitElement {
div.content-container {
height: 100%;
}
div.content-container.border {
height: auto;
}
.border {
border-bottom: 1px solid var(--colors-primary-normal);
}
Expand Down
2 changes: 1 addition & 1 deletion packages/solid-crs-components/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@
],
"coverageThreshold": {
"global": {
"branches": 89.57,
"branches": 89.66,
"functions": 96.97,
"lines": 100,
"statements": 99.11
Expand Down
1 change: 1 addition & 0 deletions packages/solid-crs-manage/lib/app-root.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ export class AppRootComponent extends RxLitElement {
description: this.translator.translate('nde.features.object.new-object-description'),
collection: undefined,
type: 'http://schema.org/CreativeWork',
identifier: this.translator.translate('nde.features.object.new-object-name').toLowerCase().replace(' ', '-'),
image: 'https://images.unsplash.com/photo-1615390164801-cf2e70f32b53?ixid=MnwxMjA3fDB8MHxwcm9maWxlLXBhZ2V8M3x8fGVufDB8fHx8&ixlib=rb-1.2.1&w=1000&q=80',
}
)).withContext({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ export class ObjectIdentificationComponent extends RxLitElement {
</nde-form-element>
<nde-form-element .actor="${this.formActor}" .translator="${this.translator}" field="description">
<label slot="label" for="description">${this.translator?.translate('nde.features.object.card.identification.field.description')}</label>
<input type="text" slot="input" name="description"/>
<textarea type="text" slot="input" name="description"/></textarea>
</nde-form-element>
<nde-form-element .actor="${this.formActor}" .translator="${this.translator}" field="collection">
<label slot="label" for="collection">${this.translator?.translate('nde.features.object.card.identification.field.collection')}</label>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { Alert } from '@netwerk-digitaal-erfgoed/solid-crs-components';
import { ArgumentError, CollectionObjectMemoryStore, ConsoleLogger, LoggerLevel, MemoryTranslator, Collection, CollectionObject, CollectionMemoryStore } from '@netwerk-digitaal-erfgoed/solid-crs-core';
import { interpret, Interpreter } from 'xstate';
import { AppEvents } from '../../app.events';
import { AppEvents, DismissAlertEvent } from '../../app.events';
import { appMachine } from '../../app.machine';
import { SolidMockService } from '../../common/solid/solid-mock.service';
import { ObjectRootComponent } from './object-root.component';
Expand Down Expand Up @@ -36,7 +36,7 @@ describe('ObjectRootComponent', () => {
image: null,
subject: null,
type: null,
updated: 0,
updated: '0',
collection: 'collection-uri-1',
};

Expand All @@ -51,21 +51,30 @@ describe('ObjectRootComponent', () => {
machine = interpret(objectMachine(objectStore)
.withContext({
object: object1,
collections: [ collection1, collection2 ],
}));

machine.parent = interpret(appMachine(
new SolidMockService(new ConsoleLogger(LoggerLevel.silly, LoggerLevel.silly)),
collectionStore,
objectStore,
{},
));
{ ...collection1 },
{ ...object1 },
).withContext({
collections: [ collection1, collection2 ],
alerts: [],
}));

component = window.document.createElement('nde-object-root') as ObjectRootComponent;

component.actor = machine;

component.translator = new MemoryTranslator([], 'nl-NL');

component.object = object1;

component.collections = [ collection1, collection2 ];

});

afterEach(() => {
Expand Down Expand Up @@ -99,7 +108,7 @@ describe('ObjectRootComponent', () => {
const alerts = window.document.body.getElementsByTagName('nde-object-root')[0].shadowRoot.querySelectorAll('nde-alert');

expect(alerts).toBeTruthy();
expect(alerts.length).toBe(0);
expect(alerts.length).toBe(1);

});

Expand Down Expand Up @@ -237,69 +246,49 @@ describe('ObjectRootComponent', () => {

});

it('should send event when edit is clicked', async () => {
it('should only show save and cancel buttons when form is dirty', async () => {

machine.start();
machine.send(ObjectEvents.SELECTED_OBJECT, { object: collection1 });

window.document.body.appendChild(component);
await component.updateComplete;

machine.onTransition((state) => {

if(state.matches(ObjectStates.IDLE) && state.context?.object) {

machine.send = jest.fn();

const button = window.document.body.getElementsByTagName('nde-object-root')[0].shadowRoot.querySelector('.edit') as HTMLElement;
const save = window.document.body.getElementsByTagName('nde-object-root')[0].shadowRoot.querySelector('.save') as HTMLElement;
const cancel = window.document.body.getElementsByTagName('nde-object-root')[0].shadowRoot.querySelector('.cancel') as HTMLElement;

if(button) {
expect(save).toBeFalsy();
expect(cancel).toBeFalsy();

button.click();
});

expect(machine.send).toHaveBeenCalledTimes(1);
it('should select sidebar item when content is scrolled', async () => {

}
window.document.body.appendChild(component);
await component.updateComplete;

}
const content = window.document.body.getElementsByTagName('nde-object-root')[0].shadowRoot.querySelector('.content') as HTMLElement;
content.dispatchEvent(new CustomEvent('scroll'));

});
expect(component.visibleCard).toBeTruthy();

});

// it('should hide save and cancel buttons and show delete button when not editing', async () => {
describe('updateSelected()', () => {

// machine.start();
// (component as any).state = { matches: jest.fn().mockReturnValueOnce(false) };
// window.document.body.appendChild(component);
// await component.updateComplete;
it('should set this.visibleCard to the currently visible card', async () => {

// const root = window.document.body.querySelector('nde-object-root').shadowRoot;
// expect(root).toBeTruthy();
// const contentHeader = root.querySelector('nde-content-header');
// expect(contentHeader).toBeTruthy();
// expect(contentHeader.querySelector('.save')).toBeFalsy();
// expect(contentHeader.querySelector('.cancel')).toBeFalsy();
// expect(contentHeader.querySelector('.delete')).toBeTruthy();

// });
window.document.body.appendChild(component);
await component.updateComplete;

// it('should show save, cancel and delete buttons when editing', async () => {
component.updateSelected();
await component.updateComplete;

// machine.start();
// (component as any).state = { matches: jest.fn().mockReturnValueOnce(true) };
// window.document.body.appendChild(component);
// await component.updateComplete;
expect(component.visibleCard).toBeTruthy();
expect(component.visibleCard).toEqual(component.formCards[0].id);

// const root = window.document.body.querySelector('nde-object-root').shadowRoot;
// expect(root).toBeTruthy();
// const contentHeader = root.querySelector('nde-content-header');
// expect(contentHeader).toBeTruthy();
// expect(contentHeader.querySelector('.save')).toBeTruthy();
// expect(contentHeader.querySelector('.cancel')).toBeTruthy();
// expect(contentHeader.querySelector('.delete')).toBeTruthy();
});

// });
});

describe('handleDismiss', () => {

Expand Down Expand Up @@ -337,7 +326,7 @@ describe('ObjectRootComponent', () => {

if(event && event.type === AppEvents.DISMISS_ALERT) {

expect(event.alert).toEqual(alert);
expect((event as DismissAlertEvent).alert).toEqual(alert);
done();

}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,12 @@ export class ObjectRootComponent extends RxLitElement {
* The form cards in this component
*/
@queryAll('.form-card')
private formCards: RxLitElement[];
formCards: RxLitElement[];
/**
* The id of the currently visible form card
*/
@internalProperty()
visibleCard: string;
/**
* The component's logger.
*/
Expand Down Expand Up @@ -142,6 +147,12 @@ export class ObjectRootComponent extends RxLitElement {

}

if (this.formCards?.length > 0 && !this.visibleCard) {

this.visibleCard = this.formCards[0].id;

}

}

/**
Expand All @@ -167,6 +178,21 @@ export class ObjectRootComponent extends RxLitElement {

}

/**
* Sets this.selected to the currently visible form card's id
*/
updateSelected = (): void => {

this.visibleCard = Array.from(this.formCards).find((formCard) => {

const box = formCard.getBoundingClientRect();

return box.top > -(box.height / 3);

})?.id;

};

/**
* Renders the component as HTML.
*
Expand Down Expand Up @@ -204,7 +230,7 @@ export class ObjectRootComponent extends RxLitElement {
<nde-sidebar-list slot="content">
${sidebarItems.map((item) => html`
<nde-sidebar-list-item slot="item"
?selected="${ false }"
?selected="${ item === this.visibleCard }"
@click="${() => { Array.from(this.formCards).find((card) => card.id === item).scrollIntoView({ behavior: 'smooth', block: 'center' }); }}"
>
<div slot="title">${this.translator?.translate(item)}</div>
Expand All @@ -214,7 +240,7 @@ export class ObjectRootComponent extends RxLitElement {
</nde-sidebar-item>
</nde-sidebar>
<div class="content">
<div class="content" @scroll="${ () => window.requestAnimationFrame(() => { this.updateSelected(); })}">
${ alerts }
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { FormContext, FormUpdatedEvent } from '@netwerk-digitaal-erfgoed/solid-crs-components';
import { CollectionObjectMemoryStore, CollectionObjectStore, ConsoleLogger, LoggerLevel, CollectionStore, CollectionMemoryStore, Collection, CollectionObject } from '@netwerk-digitaal-erfgoed/solid-crs-core';
import { interpret, Interpreter } from 'xstate';
import { appMachine } from '../../app.machine';
Expand Down Expand Up @@ -179,7 +180,7 @@ describe('ObjectMachine', () => {

describe('validateObjectForm()', () => {

let context = {};
let context: FormContext<CollectionObject>;

beforeEach(() => {

Expand All @@ -194,6 +195,16 @@ describe('ObjectMachine', () => {
uri: undefined,
image: undefined,
},
original: {
description: 'description',
name: 'name',
identifier: 'identifier',
dateCreated: '2021',
type: undefined,
collection: undefined,
uri: undefined,
image: undefined,
},
};

});
Expand Down Expand Up @@ -245,17 +256,17 @@ describe('ObjectMachine', () => {

});

it('should return an error when image is a valid url', async () => {
it('should return an error when image is an empty string', async () => {

context.data = { ...context.data, image: 'StringThatDoesNotMakeSense' };
context.data = { ...context.data, image: '' };
const res = validateObjectForm(context);
await expect(res).resolves.toHaveLength(1);

});

it('should return an error when image is not a real url', async () => {

context.data = { ...context.data, image: 'http://www.image.be/image.png' };
context.data = { ...context.data, image: 'StringThatDoesNotMakeSense' };
const res = validateObjectForm(context);
await expect(res).resolves.toHaveLength(1);

Expand Down
Loading

0 comments on commit c4326b1

Please sign in to comment.