split out react UI
This commit is contained in:
parent
74603cba65
commit
618c0013ee
156
index.html
156
index.html
@ -3,165 +3,11 @@
|
|||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8">
|
||||||
<meta content="width=device-width, initial-scale=1" name="viewport"/>
|
<meta content="width=device-width, initial-scale=1" name="viewport"/>
|
||||||
|
<link href="/styles.css" rel="stylesheet">
|
||||||
<link href="/assets/favicon-32x32.png" rel="icon" sizes="32x32" type="image/png">
|
<link href="/assets/favicon-32x32.png" rel="icon" sizes="32x32" type="image/png">
|
||||||
<link href="/assets/favicon-16x16.png" rel="icon" sizes="16x16" type="image/png">
|
<link href="/assets/favicon-16x16.png" rel="icon" sizes="16x16" type="image/png">
|
||||||
<link href="/assets/favicon-96x96.png" rel="icon" sizes="96x96" type="image/png">
|
<link href="/assets/favicon-96x96.png" rel="icon" sizes="96x96" type="image/png">
|
||||||
<title>Deep Diagram</title>
|
<title>Deep Diagram</title>
|
||||||
<style>
|
|
||||||
body {
|
|
||||||
width: 100vw;
|
|
||||||
height: 100vh;
|
|
||||||
margin: 0px;
|
|
||||||
padding: 0px;
|
|
||||||
aspect-ratio: auto;
|
|
||||||
font-family: Roboto, sans-serif;
|
|
||||||
font-size: large;
|
|
||||||
color: #4444ee;
|
|
||||||
}
|
|
||||||
|
|
||||||
.scene {
|
|
||||||
width: 100vw;
|
|
||||||
height: 100vh;
|
|
||||||
overflow: hidden;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
#gameCanvas {
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
margin: 0px;
|
|
||||||
padding: 0px;
|
|
||||||
background: transparent;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
div.overlay {
|
|
||||||
position: absolute;
|
|
||||||
background: #000;
|
|
||||||
left: 50%;
|
|
||||||
top: 50%;
|
|
||||||
transform: translate(-50%, -50%);
|
|
||||||
z-index: 12;
|
|
||||||
width: 320px;
|
|
||||||
height: 300px;
|
|
||||||
}
|
|
||||||
|
|
||||||
div.overlay div {
|
|
||||||
background-color: #000000;
|
|
||||||
color: #FFD700;
|
|
||||||
padding: 15px 25px;
|
|
||||||
text-align: center;
|
|
||||||
text-decoration: none;
|
|
||||||
cursor: pointer;
|
|
||||||
border: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
div.overlay div a {
|
|
||||||
display: inline-block;
|
|
||||||
text-decoration: none;
|
|
||||||
border-color: #FFD700;
|
|
||||||
border-style: solid;
|
|
||||||
border-width: 1px;
|
|
||||||
padding: 10px;
|
|
||||||
width: 200px;
|
|
||||||
}
|
|
||||||
|
|
||||||
div.overlay div a:visited, div.overlay div a:link {
|
|
||||||
color: white;
|
|
||||||
}
|
|
||||||
|
|
||||||
div.overlay div a:hover {
|
|
||||||
background-color: #FFD700;
|
|
||||||
color: #000000;
|
|
||||||
}
|
|
||||||
|
|
||||||
div.overlay div a {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
div.overlay input {
|
|
||||||
display: inline-block;
|
|
||||||
margin: 10px auto;
|
|
||||||
text-decoration: none;
|
|
||||||
border-color: #FFD700;
|
|
||||||
border-style: solid;
|
|
||||||
border-width: 1px;
|
|
||||||
padding: 10px;
|
|
||||||
width: 200px;
|
|
||||||
}
|
|
||||||
|
|
||||||
div#create {
|
|
||||||
left: 50%;
|
|
||||||
top: 60%;
|
|
||||||
transform: translate(-50%, -50%);
|
|
||||||
z-index: 12;
|
|
||||||
width: 320px;
|
|
||||||
height: 344px;
|
|
||||||
border: 3px inset #FFD700;
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
div.overlay div a.cancel {
|
|
||||||
font-size: small;
|
|
||||||
font-weight: lighter;
|
|
||||||
font-style: italic;
|
|
||||||
background-color: #222211;
|
|
||||||
color: #EEC755;
|
|
||||||
}
|
|
||||||
|
|
||||||
div.overlay div a.cancel:hover {
|
|
||||||
background-color: #EEC700;
|
|
||||||
color: #000000;
|
|
||||||
}
|
|
||||||
|
|
||||||
#download {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
#main.mini {
|
|
||||||
left: 100px;
|
|
||||||
top: 200px;
|
|
||||||
width: 160px;
|
|
||||||
}
|
|
||||||
|
|
||||||
#main.mini img, #tutorial img {
|
|
||||||
width: 160px;
|
|
||||||
height: 60px;
|
|
||||||
}
|
|
||||||
|
|
||||||
#main.mini div a, #tutorial div a {
|
|
||||||
width: 80px;
|
|
||||||
}
|
|
||||||
|
|
||||||
#tutorial h1 {
|
|
||||||
font-size: x-large;
|
|
||||||
font-weight: bolder;
|
|
||||||
text-align: center;
|
|
||||||
color: #F9F9E9;
|
|
||||||
}
|
|
||||||
|
|
||||||
#tutorial {
|
|
||||||
z-index: 15;
|
|
||||||
left: 100px;
|
|
||||||
top: 560px;
|
|
||||||
width: 160px;
|
|
||||||
height: 210px;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#closekey, #closekey a:active, #closekey a:visited, #closekey a:link {
|
|
||||||
position: relative;
|
|
||||||
color: #ffffff;
|
|
||||||
}
|
|
||||||
|
|
||||||
#loadingGrid {
|
|
||||||
z-index: -1;
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
</style>
|
|
||||||
|
|
||||||
<link as="script" href="/newRelic.js" rel="preload">
|
<link as="script" href="/newRelic.js" rel="preload">
|
||||||
<script src="/newRelic.js"></script>
|
<script src="/newRelic.js"></script>
|
||||||
<meta content="width=device-width, initial-scale=1, height=device-height" name="viewport">
|
<meta content="width=device-width, initial-scale=1, height=device-height" name="viewport">
|
||||||
|
|||||||
188
public/styles.css
Normal file
188
public/styles.css
Normal file
@ -0,0 +1,188 @@
|
|||||||
|
body {
|
||||||
|
width: 100vw;
|
||||||
|
height: 100vh;
|
||||||
|
margin: 0px;
|
||||||
|
padding: 0px;
|
||||||
|
aspect-ratio: auto;
|
||||||
|
font-family: Roboto, sans-serif;
|
||||||
|
font-size: large;
|
||||||
|
color: #4444ee;
|
||||||
|
}
|
||||||
|
|
||||||
|
.scene {
|
||||||
|
width: 100vw;
|
||||||
|
height: 100vh;
|
||||||
|
overflow: hidden;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#gameCanvas {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
margin: 0px;
|
||||||
|
padding: 0px;
|
||||||
|
background: transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
div.overlay {
|
||||||
|
position: absolute;
|
||||||
|
background: #000;
|
||||||
|
left: 50%;
|
||||||
|
top: 50%;
|
||||||
|
transform: translate(-50%, -50%);
|
||||||
|
z-index: 12;
|
||||||
|
width: 320px;
|
||||||
|
height: 120px;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.overlay div {
|
||||||
|
background-color: #000000;
|
||||||
|
color: #FFD700;
|
||||||
|
padding: 15px 25px;
|
||||||
|
text-align: center;
|
||||||
|
text-decoration: none;
|
||||||
|
cursor: pointer;
|
||||||
|
border: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.overlay div a {
|
||||||
|
display: inline-block;
|
||||||
|
text-decoration: none;
|
||||||
|
border-color: #FFD700;
|
||||||
|
border-style: solid;
|
||||||
|
border-width: 1px;
|
||||||
|
padding: 10px;
|
||||||
|
width: 200px;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.overlay div a:visited, div.overlay div a:link {
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.overlay div a:hover {
|
||||||
|
background-color: #FFD700;
|
||||||
|
color: #000000;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.overlay div a {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
div.overlay input {
|
||||||
|
display: inline-block;
|
||||||
|
margin: 10px auto;
|
||||||
|
text-decoration: none;
|
||||||
|
border-color: #FFD700;
|
||||||
|
border-style: solid;
|
||||||
|
border-width: 1px;
|
||||||
|
padding: 10px;
|
||||||
|
width: 200px;
|
||||||
|
}
|
||||||
|
|
||||||
|
div#create {
|
||||||
|
left: 600px;
|
||||||
|
top: 400px;
|
||||||
|
transform: translate(-50%, -50%);
|
||||||
|
z-index: 14;
|
||||||
|
width: 320px;
|
||||||
|
height: 344px;
|
||||||
|
border: 3px inset #FFD700;
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.overlay div a.cancel {
|
||||||
|
font-size: small;
|
||||||
|
font-weight: lighter;
|
||||||
|
font-style: italic;
|
||||||
|
background-color: #222211;
|
||||||
|
color: #EEC755;
|
||||||
|
}
|
||||||
|
|
||||||
|
#diagramListContent ul {
|
||||||
|
list-style-type: none;
|
||||||
|
text-align: left;
|
||||||
|
padding: 0;
|
||||||
|
padding-inline-start: 0;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#diagramList {
|
||||||
|
overflow: scroll;
|
||||||
|
}
|
||||||
|
|
||||||
|
#diagramList > h1 {
|
||||||
|
width: 100%;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
#diagramListContent li {
|
||||||
|
margin: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#diagramListContent li a {
|
||||||
|
width: 90%;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.overlay div a.cancel:hover {
|
||||||
|
background-color: #EEC700;
|
||||||
|
color: #000000;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#main.mini {
|
||||||
|
left: 100px;
|
||||||
|
top: 200px;
|
||||||
|
width: 160px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#main.mini img, #tutorial img {
|
||||||
|
width: 160px;
|
||||||
|
height: 60px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#main.mini div a, #tutorial div a {
|
||||||
|
width: 80px;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1 {
|
||||||
|
font-size: x-large;
|
||||||
|
font-weight: bolder;
|
||||||
|
text-align: center;
|
||||||
|
color: #F9F9E9;
|
||||||
|
}
|
||||||
|
|
||||||
|
#tutorial {
|
||||||
|
z-index: 15;
|
||||||
|
left: 100px;
|
||||||
|
top: 560px;
|
||||||
|
width: 160px;
|
||||||
|
height: 210px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#diagramList {
|
||||||
|
left: 340px;
|
||||||
|
top: 240px;
|
||||||
|
height: 300px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#create {
|
||||||
|
left: 500px;
|
||||||
|
top: 340px;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#closekey, #closekey a:active, #closekey a:visited, #closekey a:link {
|
||||||
|
position: relative;
|
||||||
|
color: #ffffff;
|
||||||
|
}
|
||||||
|
|
||||||
|
#enterXR {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
#loadingGrid {
|
||||||
|
z-index: -1;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
@ -11,11 +11,9 @@ import {
|
|||||||
import {ControllerEventType, Controllers} from "./controllers";
|
import {ControllerEventType, Controllers} from "./controllers";
|
||||||
import log from "loglevel";
|
import log from "loglevel";
|
||||||
import {DiagramManager} from "../diagram/diagramManager";
|
import {DiagramManager} from "../diagram/diagramManager";
|
||||||
import {DiagramListingMenu} from "../menus/diagramListingMenu";
|
|
||||||
import {RoundButton} from "../objects/roundButton";
|
import {RoundButton} from "../objects/roundButton";
|
||||||
|
|
||||||
export class Right extends Base {
|
export class Right extends Base {
|
||||||
private listingMenu: DiagramListingMenu;
|
|
||||||
|
|
||||||
private startPosition: Vector3 = null;
|
private startPosition: Vector3 = null;
|
||||||
|
|
||||||
@ -42,7 +40,6 @@ export class Right extends Base {
|
|||||||
controllers: Controllers,
|
controllers: Controllers,
|
||||||
) {
|
) {
|
||||||
super(controller, scene, xr, controllers, diagramManager);
|
super(controller, scene, xr, controllers, diagramManager);
|
||||||
this.listingMenu = new DiagramListingMenu(this.scene, xr, this.controllers, diagramManager);
|
|
||||||
this.controller.onMotionControllerInitObservable.add((init) => {
|
this.controller.onMotionControllerInitObservable.add((init) => {
|
||||||
this.initTrigger(init.components['xr-standard-trigger']);
|
this.initTrigger(init.components['xr-standard-trigger']);
|
||||||
if (init.components['a-button']) {
|
if (init.components['a-button']) {
|
||||||
|
|||||||
@ -14,12 +14,11 @@ import {toDiagramEntity} from "./functions/toDiagramEntity";
|
|||||||
import {v4 as uuidv4} from 'uuid';
|
import {v4 as uuidv4} from 'uuid';
|
||||||
import {buildEntityActionManager} from "./functions/buildEntityActionManager";
|
import {buildEntityActionManager} from "./functions/buildEntityActionManager";
|
||||||
import {isDiagramEntity} from "./functions/isDiagramEntity";
|
import {isDiagramEntity} from "./functions/isDiagramEntity";
|
||||||
import {DiagramListingEvent} from "./types/diagramListing";
|
|
||||||
|
|
||||||
|
|
||||||
export class DiagramManager {
|
export class DiagramManager {
|
||||||
public readonly onDiagramEventObservable: Observable<DiagramEvent> = new Observable();
|
public readonly onDiagramEventObservable: Observable<DiagramEvent> = new Observable();
|
||||||
public readonly onDiagramEventListingObservable: Observable<DiagramListingEvent> = new Observable();
|
|
||||||
private readonly logger = log.getLogger('DiagramManager');
|
private readonly logger = log.getLogger('DiagramManager');
|
||||||
private readonly toolbox: Toolbox;
|
private readonly toolbox: Toolbox;
|
||||||
private readonly scene: Scene;
|
private readonly scene: Scene;
|
||||||
@ -68,12 +67,6 @@ export class DiagramManager {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
//@TODO Refactor
|
|
||||||
/*public setPersistenceManager(persistenceManager: IPersistenceManager) {
|
|
||||||
this.persistenceManager = persistenceManager;
|
|
||||||
this._config = new AppConfig(persistenceManager);
|
|
||||||
this.persistenceManager.updateObserver.add(this.onRemoteEvent, -1, true, this);
|
|
||||||
}*/
|
|
||||||
public createCopy(mesh: AbstractMesh, copy: boolean = false): AbstractMesh {
|
public createCopy(mesh: AbstractMesh, copy: boolean = false): AbstractMesh {
|
||||||
let newMesh;
|
let newMesh;
|
||||||
if (!mesh.isAnInstance) {
|
if (!mesh.isAnInstance) {
|
||||||
@ -97,13 +90,6 @@ export class DiagramManager {
|
|||||||
if (this.config.current?.physicsEnabled) {
|
if (this.config.current?.physicsEnabled) {
|
||||||
applyPhysics(this.sounds, newMesh, this.scene);
|
applyPhysics(this.sounds, newMesh, this.scene);
|
||||||
}
|
}
|
||||||
//@TODO Refactor
|
|
||||||
/*this.onDiagramEventObservable.notifyObservers({
|
|
||||||
type: DiagramEventType.ADD,
|
|
||||||
entity: toDiagramEntity(newMesh)
|
|
||||||
}, 2);*/
|
|
||||||
//this.persistenceManager.add(toDiagramEntity(newMesh));
|
|
||||||
|
|
||||||
return newMesh;
|
return newMesh;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,18 +0,0 @@
|
|||||||
export enum DiagramListingEventType {
|
|
||||||
GET,
|
|
||||||
ADD,
|
|
||||||
REMOVE,
|
|
||||||
MODIFY,
|
|
||||||
GETALL,
|
|
||||||
}
|
|
||||||
|
|
||||||
export type DiagramListingEvent = {
|
|
||||||
type: DiagramListingEventType;
|
|
||||||
listing?: DiagramListing;
|
|
||||||
}
|
|
||||||
export type DiagramListing = {
|
|
||||||
id: string;
|
|
||||||
name: string;
|
|
||||||
description?: string;
|
|
||||||
sharekey?: string;
|
|
||||||
}
|
|
||||||
@ -6,8 +6,6 @@ import {v4 as uuidv4} from 'uuid';
|
|||||||
import axios from "axios";
|
import axios from "axios";
|
||||||
import {DiagramManager} from "../diagram/diagramManager";
|
import {DiagramManager} from "../diagram/diagramManager";
|
||||||
import log, {Logger} from "loglevel";
|
import log, {Logger} from "loglevel";
|
||||||
import {DiagramListing, DiagramListingEventType} from "../diagram/types/diagramListing";
|
|
||||||
|
|
||||||
|
|
||||||
export class PouchdbPersistenceManager {
|
export class PouchdbPersistenceManager {
|
||||||
configObserver: Observable<AppConfigType> = new Observable<AppConfigType>();
|
configObserver: Observable<AppConfigType> = new Observable<AppConfigType>();
|
||||||
@ -16,30 +14,14 @@ export class PouchdbPersistenceManager {
|
|||||||
//implement IPersistenceManager interface with pouchdb apis
|
//implement IPersistenceManager interface with pouchdb apis
|
||||||
private db: PouchDB;
|
private db: PouchDB;
|
||||||
private remote: PouchDB;
|
private remote: PouchDB;
|
||||||
private config: PouchDB;
|
|
||||||
private diagramListings: PouchDB;
|
private diagramListings: PouchDB;
|
||||||
private readonly logger: Logger = log.getLogger('PouchdbPersistenceManager');
|
private readonly logger: Logger = log.getLogger('PouchdbPersistenceManager');
|
||||||
constructor() {
|
constructor() {
|
||||||
this.config = new PouchDB("config");
|
|
||||||
this.diagramListings = new PouchDB("diagramListings");
|
this.diagramListings = new PouchDB("diagramListings");
|
||||||
}
|
}
|
||||||
|
|
||||||
public async getDiagramListings() {
|
|
||||||
return this.diagramListings.allDocs({include_docs: true});
|
|
||||||
}
|
|
||||||
public setDiagramManager(diagramManager: DiagramManager) {
|
public setDiagramManager(diagramManager: DiagramManager) {
|
||||||
diagramManager.onDiagramEventListingObservable.add((evt) => {
|
|
||||||
if (evt.type == DiagramListingEventType.GETALL) {
|
|
||||||
this.diagramListings.allDocs({include_docs: true}).then((all) => {
|
|
||||||
for (const entity of all.rows) {
|
|
||||||
diagramManager.onDiagramEventListingObservable.notifyObservers({
|
|
||||||
type: DiagramListingEventType.ADD,
|
|
||||||
listing: {id: entity.doc._id, name: entity.doc.name}
|
|
||||||
}, -1, false, this);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}, -1, false, this);
|
|
||||||
diagramManager.onDiagramEventObservable.add((evt) => {
|
diagramManager.onDiagramEventObservable.add((evt) => {
|
||||||
switch (evt.type) {
|
switch (evt.type) {
|
||||||
case DiagramEventType.CHANGECOLOR:
|
case DiagramEventType.CHANGECOLOR:
|
||||||
@ -125,34 +107,6 @@ export class PouchdbPersistenceManager {
|
|||||||
this.logger.error(err);
|
this.logger.error(err);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public async addDiagram(diagram: DiagramListing) {
|
|
||||||
try {
|
|
||||||
const doc = await this.diagramListings.get(diagram.id);
|
|
||||||
|
|
||||||
} catch (err) {
|
|
||||||
this.diagramListings.put({...diagram, _id: diagram.id});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public async removeDiagram(diagram: DiagramListing) {
|
|
||||||
try {
|
|
||||||
this.diagramListings.delete(diagram.id);
|
|
||||||
} catch (err) {
|
|
||||||
this.logger.error(err);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public async modifyDiagram(diagram: DiagramListing) {
|
|
||||||
try {
|
|
||||||
const doc = await this.db.get(diagram.id);
|
|
||||||
this.db.put({...doc, ...diagram});
|
|
||||||
} catch (err) {
|
|
||||||
this.logger.error(err);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public async getNewRelicData(): Promise<any[]> {
|
public async getNewRelicData(): Promise<any[]> {
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
@ -161,25 +115,23 @@ export class PouchdbPersistenceManager {
|
|||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async setConfig(config: any, initial: boolean = false): Promise<any> {
|
public async setConfig(config: AppConfigType, initial: boolean = false) {
|
||||||
if (!initial) {
|
if (!initial) {
|
||||||
const doc = await this.config.get('1');
|
localStorage.setItem('config', JSON.stringify(config));
|
||||||
const newConf = {...config, _id: '1', _rev: doc._rev};
|
|
||||||
return this.config.put(newConf);
|
|
||||||
} else {
|
} else {
|
||||||
const newConf = {...config, _id: '1'};
|
localStorage.setItem('config', JSON.stringify(config));
|
||||||
return this.config.put(newConf);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public async getConfig(): Promise<any> {
|
public getConfig(): AppConfigType {
|
||||||
return this.config.get('1');
|
return JSON.parse(localStorage.getItem('config')) as AppConfigType;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async initialize() {
|
public async initialize() {
|
||||||
try {
|
try {
|
||||||
let current = this.getPath();
|
let current = this.getPath();
|
||||||
const config = await this.config.get('1');
|
const configString = localStorage.getItem('config');
|
||||||
|
const config = JSON.parse(configString) as AppConfigType;
|
||||||
|
|
||||||
if (!current && config.currentDiagramId) {
|
if (!current && config.currentDiagramId) {
|
||||||
this.db = new PouchDB(config.currentDiagramId);
|
this.db = new PouchDB(config.currentDiagramId);
|
||||||
@ -192,7 +144,7 @@ export class PouchdbPersistenceManager {
|
|||||||
}
|
}
|
||||||
this.db = new PouchDB(config.currentDiagramId);
|
this.db = new PouchDB(config.currentDiagramId);
|
||||||
await this.beginSync(config.currentDiagramId);
|
await this.beginSync(config.currentDiagramId);
|
||||||
await this.config.put(config);
|
localStorage.setItem('config', JSON.stringify(config));
|
||||||
}
|
}
|
||||||
this.configObserver.notifyObservers(config);
|
this.configObserver.notifyObservers(config);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
@ -264,10 +216,6 @@ export class PouchdbPersistenceManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
setCurrentDiagram(diagram: DiagramListing) {
|
|
||||||
this.currentDiagramId = diagram.id;
|
|
||||||
}
|
|
||||||
|
|
||||||
sync() {
|
sync() {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,94 +0,0 @@
|
|||||||
import {AbstractMesh, MeshBuilder, Scene, Vector3, WebXRDefaultExperience} from "@babylonjs/core";
|
|
||||||
import {AbstractMenu} from "./abstractMenu";
|
|
||||||
import {ControllerEventType, Controllers} from "../controllers/controllers";
|
|
||||||
import {AdvancedDynamicTexture, Button, Control, ScrollViewer, StackPanel, TextBlock} from "@babylonjs/gui";
|
|
||||||
import {setMenuPosition} from "../util/functions/setMenuPosition";
|
|
||||||
import {DiagramManager} from "../diagram/diagramManager";
|
|
||||||
import {DiagramListingEvent, DiagramListingEventType} from "../diagram/types/diagramListing";
|
|
||||||
import {DiagramEventType} from "../diagram/types/diagramEntity";
|
|
||||||
|
|
||||||
|
|
||||||
export class DiagramListingMenu extends AbstractMenu {
|
|
||||||
private mesh: AbstractMesh;
|
|
||||||
private panel: StackPanel;
|
|
||||||
private readonly diagramManager: DiagramManager;
|
|
||||||
|
|
||||||
constructor(scene: Scene, xr: WebXRDefaultExperience, controllers: Controllers, diagramManager: DiagramManager) {
|
|
||||||
super(scene, xr, controllers);
|
|
||||||
this.diagramManager = diagramManager;
|
|
||||||
this.buildMenu();
|
|
||||||
this.controllers.controllerObserver.add((event) => {
|
|
||||||
if (event.type == ControllerEventType.B_BUTTON) {
|
|
||||||
this.toggle();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
public toggle() {
|
|
||||||
setMenuPosition(this.handle.mesh, this.scene, new Vector3(0, .4, 0));
|
|
||||||
this.mesh.isVisible = !this.mesh.isVisible;
|
|
||||||
this.populateData();
|
|
||||||
(this.mesh.parent as AbstractMesh).isVisible = this.mesh.isVisible;
|
|
||||||
}
|
|
||||||
|
|
||||||
public populateData() {
|
|
||||||
this.panel.clearControls();
|
|
||||||
this.diagramManager.onDiagramEventListingObservable.notifyObservers({type: DiagramListingEventType.GETALL}, -1);
|
|
||||||
}
|
|
||||||
|
|
||||||
private buildMenu() {
|
|
||||||
const configPlane = MeshBuilder
|
|
||||||
.CreatePlane("gridSizePlane",
|
|
||||||
{
|
|
||||||
width: 1,
|
|
||||||
height: .5
|
|
||||||
}, this.scene);
|
|
||||||
this.mesh = configPlane;
|
|
||||||
this.createHandle(this.mesh);
|
|
||||||
this.mesh.position = new Vector3(0, .32, 0);
|
|
||||||
const configTexture = AdvancedDynamicTexture.CreateForMesh(configPlane, 2048, 1024);
|
|
||||||
|
|
||||||
configTexture.background = "white";
|
|
||||||
const scrollViewer = new ScrollViewer('diagramListingScroll');
|
|
||||||
configTexture.addControl(scrollViewer);
|
|
||||||
this.panel = new StackPanel('diagramListingStack');
|
|
||||||
scrollViewer.addControl(this.panel);
|
|
||||||
|
|
||||||
//configPlane.position.y = .5;
|
|
||||||
setMenuPosition(this.handle.mesh, this.scene, new Vector3(0, .4, 0));
|
|
||||||
this.mesh.isVisible = false;
|
|
||||||
(this.mesh.parent as AbstractMesh).isVisible = false;
|
|
||||||
this.diagramManager.onDiagramEventListingObservable.add((event: DiagramListingEvent) => {
|
|
||||||
if (event.type == DiagramListingEventType.ADD) {
|
|
||||||
this.addRow(event.listing.id, event.listing.name);
|
|
||||||
}
|
|
||||||
}, -1, false, this);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
private addRow(id: string, name: string) {
|
|
||||||
const row = new StackPanel('diagramListingRow ' + id);
|
|
||||||
row.isVertical = false;
|
|
||||||
row.height = "68px";
|
|
||||||
row.width = 1;
|
|
||||||
this.panel.addControl(row);
|
|
||||||
const selectButton = Button.CreateSimpleButton('diagramListingText ' + id, id);
|
|
||||||
selectButton.height = "64px";
|
|
||||||
selectButton.horizontalAlignment = Control.HORIZONTAL_ALIGNMENT_LEFT;
|
|
||||||
selectButton.width = "220px";
|
|
||||||
selectButton.color = "white";
|
|
||||||
selectButton.fontSize = "48px";
|
|
||||||
selectButton.background = "#333333";
|
|
||||||
selectButton.onPointerClickObservable.add(() => {
|
|
||||||
this.diagramManager.onDiagramEventObservable.notifyObservers({type: DiagramEventType.RESET});
|
|
||||||
console.log(id);
|
|
||||||
}, -1, false, this);
|
|
||||||
const textBlock = new TextBlock('diagramListingText ' + name, 'Diagram ' + name);
|
|
||||||
textBlock.width = "1000px";
|
|
||||||
textBlock.horizontalAlignment = Control.HORIZONTAL_ALIGNMENT_LEFT;
|
|
||||||
textBlock.textHorizontalAlignment = Control.HORIZONTAL_ALIGNMENT_LEFT;
|
|
||||||
textBlock.fontSize = "48px";
|
|
||||||
row.addControl(selectButton);
|
|
||||||
row.addControl(textBlock);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,26 +1,34 @@
|
|||||||
import {useState} from "react";
|
import {useEffect, useState} from "react";
|
||||||
|
|
||||||
function MainMenu({onClick}) {
|
function MainMenu({onClick}) {
|
||||||
return (
|
return (
|
||||||
<div className="overlay mini" id="main" onClick={onClick}>
|
<div className="overlay mini" id="main">
|
||||||
<img height="120" src="/assets/ddd.svg" width="320"/>
|
<img height="120" src="/assets/ddd.svg" width="320"/>
|
||||||
<div id="startCreate"><a href="#" id="startCreateLink">Start</a></div>
|
<div id="diagrams"><a href="#" id="diagramsLink" onClick={onClick}>Diagrams</a></div>
|
||||||
|
<div id="enterXR"><a href="#" id="enterVRLink">Enter VR</a></div>
|
||||||
<div id="download"><a href="#" id="downloadLink">Download Model</a></div>
|
<div id="download"><a href="#" id="downloadLink">Download Model</a></div>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
function CreateMenu({display}) {
|
function CreateMenu({display, toggleCreateMenu}) {
|
||||||
|
const onCreateClick = (evt) => {
|
||||||
|
evt.preventDefault();
|
||||||
|
const name = (document.querySelector('#createName') as HTMLInputElement).value;
|
||||||
|
if (name && name.length > 4) {
|
||||||
|
document.location.href = '/db/' + name;
|
||||||
|
} else {
|
||||||
|
window.alert('Name must be longer than 4 characters');
|
||||||
|
}
|
||||||
|
}
|
||||||
return (
|
return (
|
||||||
<div className="overlay" id="create" style={{'display': display}}>
|
<div className="overlay" id="create" style={{'display': display}}>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<div><input id="createName" placeholder="Enter a name for your diagram" type="text"/></div>
|
<div><input id="createName" placeholder="Enter a name for your diagram" type="text"/></div>
|
||||||
<div><input id="createPassword" placeholder="Enter a password (optional)" type="text"/></div>
|
<div><input id="createPassword" placeholder="Enter a password (optional)" type="text"/></div>
|
||||||
<div><a href="#" id="createActionLink">Create</a></div>
|
<div><a href="#" id="createActionLink" onClick={onCreateClick}>Create</a></div>
|
||||||
<div><a className="cancel" href="#" id="cancelCreateLink">Cancel</a></div>
|
<div><a className="cancel" onClick={toggleCreateMenu} href="#" id="cancelCreateLink">Cancel</a></div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -30,7 +38,6 @@ function TutorialMenu({onClick}) {
|
|||||||
<div className="overlay" id="tutorial">
|
<div className="overlay" id="tutorial">
|
||||||
<h1>Help</h1>
|
<h1>Help</h1>
|
||||||
<div id="desktopTutorial"><a href="#" id="desktopLink" onClick={onClick}>Desktop</a></div>
|
<div id="desktopTutorial"><a href="#" id="desktopLink" onClick={onClick}>Desktop</a></div>
|
||||||
<div id="questTutorial"><a href="#" id="questLink">Quest</a></div>
|
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -45,15 +52,26 @@ function KeyboardHelp({display, onClick}) {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
function DiagramList() {
|
function DiagramList({display, onClick}) {
|
||||||
|
const [dbList, setDbList] = useState([]);
|
||||||
|
useEffect(() => {
|
||||||
|
const listDb = async () => {
|
||||||
|
const data = await indexedDB.databases();
|
||||||
|
setDbList(data.filter((item) => item.name.indexOf('_pouch_') > -1).map((item) => {
|
||||||
|
return {name: item.name.replace('_pouch_', '')}
|
||||||
|
}));
|
||||||
|
};
|
||||||
|
listDb();
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="overlay" id="diagramList" style={{'left': '500px'}}>
|
<div className="overlay" id="diagramList" style={{'display': display}}>
|
||||||
<h1>Existing Diagrams</h1>
|
<h1>Diagrams</h1>
|
||||||
|
<div id="startCreate"><a href="#" id="startCreateLink" onClick={onClick}>New</a></div>
|
||||||
<div id="diagramListContent">
|
<div id="diagramListContent">
|
||||||
<ul>
|
<ul>
|
||||||
<li><a href="/db/ddd">ddd</a></li>
|
{dbList.map((item) => <li><a href={`/db/${item.name}`}>{item.name}</a></li>)}
|
||||||
<li><a href="/db/ddd2">ddd2</a></li>
|
|
||||||
<li><a href="/db/ddd3">ddd3</a></li>
|
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -64,21 +82,30 @@ function Menu() {
|
|||||||
|
|
||||||
const [createState, setCreateState] = useState('none');
|
const [createState, setCreateState] = useState('none');
|
||||||
const [desktopTutorialState, setDesktopTutorialState] = useState('none');
|
const [desktopTutorialState, setDesktopTutorialState] = useState('none');
|
||||||
|
const [diagramListState, setDiagramListState] = useState('none');
|
||||||
|
|
||||||
function handleCreateClick() {
|
function handleCreateClick(evt: React.MouseEvent<HTMLAnchorElement>) {
|
||||||
|
evt.preventDefault();
|
||||||
setCreateState(createState == 'none' ? 'block' : 'none');
|
setCreateState(createState == 'none' ? 'block' : 'none');
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleDesktopTutorialClick() {
|
function handleDesktopTutorialClick(evt: React.MouseEvent<HTMLAnchorElement>) {
|
||||||
|
evt.preventDefault();
|
||||||
setDesktopTutorialState(desktopTutorialState == 'none' ? 'block' : 'none');
|
setDesktopTutorialState(desktopTutorialState == 'none' ? 'block' : 'none');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function handleDiagramListClick(evt: React.MouseEvent<HTMLAnchorElement>) {
|
||||||
|
evt.preventDefault();
|
||||||
|
setDiagramListState(diagramListState == 'none' ? 'block' : 'none');
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<MainMenu onClick={handleCreateClick}/>
|
<MainMenu onClick={handleDiagramListClick}/>
|
||||||
<TutorialMenu onClick={handleDesktopTutorialClick}/>
|
<TutorialMenu onClick={handleDesktopTutorialClick}/>
|
||||||
<CreateMenu display={createState}/>
|
<CreateMenu display={createState} toggleCreateMenu={handleCreateClick}/>
|
||||||
<KeyboardHelp display={desktopTutorialState} onClick={handleDesktopTutorialClick}/>
|
<KeyboardHelp display={desktopTutorialState} onClick={handleDesktopTutorialClick}/>
|
||||||
|
<DiagramList onClick={handleCreateClick} display={diagramListState}/>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -89,8 +116,6 @@ export default function WebApp() {
|
|||||||
<Menu/>
|
<Menu/>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
const create = document.querySelector('#startCreateLink');
|
const create = document.querySelector('#startCreateLink');
|
||||||
|
|||||||
@ -2,4 +2,4 @@ import {createRoot} from "react-dom/client";
|
|||||||
import WebApp from "./react/webApp";
|
import WebApp from "./react/webApp";
|
||||||
|
|
||||||
const root = createRoot(document.getElementById('webApp'));
|
const root = createRoot(document.getElementById('webApp'));
|
||||||
root.render(WebApp());
|
root.render(WebApp());
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user