Skip to content

Commit 85b3518

Browse files
committed
chore: install nestjs
1 parent b8ca9c6 commit 85b3518

File tree

13 files changed

+798
-455
lines changed

13 files changed

+798
-455
lines changed

apps/web/src/index.html

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
</head>
1616
<body class="mat-typography">
1717
<npl-root></npl-root>
18-
<!--<div id="container" data-plotid="{{plotid}}"></div>
19-
<script type="text/javascript" src="https://cdn.plot.ly/plotly-1.58.4.min.js"></script>-->
18+
<!--<div id="container" data-plotid="{{plotid}}"></div>-->
19+
<script type="text/javascript" src="https://cdn.plot.ly/plotly-1.58.4.min.js"></script>
2020
</body>
2121
</html>
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import { merge, Observable, Subject } from 'rxjs';
2+
import { map } from 'rxjs/operators';
3+
import { Action, PlotData } from '../models';
4+
import { Update } from '../models/store';
5+
6+
export const addPlot$ = new Subject<PlotData>();
7+
export const removePlot$ = new Subject<number>();
8+
export const removeAll$ = new Subject<void>();
9+
export const updatePlot$ = new Subject<Update<PlotData>>();
10+
11+
export const actions$: Observable<Action> = merge(
12+
addPlot$.pipe(map(plotdata => ({ type: 'addPlot', payload: plotdata}) as Action<PlotData>)),
13+
updatePlot$.pipe(map(changes => ({ type: 'updatePlot', payload: changes}) as Action<Update<PlotData>>)),
14+
removePlot$.pipe(map(id => ({ type: 'removePlot', payload: id}))),
15+
removeAll$.pipe(map(() => ({ type: 'removeAll' })))
16+
);
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
import { Observable } from 'rxjs';
2+
import { reduce, startWith } from 'rxjs/operators';
3+
import { EntityStore, PlotData } from '../models';
4+
import { Update } from '../models/store';
5+
import { actions$ } from './actions';
6+
7+
8+
export type State = EntityStore<PlotData>;
9+
10+
const initialState: State = {
11+
ids: [],
12+
entities: {}
13+
};
14+
15+
export const store$: Observable<State> = actions$.pipe(
16+
reduce((store, action) => {
17+
switch(action.type) {
18+
case 'addPlot': return addPlot(store, action.payload as PlotData);
19+
case 'updatePlot': return updatePlot(store, action.payload as Update<PlotData>);
20+
case 'removePlot': return removePlot(store, action.payload as number);
21+
case 'removeAll': return initialState;
22+
default: return store;
23+
}
24+
}, initialState),
25+
startWith(initialState)
26+
);
27+
28+
function addPlot(store: State, plotdata: PlotData): State {
29+
const id = Math.max(...store.ids, 0) + 1;
30+
return {
31+
ids: [...store.ids, id],
32+
entities: {...store.entities, [id]: plotdata}
33+
}
34+
}
35+
36+
function updatePlot(store: State, update: Update<PlotData>): State {
37+
return {
38+
ids: store.ids,
39+
entities: {
40+
...store.entities,
41+
[update.id]: {...store.entities[update.id], ...update.changes}
42+
}
43+
}
44+
}
45+
46+
function removePlot(store: State, id: number): State {
47+
const ids = store.ids.filter(plotId => plotId !== id);
48+
const entities = {...store.entities};
49+
delete entities[id];
50+
return { ids, entities }
51+
}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
import { WebSocketGateway } from '@nestjs/websockets';
2+
3+
@WebSocketGateway(81, { transports: ['websocket'] })
4+
export class DataGateway {
5+
6+
}
Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
export * from 'plotly.js';
22

3-
export * from './plots-container';
4-
export { Layout, Plot, IPlot } from './plot';
3+
4+
export { PlotsContainer } from './plots-container';
5+
export { Layout, Plot, PlotData } from './plot';
6+
export { EntityStore, Action } from './store';
Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,13 @@
1-
import { Layout as FullLayout, PlotData } from 'plotly.js';
1+
import { Layout as FullLayout, PlotData as PlotlyPlotData } from 'plotly.js';
22

3-
export type Plot = Partial<PlotData>;
3+
export type Plot = Partial<PlotlyPlotData>;
44
export type Layout = Partial<FullLayout>;
55

