Skip to content

Commit

Permalink
feat(imjoy-api): create service, move dispatchSpawn to render
Browse files Browse the repository at this point in the history
  • Loading branch information
PaulHax committed Jan 16, 2024
1 parent 01f1698 commit 171d847
Show file tree
Hide file tree
Showing 25 changed files with 380 additions and 215 deletions.
16 changes: 2 additions & 14 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,7 @@ jobs:
- name: Test with Chrome
uses: cypress-io/github-action@v5
with:
start: pnpm run test:ci
record: true
start: pnpm run test
component: true
browser: chrome
env:
Expand All @@ -38,20 +37,9 @@ jobs:
- name: Test with Firefox
uses: cypress-io/github-action@v5
with:
start: pnpm run test:ci
record: true
start: pnpm run cy:component
component: true
browser: firefox
env:
CYPRESS_RECORD_KEY: ${{ secrets.CYPRESS_RECORD_KEY }}
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

# Not quite read for automated publication
#- name: Publish
#env:
#GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
#NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
#run: |
#git config --global user.name "GitHub Actions"
#git config --global user.email "itk+community@discourse.itk.org"
#npx semantic-release
2 changes: 0 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,9 @@
"setup-micromamba": "setup-micromamba --micromamba-binary-path ./micromamba/micromamba --micromamba-root-path ./micromamba --init-shell none --create-environment true --environment-file environment.yml --log-level info --run-command \"clean -fya\"",
"start-hypha": "pnpm setup-micromamba && ./micromamba/micromamba run -r micromamba -n itk-viewer hypha --host=127.0.0.1 --port=37580",
"test": "pnpm test:downloadData && concurrently -n \"hypha,cypress\" --success first -k \"pnpm start-hypha\" \"pnpm cy:component\"",
"test:ci": "pnpm test:downloadData && pnpm cy:component:ci",
"test:downloadData": "node test/downloadData.mjs",
"cy:watch": "cypress open --component -b chrome",
"cy:component": "cypress run --component",
"cy:component:ci": "cypress run --component --record",
"cy:component:chrome": "cypress run --component --browser chrome",
"clean": "git clean -fdx",
"ci:publish": "pnpm publish -r --access public"
Expand Down
2 changes: 0 additions & 2 deletions packages/element/examples/view-3d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,6 @@ setPipelinesBaseUrl(pipelineBaseUrl);

