Skip to content

Instantly share code, notes, and snippets.

@ljmotta
Last active September 30, 2020 23:29
Show Gist options
  • Save ljmotta/153b9b8af8a190b93ec4b192f6dafd11 to your computer and use it in GitHub Desktop.
Save ljmotta/153b9b8af8a190b93ec4b192f6dafd11 to your computer and use it in GitHub Desktop.
Todo List View
import { Item } from "./TodoListEnvelopeApi";
export interface TodoListApi {
addItem(item: string): Promise<void>;
getItems(): Promise<Item[]>;
markAllAsCompleted(): void;
}
export interface TodoListChannelApi {
todoList__itemRemoved(item: string): void;
}
export interface TodoListEnvelopeApi {
todoList__init(association: Association, initArgs: TodoListInitArgs): Promise<void>;
todoList__addItem(item: string): Promise<void>;
todoList__getItems(): Promise<Item[]>;
todoList__markAllAsCompleted(): void;
}
export interface Association {
origin: string;
envelopeServerId: string;
}
export interface TodoListInitArgs {
user: string;
}
export interface Item {
label: string;
completed: boolean;
}
import * as React from "react";
import { useMemo } from "react";
import { EmbeddedEnvelopeFactory } from "../__copied-from-kogito-tooling/EmbeddedEnvelopeFactory";
export const EmbeddedTodoList = React.forwardRef<TodoListApi, Props>((props, forwardedRef) => {
...
const EmbeddedEnvelope = useMemo(() => {
return EmbeddedEnvelopeFactory({
api: props,
envelopePath: props.envelopePath,
origin: props.targetOrigin,
refDelegate,
pollInit,
});
}, []);
return <EmbeddedEnvelope ref={forwardedRef} />;
});
import { useCallback } from "react";
import { EnvelopeServer } from "@kogito-tooling/envelope-bus/dist/channel";
import { TodoListChannelApi, TodoListEnvelopeApi } from "../api";
export const EmbeddedTodoList = React.forwardRef<TodoListApi, Props>((props, forwardedRef) => {
const pollInit = useCallback((envelopeServer: EnvelopeServer<TodoListChannelApi, TodoListEnvelopeApi>) => {
return envelopeServer.client.request(
"todoList__init",
{
origin: envelopeServer.origin,
envelopeServerId: envelopeServer.id,
},
{ user: "Tiago" }
);
}, []);
...
});
import * as React from "react";
import { TodoListApi, TodoListChannelApi } from "../api";
export type Props = TodoListChannelApi & {
targetOrigin: string;
envelopePath: string;
};
export const EmbeddedTodoList = React.forwardRef<TodoListApi, Props>((props, forwardedRef) => {
...
});
import { useCallback } from "react";
import { TodoListApi } from "../api";
export const EmbeddedTodoList = React.forwardRef<TodoListApi, Props>((props, forwardedRef) => {
...
const refDelegate = useCallback(
(envelopeServer: EnvelopeServer<TodoListChannelApi, TodoListEnvelopeApi>): TodoListApi => ({
addItem: (item) => envelopeServer.client.request("todoList__addItem", item),
getItems: () => envelopeServer.client.request("todoList__getItems"),
markAllAsCompleted: () => envelopeServer.client.notify("todoList__markAllAsCompleted"),
}),
[]
);
...
});
import { Association, TodoListInitArgs } from "../api";
export class TodoListEnvelopeApiImpl implements TodoListEnvelopeApi {
...
public async todoList__init(association: Association, initArgs: TodoListInitArgs) {
this.args.envelopeBusController.associate(association.origin, association.envelopeServerId);
this.args.view().setUser(initArgs.user);
}
public async todoList__addItem(item: string) {
return this.args.view().addItem(item);
}
public async todoList__getItems() {
return this.args.view().getItems();
}
public todoList__markAllAsCompleted() {
this.args.view().markAllAsCompleted();
}
}
import { EnvelopeApiFactoryArgs } from "../__copied-from-kogito-tooling/EnvelopeApiFactory";
import { TodoListEnvelopeContext } from "./TodoListEnvelopeContext";
import { TodoListChannelApi, TodoListEnvelopeApi } from "../api";
import { TodoListEnvelopeViewApi } from "./TodoListEnvelopeView";
export class TodoListEnvelopeApiImpl implements TodoListEnvelopeApi {
constructor(
private readonly args: EnvelopeApiFactoryArgs<
TodoListEnvelopeApi,
TodoListChannelApi,
TodoListEnvelopeViewApi,
TodoListEnvelopeContext
>
) {}
...
}
import { Envelope, EnvelopeBus } from "@kogito-tooling/envelope-bus/dist/api";
import { TodoListEnvelopeContext } from "./TodoListEnvelopeContext";
import { TodoListEnvelopeViewApi } from "./TodoListEnvelopeView";
import { TodoListChannelApi, TodoListEnvelopeApi } from "../api";
export function init(args: { container: HTMLElement; bus: EnvelopeBus }) {
const envelope = new Envelope<
TodoListEnvelopeApi,
TodoListChannelApi,
TodoListEnvelopeViewApi,
TodoListEnvelopeContext
>(args.bus);
...
}
import { TodoListEnvelopeApiImpl } from "./TodoListEnvelopeApiImpl";
import { TodoListEnvelopeContext } from "./TodoListEnvelopeContext";
export function init(args: { container: HTMLElement; bus: EnvelopeBus }) {
...
const context: TodoListEnvelopeContext = {};
return envelope.start(envelopeViewDelegate, context, {
create: (apiFactoryArgs) => new TodoListEnvelopeApiImpl(apiFactoryArgs),
});
}
import { MessageBusClient } from "@kogito-tooling/envelope-bus/dist/api";
import * as React from "react";
import { useState } from "react";
import { Item, TodoListChannelApi } from "../api";
export interface TodoListEnvelopeViewApi {
setUser(user: string): void;
addItem(item: string): void;
getItems(): Item[];
markAllAsCompleted(): void;
}
interface Props {
channelApi: MessageBusClient<TodoListChannelApi>;
}
export const TodoListEnvelopeView = React.forwardRef<TodoListEnvelopeViewApi, Props>((props, forwardedRef) => {
const [user, setUser] = useState<string | undefined>();
const [items, setItems] = useState<Item[]>([]);
...
});
export const TodoListEnvelopeView = React.forwardRef<TodoListEnvelopeViewApi, Props>((props, forwardedRef) => {
...
const removeItem = useCallback(
(e: React.MouseEvent<HTMLAnchorElement, MouseEvent>, item: Item) => {
e.preventDefault();
const itemsCopy = [...items];
const i = itemsCopy.indexOf(item);
if (i >= 0) {
itemsCopy.splice(i, 1);
setItems(itemsCopy);
props.channelApi.notify("todoList__itemRemoved", item.label);
}
},
[items]
);
const updateItemCompletedStatus = useCallback(
(e: React.MouseEvent<HTMLAnchorElement, MouseEvent>, item: Item, completed: boolean) => {
e.preventDefault();
const itemsCopy = [...items];
const i = itemsCopy.indexOf(item);
if (i >= 0) {
itemsCopy[i].completed = completed;
setItems(itemsCopy);
}
},
[items]
);
const allCompleted = useMemo(() => {
const completedItems = items.filter((i) => i.completed);
return items.length > 0 && completedItems.length === items.length;
}, [items]);
...
});
import * as React from "react";
import * as ReactDOM from "react-dom";
import { TodoListEnvelopeView, TodoListEnvelopeViewApi } from "./TodoListEnvelopeView";
export function init(args: { container: HTMLElement; bus: EnvelopeBus }) {
...
const envelopeViewDelegate = async () => {
const ref = React.createRef<TodoListEnvelopeViewApi>();
return new Promise<() => TodoListEnvelopeViewApi>((res) =>
ReactDOM.render(<TodoListEnvelopeView ref={ref} channelApi={envelope.channelApi} />, args.container, () =>
res(() => ref.current!)
)
);
};
...
}
import { useImperativeHandle } from "react";
export const TodoListEnvelopeView = React.forwardRef<TodoListEnvelopeViewApi, Props>((props, forwardedRef) => {
...
useImperativeHandle(
forwardedRef,
() => ({
setUser,
addItem: (item) => setItems([...items, { label: item, completed: false }]),
getItems: () => items,
markAllAsCompleted: () => setItems(items.map((item) => ({ ...item, completed: true }))),
}),
[items]
);
...
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment