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

Feat: loan machine, events, states, root #564

Merged
merged 10 commits into from
Jan 27, 2022
1 change: 1 addition & 0 deletions packages/solid-crs-core/lib/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ export * from './collections/collection-object-memory-store';
export * from './collections/collection-object-store';
export * from './collections/collection-store';
export * from './collections/collection-memory-store';
export * from './loan/models/loan-request';
export * from './errors/argument-error';
export * from './errors/base-error';
export * from './errors/not-implemented-error';
Expand Down
31 changes: 31 additions & 0 deletions packages/solid-crs-core/lib/loan/models/loan-request.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
export interface LoanRequest {
/**
* The uri of the request
*/
uri: string;
/**
* The uri of the requested collection
*/
collection: string;
/**
* UNIX timestamp of when the request was created
*/
createdAt: string;
/**
* WebID of the institution sending the request
*/
from: string;
/**
* WebID of the institution receiving the request
*/
to: string;
/**
* An optional note for the receiving institution
*/
description?: string;
/**
* Indicates if the request is accepted or not
* Optional: when this parameter is undefined, the request is pending / neither accepted or rejected
*/
accepted?: boolean;
}
20 changes: 20 additions & 0 deletions packages/solid-crs-manage/lib/app-root.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ import { CollectionEvents } from './features/collection/collection.events';
import { SearchEvent, SearchUpdatedEvent } from './features/search/search.events';
import { SearchContext } from './features/search/search.machine';
import { AuthenticateRootComponent } from './features/authenticate/authenticate-root.component';
import { LoanRootComponent } from './features/loan/loan-root.component';
import { ClickedLoanRequestOverviewEvent } from './features/loan/loan.events';

