Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: collection page improvements #320

Merged
merged 11 commits into from
Jun 21, 2021
Original file line number Diff line number Diff line change
Expand Up @@ -22,17 +22,17 @@ describe('FormElementComponent', () => {
]),
)
.withContext({
data: { uri: '', name: 'Test', description: 'description', weight: 321 },
original: { uri: '', name: 'Test', description: 'description', weight: 321 },
data: { uri: '', name: 'Test', description: 'description', weight: 321, type: '', collection: '', image: '' },
original: { uri: '', name: 'Test', description: 'description', weight: 321, type: '', collection: '', image: '' },
validation: [ { field: 'name', message: 'lorem' } ],
}),
);

component = window.document.createElement('nde-form-element') as FormElementComponent<Collection>;
component = window.document.createElement('nde-form-element') as FormElementComponent<CollectionObject>;

component.actor = machine;
component.field = 'name';
component.data = { uri: '', name: 'Test', description: 'description' };
component.data = { uri: '', name: 'Test', description: 'description', type: '', collection: '', image: '' };

const label = window.document.createElement('label');
label.innerHTML = 'Foo';
Expand Down Expand Up @@ -214,6 +214,19 @@ describe('FormElementComponent', () => {

});

it('should show yellow border when showValidation is false', async () => {

component.validationResults = [ { field: 'name', message: 'lorem' } ];
component.showValidation = false;

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

expect(window.document.body.getElementsByTagName('nde-form-element')[0].shadowRoot.querySelector<HTMLDivElement>('.results').hidden).toBeTruthy();
expect(window.document.body.getElementsByTagName('nde-form-element')[0].shadowRoot.querySelector<HTMLDivElement>('.content').classList).toContain('no-validation');

});