document.addEventListener('DOMContentLoaded', async function () {
const imagePath = '/ome-ngff-prototypes/single_image/v0.4/zyx.ome.zarr';
// const imagePath = '/ome-ngff-prototypes/single_image/v0.4/tczyx.ome.zarr';
// const imagePath = '/astronaut.zarr';
const url = new URL(imagePath, document.location.origin);
const image = await ZarrMultiscaleSpatialImage.fromUrl(url);

Expand Down
16 changes: 8 additions & 8 deletions packages/element/src/itk-view-2d-vtkjs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { SelectorController } from 'xstate-lit';
import { Actor } from 'xstate';

import { createLogic } from '@itk-viewer/vtkjs/view-2d-vtkjs.js';
import { SpawnController } from './spawn-controller.js';
import { dispatchSpawn } from './spawn-controller.js';
import { Camera } from '@itk-viewer/viewer/camera.js';
import './itk-camera.js';

Expand All @@ -15,13 +15,7 @@ type ComponentActor = Actor<ReturnType<typeof createLogic>>;
export class ItkView2dVtkjs extends LitElement {
actor: ComponentActor | undefined;
container: HTMLElement | undefined;

spawner = new SpawnController(
this,
'renderer',
createLogic(),
(actor: ComponentActor) => this.setActor(actor),
);
dispatched = false;

cameraActor:
| SelectorController<ComponentActor, Camera | undefined>
Expand Down Expand Up @@ -54,6 +48,12 @@ export class ItkView2dVtkjs extends LitElement {
}

render() {
if (!this.dispatched) {
dispatchSpawn(this, 'renderer', createLogic(), (actor) =>
this.setActor(actor),
);
this.dispatched = true;
}
return html`
<itk-camera .actor=${this.cameraActor?.value} class="container">
<div class="container" ${ref(this.onContainer)}></div>
Expand Down
12 changes: 7 additions & 5 deletions packages/element/src/itk-view-2d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,15 @@ import { View2dActor, view2d } from '@itk-viewer/viewer/view-2d.js';
import { LitElement, css, html, nothing } from 'lit';
import { customElement } from 'lit/decorators.js';
import { SelectorController } from 'xstate-lit';
import { SpawnController, handleLogic } from './spawn-controller.js';
import { dispatchSpawn, handleLogic } from './spawn-controller.js';

@customElement('itk-view-2d')
export class ItkView2d extends LitElement {
actor: View2dActor | undefined;
scale: SelectorController<View2dActor, number> | undefined;
scaleCount: SelectorController<View2dActor, number> | undefined;
slice: SelectorController<View2dActor, number> | undefined;

spawner = new SpawnController(this, 'view', view2d, (actor: View2dActor) =>
this.setActor(actor),
);
dispatched = false;

constructor() {
super();
Expand Down Expand Up @@ -58,6 +55,11 @@ export class ItkView2d extends LitElement {
}

render() {
if (!this.dispatched) {
dispatchSpawn(this, 'view', view2d, (actor) => this.setActor(actor));
this.dispatched = true;
}

const slice = this.slice?.value ?? 0;
const scale = this.scale?.value ?? 0;
const scaleCount = this.scaleCount?.value ?? 1;
Expand Down
17 changes: 9 additions & 8 deletions packages/element/src/itk-view-3d-vtkjs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { ref } from 'lit/directives/ref.js';
import { Actor } from 'xstate';

import { createLogic } from '@itk-viewer/vtkjs/view-3d-vtkjs.js';
import { SpawnController } from './spawn-controller.js';
import { dispatchSpawn } from './spawn-controller.js';
import { SelectorController } from 'xstate-lit';
import { Camera } from '@itk-viewer/viewer/camera.js';
import './itk-camera.js';
Expand All @@ -15,13 +15,7 @@ type ComponentActor = Actor<ReturnType<typeof createLogic>>;
export class ItkView3dVtkjs extends LitElement {
actor: ComponentActor | undefined;
container: HTMLElement | undefined;

spawner = new SpawnController(
this,
'renderer',
createLogic(),
(actor: ComponentActor) => this.setActor(actor),
);
dispatched = false;

cameraActor:
| SelectorController<ComponentActor, Camera | undefined>
Expand Down Expand Up @@ -54,6 +48,13 @@ export class ItkView3dVtkjs extends LitElement {
}

render() {
if (!this.dispatched) {
dispatchSpawn(this, 'renderer', createLogic(), (actor) =>
this.setActor(actor),
);
this.dispatched = true;
}

return html`
<itk-camera .actor=${this.cameraActor?.value} class="container">
<div class="container" ${ref(this.onContainer)}></div>
Expand Down
16 changes: 7 additions & 9 deletions packages/element/src/itk-view-3d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { View3dActor, view3d } from '@itk-viewer/viewer/view-3d.js';
import { LitElement, css, html, nothing } from 'lit';
import { customElement } from 'lit/decorators.js';
import { SelectorController } from 'xstate-lit';
import { SpawnController, handleLogic } from './spawn-controller.js';
import { dispatchSpawn, handleLogic } from './spawn-controller.js';

type Actor = View3dActor;

Expand All @@ -11,14 +11,7 @@ export class ItkView3d extends LitElement {
actor: Actor | undefined;
scale: SelectorController<Actor, number> | undefined;
scaleCount: SelectorController<Actor, number> | undefined;

spawner = new SpawnController(this, 'view', view3d, (actor: Actor) =>
this.setActor(actor),
);

constructor() {
super();
}
dispatched = false;

setActor(actor: Actor) {
this.actor = actor;
Expand Down Expand Up @@ -46,6 +39,11 @@ export class ItkView3d extends LitElement {
}

render() {
if (!this.dispatched) {
dispatchSpawn(this, 'view', view3d, (actor) => this.setActor(actor));
this.dispatched = true;
}

const scale = this.scale?.value ?? 0;
const scaleCount = this.scaleCount?.value ?? 1;
const scaleOptions = Array.from(
Expand Down
50 changes: 50 additions & 0 deletions packages/element/src/itk-viewer-3d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import { LitElement, css, html } from 'lit';
import { customElement } from 'lit/decorators.js';
import { Ref, createRef, ref } from 'lit/directives/ref.js';
import { ItkViewer } from './itk-viewer-element.js';
import './itk-viewport.js';
import './itk-view-3d.js';
import './itk-view-3d-vtkjs.js';

@customElement('itk-viewer-3d')
export class ItkViewer3d extends LitElement {
viewer: Ref<ItkViewer> = createRef();

getActor() {
return this.viewer.value?.getActor();
}

render() {
return html`
<itk-viewer class="fill" ${ref(this.viewer)}>
<itk-viewport class="fill">
<itk-view-3d class="fill">
<itk-view-3d-vtkjs></itk-view-3d-vtkjs>
</itk-view-3d>
</itk-viewport>
</itk-viewer>
`;
}

static styles = css`
:host {
flex: 1;
display: flex;
flex-direction: column;
}
.fill {
flex: 1;
min-height: 0;
overflow: hidden;
display: flex;
flex-direction: column;
}
`;
}

declare global {
interface HTMLElementTagNameMap {
'itk-viewer-3d': ItkViewer3d;
}
}
6 changes: 3 additions & 3 deletions packages/element/src/itk-viewer-element.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,20 +7,20 @@ import { handleLogic } from './spawn-controller.js';

@customElement('itk-viewer')
export class ItkViewer extends LitElement {
viewer = createActor(viewerMachine).start();
actor = createActor(viewerMachine).start();

constructor() {
super();
}

getActor() {
return this.viewer;
return this.actor;
}

render() {
return html`
<h1>Viewer</h1>
<slot @viewport=${handleLogic(this.viewer)}></slot>
<slot @viewport=${handleLogic(this.actor)}></slot>
`;
}
}
Expand Down
24 changes: 8 additions & 16 deletions packages/element/src/itk-viewport.ts
Original file line number Diff line number Diff line change
@@ -1,22 +1,12 @@
import { LitElement, html } from 'lit';
import { customElement } from 'lit/decorators.js';
import { viewportMachine, ViewportActor } from '@itk-viewer/viewer/viewport.js';
import { SpawnController, handleLogic } from './spawn-controller.js';
import { dispatchSpawn, handleLogic } from './spawn-controller.js';

@customElement('itk-viewport')
export class ItkViewport extends LitElement {
actor: ViewportActor | undefined;

spawner = new SpawnController(
this,
'viewport',
viewportMachine,
(actor) => (this.actor = actor),
);

constructor() {
super();
}
dispatched = false;

getActor() {
return this.actor;
Expand All @@ -26,11 +16,13 @@ export class ItkViewport extends LitElement {
this.actor = actor;
}

connectedCallback(): void {
super.connectedCallback();
}

render() {
if (!this.dispatched) {
dispatchSpawn(this, 'viewport', viewportMachine, (actor) =>
this.setActor(actor),
);
this.dispatched = true;
}
return html`
<h1>Viewport</h1>
<slot @view=${handleLogic(this.actor)}></slot>
Expand Down
59 changes: 22 additions & 37 deletions packages/element/src/spawn-controller.ts
Original file line number Diff line number Diff line change
@@ -1,43 +1,27 @@
import { LitElement, ReactiveController } from 'lit';
import { LitElement } from 'lit';
import { Actor, AnyActor, AnyActorLogic } from 'xstate';

export class SpawnController<TLogic extends AnyActorLogic>
implements ReactiveController
{
private host: HTMLElement;
type: string;
logic: TLogic;
onActor: (actor: Actor<TLogic>) => void;
export const dispatchSpawn = <TLogic extends AnyActorLogic>(
host: LitElement,
eventType: string,
logic: TLogic,
onActor: (actor: Actor<TLogic>) => void,
) => {
const event = new CustomEvent(eventType, {
bubbles: true,
composed: true,
detail: {
logic: logic,
onActor: onActor,
},
});
host.dispatchEvent(event);
};

constructor(
host: LitElement,
type: string,
logic: TLogic,
onActor: (actor: Actor<TLogic>) => void,
) {
(this.host = host).addController(this);
this.type = type;
this.logic = logic;
this.onActor = onActor;
}

hostConnected() {
const event = new CustomEvent(this.type, {
bubbles: true,
composed: true,
detail: {
logic: this.logic,
onActor: this.onActor,
},
});

this.host.dispatchEvent(event);
}
}

export const handleLogic =
<TActor extends AnyActor>(parentActor: TActor | undefined) =>
(e: Event) => {
export const handleLogic = <TActor extends AnyActor>(
parentActor: TActor | undefined,
) => {
return (e: Event) => {
if (!parentActor) throw new Error('Parent actor not available');
e.stopPropagation();
const logic = (e as CustomEvent).detail.logic;
Expand All @@ -49,3 +33,4 @@ export const handleLogic =
onActor: (e as CustomEvent).detail.onActor,
});
};
};
Loading

0 comments on commit 171d847

Please sign in to comment.