/**
* The root page of the application.
Expand Down Expand Up @@ -91,6 +93,7 @@ export class AppRootComponent extends RxLitElement {
super();

define('nde-authenticate-root', hydrate(AuthenticateRootComponent)(this.solidService));
define('nde-loan-root', hydrate(LoanRootComponent)(this.translator, this.logger));

}

Expand Down Expand Up @@ -254,6 +257,12 @@ export class AppRootComponent extends RxLitElement {

}

onLoanRequestOverview(): void {

this.actor.send(new ClickedLoanRequestOverviewEvent());

}

/**
* Renders the component as HTML.
*
Expand Down Expand Up @@ -295,6 +304,16 @@ export class AppRootComponent extends RxLitElement {
</nde-form-element>
</div>
</nde-sidebar-item>
<nde-sidebar-item .padding="${false}">
<nde-sidebar-list slot="content">
<nde-sidebar-list-item slot="item" inverse
?selected="${this.state?.matches({ [AppRootStates.AUTHENTICATE]: AppAuthenticateStates.AUTHENTICATED, [AppRootStates.FEATURE]: AppFeatureStates.LOAN })}"
@click="${this.onLoanRequestOverview}"
>
<div slot="title">${this.translator?.translate('navigation.loan')}</div>
</nde-sidebar-list-item>
</nde-sidebar-list>
</nde-sidebar-item>
<nde-sidebar-item .padding="${false}" .showBorder="${false}">
<nde-sidebar-list slot="content">
<nde-sidebar-list-item slot="title" isTitle inverse>
Expand All @@ -317,6 +336,7 @@ export class AppRootComponent extends RxLitElement {
${ this.state?.matches({ [AppRootStates.AUTHENTICATE]: AppAuthenticateStates.AUTHENTICATED, [AppRootStates.FEATURE]: AppFeatureStates.COLLECTION }) ? html`<nde-collection-root .actor='${this.actor.children.get(AppActors.COLLECTION_MACHINE)}' .showDelete='${this.collections?.length > 1}' .logger='${this.logger}' .translator='${this.translator}'></nde-collection-root>` : '' }
${ this.state?.matches({ [AppRootStates.AUTHENTICATE]: AppAuthenticateStates.AUTHENTICATED, [AppRootStates.FEATURE]: AppFeatureStates.SEARCH }) ? html`<nde-search-root .actor='${this.actor.children.get(AppActors.SEARCH_MACHINE)}' .logger='${this.logger}' .translator='${this.translator}'></nde-search-root>` : '' }
${ this.state?.matches({ [AppRootStates.AUTHENTICATE]: AppAuthenticateStates.AUTHENTICATED, [AppRootStates.FEATURE]: AppFeatureStates.OBJECT }) ? html`<nde-object-root .actor='${this.actor.children.get(AppActors.OBJECT_MACHINE)}' .logger='${this.logger}' .translator='${this.translator}'></nde-object-root>` : '' }
${ this.state?.matches({ [AppRootStates.AUTHENTICATE]: AppAuthenticateStates.AUTHENTICATED, [AppRootStates.FEATURE]: AppFeatureStates.LOAN }) ? html`<nde-loan-root></nde-loan-root>` : '' }
` }

`;
Expand Down
15 changes: 15 additions & 0 deletions packages/solid-crs-manage/lib/app.machine.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import { SearchEvents, SearchUpdatedEvent } from './features/search/search.event
import { objectMachine } from './features/object/object.machine';
import { ObjectEvents } from './features/object/object.events';
import { createPod } from './app.services';
import { LoanEvents } from './features/loan/loan.events';

/**
* The root context of the application.
Expand Down Expand Up @@ -82,6 +83,7 @@ export enum AppFeatureStates {
SEARCH = '[AppFeatureState: Search]',
OBJECT = '[AppFeatureState: Object]',
IDLE = '[AppFeatureState: Idle]',
LOAN = '[AppFeatureState: Loan]',
}

/**
Expand Down Expand Up @@ -188,6 +190,10 @@ export const appMachine = (
target: `#${AppFeatureStates.SEARCH}`,
cond: (_, event: SearchUpdatedEvent) => event.searchTerm !== undefined && event.searchTerm !== '',
},
[LoanEvents.CLICKED_LOANREQUEST_OVERVIEW]: {
actions: assign({ selected: (context, event) => undefined }),
target: `#${AppFeatureStates.LOAN}`,
},
[RouterEvents.NAVIGATED]: {
// this overwrites default behavior as defined in the routerStateConfig
actions: [
Expand Down Expand Up @@ -315,6 +321,15 @@ export const appMachine = (
},
],
},
[AppFeatureStates.LOAN]: {
id: AppFeatureStates.LOAN,
on: {
[CollectionEvents.SELECTED_COLLECTION]: {
target: AppFeatureStates.COLLECTION,
actions: send((c, event) => event),
},
},
},
},
},
/**
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import { html, css, TemplateResult, CSSResult, unsafeCSS } from 'lit-element';
import { RxLitElement } from 'rx-lit';
import { Theme } from '@netwerk-digitaal-erfgoed/solid-crs-theme';
import { Logger, Translator } from '@netwerk-digitaal-erfgoed/solid-crs-core';

export class LoanCreationComponent extends RxLitElement {

constructor(
public translator: Translator,
public logger: Logger,
) {

super();

}

/**
* Renders the component as HTML.
*
* @returns The rendered HTML of the component.
*/
render(): TemplateResult {

return html`
LOAN CREATION
`;

}

/**
* The styles associated with the component.
*/
static get styles(): CSSResult[] {

return [
unsafeCSS(Theme),
css`

`,
];

}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import { html, css, TemplateResult, CSSResult, unsafeCSS } from 'lit-element';
import { RxLitElement } from 'rx-lit';
import { Theme } from '@netwerk-digitaal-erfgoed/solid-crs-theme';
import { Logger, Translator } from '@netwerk-digitaal-erfgoed/solid-crs-core';