it('should show static slotted content', async () => {

window.document.body.appendChild(component);
Expand Down
36 changes: 23 additions & 13 deletions packages/solid-crs-components/lib/forms/form-element.component.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { css, html, internalProperty, property, PropertyValues, query, unsafeCSS } from 'lit-element';
import { triggerAsyncId } from 'async_hooks';
import { css, CSSResult, html, internalProperty, property, PropertyValues, query, TemplateResult, unsafeCSS } from 'lit-element';
import { unsafeSVG } from 'lit-html/directives/unsafe-svg';
import { ArgumentError, Translator, debounce } from '@netwerk-digitaal-erfgoed/solid-crs-core';
import { SpawnedActorRef, State } from 'xstate';
Expand Down Expand Up @@ -30,19 +31,19 @@ export class FormElementComponent<T> extends RxLitElement {
/**
* Decides whether a border should be shown around the content
*/
@property()
@property({ type: Boolean })
public inverse = false;

/**
* Decides whether the label should be shown
*/
@property()
@property({ type: Boolean })
public showLabel = true;

/**
* The component's translator.
*/
@property({ type: Translator })
@property({ type: Object })
public translator: Translator;

/**
Expand Down Expand Up @@ -78,7 +79,7 @@ export class FormElementComponent<T> extends RxLitElement {
/**
* Timeout to use when debouncing input.
*/
@property()
@property({ type: Number })
public debounceTimeout = 500;

/**
Expand All @@ -93,10 +94,17 @@ export class FormElementComponent<T> extends RxLitElement {
@property({ type: Object })
public actor: SpawnedActorRef<FormEvent, State<FormContext<T>>>;

/**
* Decides whether validation results should be shown below the form element
* When false, only shows a yellow border to the left of the component
*/
@property({ type: Boolean })
public showValidation = true;

/**
* Hook called on every update after connection to the DOM.
*/
updated(changed: PropertyValues) {
updated(changed: PropertyValues): void {

super.updated(changed);

Expand Down Expand Up @@ -149,7 +157,7 @@ export class FormElementComponent<T> extends RxLitElement {
actor: SpawnedActorRef<FormEvent, State<FormContext<T>>>,
field: keyof T,
data: T
) {
): void {

if (!slot) {

Expand Down Expand Up @@ -246,7 +254,7 @@ export class FormElementComponent<T> extends RxLitElement {
*
* @returns The rendered HTML of the component.
*/
render() {
render(): TemplateResult {

return html`
<div class="form-element">
Expand All @@ -256,8 +264,8 @@ export class FormElementComponent<T> extends RxLitElement {
<slot name="label"></slot>
</div>
` : ''
}
<div class="content">
}
<div class="content ${!this.showValidation && this.validationResults?.length > 0 ? 'no-validation' : ''}">
<div class="field ${this.inverse ? 'no-border' : ''}">
<slot name="input"></slot>
<div class="icon">
Expand All @@ -271,7 +279,7 @@ export class FormElementComponent<T> extends RxLitElement {
<div class="help" ?hidden="${this.validationResults && this.validationResults?.length > 0}">
<slot name="help"></slot>
</div>
<div class="results" ?hidden="${!this.validationResults || this.validationResults.length === 0}">
<div class="results" ?hidden="${!this.showValidation || !this.validationResults || this.validationResults.length === 0}">
${this.validationResults?.map((result) => html`<div class="result">${this.translator ? this.translator.translate(result.message) : result.message}</div>`)}
</div>
</div>
Expand All @@ -282,7 +290,7 @@ export class FormElementComponent<T> extends RxLitElement {
/**
* The styles associated with the component.
*/
static get styles() {
static get styles(): CSSResult[] {

return [
unsafeCSS(Theme),
Expand All @@ -294,10 +302,12 @@ export class FormElementComponent<T> extends RxLitElement {
.loading svg .loadCircle {
stroke: var(--colors-primary-normal);
}

.no-border, .no-border ::slotted(*) {
border: none !important;
}
.no-validation {
border-bottom: solid 2px var(--colors-status-warning);
}
.form-element {
display: flex;
flex-direction: column;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,14 +53,14 @@ export class ProgressBarComponent extends LitElement {
-webkit-appearance: none;
-moz-appearance: none;
appearance: none;
background-color: var(--colors-background-normal);
background-color: rgba(0,0,0,0);;
color: var(--colors-primary-light);
}
progress::-moz-progress-bar {
background-color: var(--colors-primary-light);
}
progress::-webkit-progress-bar {
background-color: var(--colors-background-normal);
background-color: rgba(0,0,0,0);;
}
progress::-webkit-progress-value {
background-color: var(--colors-primary-light);
Expand All @@ -70,7 +70,7 @@ export class ProgressBarComponent extends LitElement {
height: var(--gap-tiny);
display: block;
width: 100%;
background-color: var(--colors-background-normal);
background-color: rgba(0,0,0,0);;
border-radius: 2px;
margin: 0;
overflow: hidden;
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": 90.16,
"branches": 90.55,
"functions": 98.55,
"lines": 100,
"statements": 99.58
Expand Down
77 changes: 42 additions & 35 deletions packages/solid-crs-manage/lib/app-root.component.spec.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
import { Alert } from '@netwerk-digitaal-erfgoed/solid-crs-components';
import { ArgumentError, Collection, ConsoleLogger, LoggerLevel, MemoryStore, CollectionObjectMemoryStore } from '@netwerk-digitaal-erfgoed/solid-crs-core';
import { ArgumentError, Collection, ConsoleLogger, LoggerLevel, CollectionObjectMemoryStore, CollectionMemoryStore, CollectionObject } from '@netwerk-digitaal-erfgoed/solid-crs-core';
import { interpret, Interpreter } from 'xstate';
import { AppEvents } from './app.events';
import { AppEvents, LoggedInEvent } from './app.events';
import { AppAuthenticateStates, AppContext, AppDataStates, appMachine, AppRootStates } from './app.machine';
import { AppRootComponent } from './app-root.component';
import { SolidMockService } from './common/solid/solid-mock.service';
import { SearchEvents, SearchUpdatedEvent } from './features/search/search.events';

const solid = new SolidMockService(new ConsoleLogger(LoggerLevel.silly, LoggerLevel.silly));

Expand All @@ -14,46 +13,53 @@ describe('AppRootComponent', () => {
let component: AppRootComponent;
let machine: Interpreter<AppContext>;

const template: Collection = {
const collection1: Collection = {
uri: 'collection-uri-3',
name: 'Collection 3',
description: 'This is collection 3',
objectsUri: 'test-uri',
distribution: 'test-uri',
};

const collection2: Collection = {
uri: 'collection-uri-1',
name: 'Collection 1',
description: 'This is collection 1',
objectsUri: 'test-uri',
distribution: 'test-uri',
};

const collection3: Collection = {
uri: 'collection-uri-2',
name: 'Collection 2',
description: 'This is collection 2',
objectsUri: 'test-uri',
distribution: 'test-uri',
};

const object1: CollectionObject = {
uri: 'object-uri-1',
name: 'Object 1',
description: 'This is object 1',
image: null,
subject: null,
type: null,
updated: '0',
collection: 'collection-uri-1',
};

beforeEach(() => {

machine = interpret(appMachine(solid,
new MemoryStore<Collection>([
{
uri: 'collection-uri-1',
name: 'Collection 1',
description: 'This is collection 1',
objectsUri: 'test-uri',
distribution: 'test-uri',
},
{
uri: 'collection-uri-2',
name: 'Collection 2',
description: 'This is collection 2',
objectsUri: 'test-uri',
distribution: 'test-uri',
},
new CollectionMemoryStore([
collection2,
collection3,
]),
new CollectionObjectMemoryStore([
{
uri: 'object-uri-1',
name: 'Object 1',
description: 'This is object 1',
image: null,
subject: null,
type: null,
updated: 0,
collection: 'collection-uri-1',
},
object1,
]),
template)
collection1,
object1)
.withContext({
alerts: [],
session: { webId: 'lorem' },
Expand Down Expand Up @@ -100,7 +106,7 @@ describe('AppRootComponent', () => {
window.document.body.appendChild(component);
await component.updateComplete;

machine.send({ type: AppEvents.LOGGED_IN, session: { webId:'test' } });
machine.send({ type: AppEvents.LOGGED_IN, session: { webId:'test' } } as LoggedInEvent);

});

Expand Down Expand Up @@ -209,7 +215,7 @@ describe('AppRootComponent', () => {
[AppRootStates.DATA]: AppDataStates.IDLE,
})) {

machine.send({ type: AppEvents.LOGGED_IN, session: { webId: 'test' } });
machine.send({ type: AppEvents.LOGGED_IN, session: { webId: 'test' } } as LoggedInEvent);
await component.updateComplete;

}
Expand All @@ -228,9 +234,10 @@ describe('AppRootComponent', () => {

// start without collection
machine = interpret(appMachine(solid,
new MemoryStore<Collection>([]),
new CollectionMemoryStore([]),
new CollectionObjectMemoryStore([]),
template));
collection1,
object1));

machine.start();
component.actor = machine;
Expand All @@ -256,7 +263,7 @@ describe('AppRootComponent', () => {
})) {

done();
machine.send({ type: AppEvents.LOGGED_IN, session: { webId: 'test' } });
machine.send({ type: AppEvents.LOGGED_IN, session: { webId: 'test' } } as LoggedInEvent);
await component.updateComplete;

}
Expand Down
17 changes: 15 additions & 2 deletions packages/solid-crs-manage/lib/app-root.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { Alert, FormActors, FormEvent } from '@netwerk-digitaal-erfgoed/solid-cr
import { RxLitElement } from 'rx-lit';
import { Theme, Logout, Logo, Plus, Cross, Search } from '@netwerk-digitaal-erfgoed/solid-crs-theme';
import { unsafeSVG } from 'lit-html/directives/unsafe-svg';
import { AppActors, AppAuthenticateStates, AppContext, AppFeatureStates, appMachine, AppRootStates } from './app.machine';
import { AppActors, AppAuthenticateStates, AppContext, AppDataStates, AppFeatureStates, appMachine, AppRootStates } from './app.machine';
import nlNL from './i8n/nl-NL.json';
import { AppEvents } from './app.events';
import { SolidSDKService } from './common/solid/solid-sdk.service';
Expand Down Expand Up @@ -231,8 +231,16 @@ export class AppRootComponent extends RxLitElement {
*/
render(): TemplateResult {

const showLoading = this.state?.matches({ [AppRootStates.DATA]: AppDataStates.CREATING })
|| this.state?.matches({ [AppRootStates.DATA]: AppDataStates.REFRESHING });

return html`


${ this.state?.matches({ [AppRootStates.AUTHENTICATE]: AppAuthenticateStates.AUTHENTICATED }) ? html`

${ showLoading ? html`<nde-progress-bar></nde-progress-bar>` : html``}

<nde-sidebar inverse>
<nde-content-header>
<div slot="icon">${ unsafeSVG(Logo) }</div>
Expand Down Expand Up @@ -294,7 +302,12 @@ export class AppRootComponent extends RxLitElement {
:host > *:not(nde-sidebar) {
flex: 1 1;
}

nde-progress-bar {
position: absolute;
width: 100%;
top: 0;
left: 0;
}
nde-sidebar {
width: var(--size-sidebar);
}
Expand Down
Loading