6-
export interface IPlot {
6+
export interface PlotData {
77
data: Plot[];
88
layout?: Layout;
99
}
10+
11+
export interface PlotEntities {
12+
[id: number]: PlotData;
13+
}
Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
1-
import { IPlot } from './plot';
1+
import { PlotData } from './plot';
22

3-
export interface IPlotsContainer {
3+
export interface PlotsContainer {
44
[id: number]: {
55
opened: boolean;
66
pending: boolean;
7-
plots: IPlot[];
7+
plots: PlotData[];
88
};
99
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
2+
export interface EntityStore<T> {
3+
ids: number[];
4+
entities: {[id: number]: T}
5+
}
6+
7+
export interface Action<T = unknown> {
8+
type: string;
9+
payload?: T;
10+
}
11+
12+
export interface Update<T = unknown> {
13+
id: number;
14+
changes: Partial<T>
15+
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import { Module } from '@nestjs/common';
2+
import { ServeStaticModule } from '@nestjs/serve-static';
3+
import { join } from 'path';
4+
import { DataGateway } from './data.gateway';
5+
6+
@Module({
7+
imports: [
8+
ServeStaticModule.forRoot({
9+
rootPath: join(__dirname, '..', '..', 'web')
10+
})
11+
],
12+
providers: [
13+
DataGateway
14+
]
15+
})
16+
export class NodeplotlibModule {}

libs/nodeplotlib/src/lib/nodeplotlib.ts

Lines changed: 42 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,42 +1,57 @@
1-
import * as express from 'express';
2-
import { Server } from 'http';
3-
import { Layout, Plot } from './models';
1+
import { INestApplication } from '@nestjs/common';
2+
import { NestFactory } from '@nestjs/core';
43
import { exec } from 'child_process';
54
import { type } from 'os';
6-
import { AddressInfo } from 'net';
7-
import { join } from 'path';
8-
let server: Server | null = null;
9-
const appFolder = join(__dirname, '..', '..', 'web');
5+
import { addPlot$ } from './+state/actions';
6+
import { Layout, Plot } from './models';
7+
import { NodeplotlibModule } from './nodeplotlib.module';
8+
let app: INestApplication|null = null;
109

11-
export function stack(data: Plot[], layout?: Layout) {
12-
//
10+
11+
/**
12+
* Plots the registered plots to a browser.
13+
* @param data
14+
* @param layout
15+
* @param cb
16+
*/
17+
export async function plot(data?: Plot[] | null, layout?: Layout) {
18+
addPlot$.next({ data, layout });
19+
20+
await bootstrap();
21+
const address = app.getHttpServer().address();
22+
openWindow(`http://localhost:${address.port}`);
1323
}
1424

25+
1526
/**
16-
* Start the webserver
17-
* Open the browser
27+
* Stacks plot data to a stack. When executing `plot`
28+
* the stack will also be plotted.
29+
* @param data
30+
* @param layout
1831
*/
19-
export function plot(data?: Plot[] | null, layout?: Layout) {
20-
clear();
21-
22-
const app = express();
23-
app.use('/', express.static(appFolder));
24-
25-
app.get('*', (req, res) => {
26-
res.status(200).sendFile(`/`, { root: appFolder });
27-
});
28-
server = app.listen(0, () => {
29-
console.log('Nodeplotlib server active');
30-
openWindow(`http://localhost:${(server.address() as AddressInfo).port}`);
31-
});
32+
export function stack(data: Plot[], layout?: Layout) {
33+
addPlot$.next({ data, layout });
3234
}
3335

34-
export function clear() {
35-
if (server) {
36-
server.close();
36+
37+
/**
38+
* Clears all stacked plots and shuts down the server if it
39+
* exists.
40+
*/
41+
export async function clear() {
42+
if (app) {
43+
await app.close();
3744
}
3845
}
3946

47+
48+
async function bootstrap() {
49+
await clear();
50+
app = await NestFactory.create(NodeplotlibModule);
51+
await app.listen(0);
52+
}
53+
54+
4055
function openWindow(location: string) {
4156
switch (type()) {
4257
case 'Linux':

0 commit comments

Comments
 (0)