export class LoanDetailComponent extends RxLitElement {

constructor(
public translator: Translator,
public logger: Logger,
) {

super();

}

/**
* Renders the component as HTML.
*
* @returns The rendered HTML of the component.
*/
render(): TemplateResult {

return html`
LOAN DETAIL
`;

}

/**
* The styles associated with the component.
*/
static get styles(): CSSResult[] {

return [
unsafeCSS(Theme),
css`

`,
];

}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import { html, css, TemplateResult, CSSResult, unsafeCSS } from 'lit-element';
import { RxLitElement } from 'rx-lit';
import { Theme } from '@netwerk-digitaal-erfgoed/solid-crs-theme';
import { Logger, Translator } from '@netwerk-digitaal-erfgoed/solid-crs-core';

export class LoanOverviewComponent extends RxLitElement {

constructor(
public translator: Translator,
public logger: Logger,
) {

super();

}

/**
* Renders the component as HTML.
*
* @returns The rendered HTML of the component.
*/
render(): TemplateResult {

return html`
LOAN OVERVIEW
`;

}

/**
* The styles associated with the component.
*/
static get styles(): CSSResult[] {

return [
unsafeCSS(Theme),
css`

`,
];

}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
/* eslint-disable @typescript-eslint/no-explicit-any */
/* eslint-disable @typescript-eslint/dot-notation */
import { define, hydrate } from '@digita-ai/dgt-components';
import { ConsoleLogger, LoanRequest, Logger, LoggerLevel } from '@netwerk-digitaal-erfgoed/solid-crs-core';
import { LoanRootComponent } from './loan-root.component';
import { ClickedLoanRequestDetailEvent, ClickedLoanRequestOverviewEvent, ClickedNewLoanRequestEvent } from './loan.events';
import { LoanStates } from './loan.states';
import * as services from './loan.services';

(services as any).loadRequests = jest.fn().mockResolvedValue([]);
(services as any).createRequest = jest.fn().mockImplementation(async (request: LoanRequest) => request);
(services as any).acceptRequest = jest.fn().mockImplementation(async (request: LoanRequest) => request);
(services as any).rejectRequest = jest.fn().mockImplementation(async (request: LoanRequest) => request);

describe('LoanRootComponent', () => {

let component: LoanRootComponent;
const tag = 'nde-loan-root';
const translator = { translate: (input: string) => input };
const logger: Logger = new ConsoleLogger(LoggerLevel.silly, LoggerLevel.silly);

beforeEach(() => {

jest.clearAllMocks();
define(tag, hydrate(LoanRootComponent)(translator, logger));
component = document.createElement(tag) as LoanRootComponent;

});

it('should instantiate', async () => {

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

expect(component).toBeTruthy();
expect(component).toBeInstanceOf(LoanRootComponent);

});

describe('onNewLoanRequest', () => {

it('should send ClickedNewLoanRequestEvent', () => {

component['actor'].send = jest.fn();
component['onNewLoanRequest']();

expect(component['actor'].send).toHaveBeenCalledWith(new ClickedNewLoanRequestEvent());

});

});

describe('onLoanRequestOverview', () => {

it('should send ClickedLoanRequestOverviewEvent', () => {

component['actor'].send = jest.fn();
component['onLoanRequestOverview']();

expect(component['actor'].send).toHaveBeenCalledWith(new ClickedLoanRequestOverviewEvent());

});

});

describe('HTML', () => {

it(`should render loan-overview-component when ${LoanStates.REQUEST_OVERVIEW}`, async () => {

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

expect(component.shadowRoot.innerHTML).toContain('<nde-loan-overview-component');
expect(component.shadowRoot.innerHTML).not.toContain('<nde-loan-creation-component');
expect(component.shadowRoot.innerHTML).not.toContain('<nde-loan-detail-component');

});

it(`should render loan-detail-component when ${LoanStates.REQUEST_DETAIL}`, async () => {

component['actor'].send(new ClickedLoanRequestDetailEvent({} as any));

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

expect(component.shadowRoot.innerHTML).not.toContain('<nde-loan-overview-component');
expect(component.shadowRoot.innerHTML).not.toContain('<nde-loan-creation-component');
expect(component.shadowRoot.innerHTML).toContain('<nde-loan-detail-component');

});

it(`should render loan-creation-component when ${LoanStates.CREATING_REQUEST}`, async () => {

component['actor'].send(new ClickedNewLoanRequestEvent());

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

expect(component.shadowRoot.innerHTML).not.toContain('<nde-loan-overview-component');
expect(component.shadowRoot.innerHTML).toContain('<nde-loan-creation-component');
expect(component.shadowRoot.innerHTML).not.toContain('<nde-loan-detail-component');

});

});

});
Loading