-
Notifications
You must be signed in to change notification settings - Fork 486
add tsunami view in wave #2350
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
Merged
Merged
add tsunami view in wave #2350
Changes from 15 commits
Commits
Show all changes
22 commits
Select commit
Hold shift + click to select a range
afc886f
add new tsunami view type
sawka 6b4337d
pull a clientid off the URL
sawka 8fe056c
some tsunami meta
sawka d0c94c8
nodepath option in tsunami. use nodepath to run tailwind instead of npx
sawka be31657
pass the electron exec path through to wavesrv, use for tsunami
sawka 3d96c1c
switch to apppath (from appdir)
sawka 3b309ff
big refactor of ugly blockcontroller code. MUCH cleaner surface to i…
sawka 8307089
movefilesback flag and TsunamiBuildInternal exposed
sawka 074d671
checkpoint on running tsunami apps
sawka fabf284
tsunami port in status
sawka d7b0755
check for abs path
sawka 4203d80
getting there with the tsunami widget
sawka bc9e8e6
working tsunami app in wave
sawka cd10f88
tsunami apps, autoload (resync), fix logging, fix sse handling (if mu…
sawka e2aa49f
just keep package.json for scaffold as a template...
sawka 567110e
consolidate copying from apppath in one func instead of spread to the…
sawka 12fa501
support zip files (.tsapp), run and then a new package command to bui…
sawka 3c8233b
fix dependencies
sawka 725b959
misc changes, tighten up iframe, add more simple tags, etc
sawka a61f838
more minor cleanups
sawka 81c966d
Merge remote-tracking branch 'origin/main' into sawka/tsunami-view
sawka 92c1a91
remove some code duplication
sawka File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -485,6 +485,19 @@ tasks: | |
cmds: | ||
- task: tsunami:scaffold:internal | ||
|
||
tsunami:scaffold:packagejson: | ||
desc: Create package.json for tsunami scaffold using npm commands | ||
dir: tsunami/frontend/scaffold | ||
cmds: | ||
- cmd: "{{.RM}} package.json" | ||
ignore_error: true | ||
- npm --no-workspaces init -y --init-license Apache-2.0 | ||
- npm pkg set name=tsunami-scaffold | ||
- npm pkg delete author | ||
- npm pkg set author.name="Command Line Inc" | ||
- npm pkg set author.email="[email protected]" | ||
- npm --no-workspaces install [email protected] @tailwindcss/[email protected] | ||
|
||
tsunami:scaffold:internal: | ||
desc: Internal task to create scaffold directory structure | ||
dir: tsunami/frontend | ||
|
@@ -493,12 +506,8 @@ tasks: | |
- cmd: "{{.RMRF}} scaffold" | ||
ignore_error: true | ||
- mkdir scaffold | ||
- cd scaffold && npm --no-workspaces init -y --init-license Apache-2.0 | ||
- cd scaffold && npm pkg set name=tsunami-scaffold | ||
- cd scaffold && npm pkg delete author | ||
- cd scaffold && npm pkg set author.name="Command Line Inc" | ||
- cd scaffold && npm pkg set author.email="[email protected]" | ||
- cd scaffold && npm --no-workspaces install tailwindcss @tailwindcss/cli | ||
- cp ../templates/package.json.tmpl scaffold/package.json | ||
- cd scaffold && npm install | ||
- cp -r dist scaffold/ | ||
- cp ../templates/app-main.go.tmpl scaffold/app-main.go | ||
- cp ../templates/tailwind.css scaffold/ | ||
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,175 @@ | ||
// Copyright 2025, Command Line Inc. | ||
// SPDX-License-Identifier: Apache-2.0 | ||
|
||
import { BlockNodeModel } from "@/app/block/blocktypes"; | ||
import { atoms, globalStore, WOS } from "@/app/store/global"; | ||
import { waveEventSubscribe } from "@/app/store/wps"; | ||
import { RpcApi } from "@/app/store/wshclientapi"; | ||
import { TabRpcClient } from "@/app/store/wshrpcutil"; | ||
import * as services from "@/store/services"; | ||
import * as jotai from "jotai"; | ||
import { memo, useEffect } from "react"; | ||
|
||
class TsunamiViewModel implements ViewModel { | ||
viewType: string; | ||
blockAtom: jotai.Atom<Block>; | ||
blockId: string; | ||
viewIcon: jotai.Atom<string>; | ||
viewName: jotai.Atom<string>; | ||
shellProcFullStatus: jotai.PrimitiveAtom<BlockControllerRuntimeStatus>; | ||
shellProcStatusUnsubFn: () => void; | ||
isRestarting: jotai.PrimitiveAtom<boolean>; | ||
|
||
constructor(blockId: string, nodeModel: BlockNodeModel) { | ||
this.viewType = "tsunami"; | ||
this.blockId = blockId; | ||
this.blockAtom = WOS.getWaveObjectAtom<Block>(`block:${blockId}`); | ||
this.viewIcon = jotai.atom("cube"); | ||
this.viewName = jotai.atom("Tsunami"); | ||
this.isRestarting = jotai.atom(false); | ||
|
||
this.shellProcFullStatus = jotai.atom(null) as jotai.PrimitiveAtom<BlockControllerRuntimeStatus>; | ||
const initialShellProcStatus = services.BlockService.GetControllerStatus(blockId); | ||
initialShellProcStatus.then((rts) => { | ||
this.updateShellProcStatus(rts); | ||
}); | ||
this.shellProcStatusUnsubFn = waveEventSubscribe({ | ||
eventType: "controllerstatus", | ||
scope: WOS.makeORef("block", blockId), | ||
handler: (event) => { | ||
let bcRTS: BlockControllerRuntimeStatus = event.data; | ||
this.updateShellProcStatus(bcRTS); | ||
}, | ||
}); | ||
} | ||
|
||
get viewComponent(): ViewComponent { | ||
return TsunamiView; | ||
} | ||
|
||
updateShellProcStatus(fullStatus: BlockControllerRuntimeStatus) { | ||
console.log("tsunami-status", fullStatus); | ||
if (fullStatus == null) { | ||
return; | ||
} | ||
const curStatus = globalStore.get(this.shellProcFullStatus); | ||
if (curStatus == null || curStatus.version < fullStatus.version) { | ||
globalStore.set(this.shellProcFullStatus, fullStatus); | ||
} | ||
} | ||
|
||
triggerRestartAtom() { | ||
globalStore.set(this.isRestarting, true); | ||
setTimeout(() => { | ||
globalStore.set(this.isRestarting, false); | ||
}, 300); | ||
} | ||
|
||
resyncController() { | ||
const prtn = RpcApi.ControllerResyncCommand(TabRpcClient, { | ||
tabid: globalStore.get(atoms.staticTabId), | ||
blockid: this.blockId, | ||
forcerestart: false, | ||
}); | ||
prtn.catch((e) => console.log("error controller resync", e)); | ||
} | ||
|
||
forceRestartController() { | ||
if (globalStore.get(this.isRestarting)) { | ||
return; | ||
} | ||
this.triggerRestartAtom(); | ||
const prtn = RpcApi.ControllerResyncCommand(TabRpcClient, { | ||
tabid: globalStore.get(atoms.staticTabId), | ||
blockid: this.blockId, | ||
forcerestart: true, | ||
}); | ||
prtn.catch((e) => console.log("error controller resync (force restart)", e)); | ||
} | ||
|
||
dispose() { | ||
if (this.shellProcStatusUnsubFn) { | ||
this.shellProcStatusUnsubFn(); | ||
} | ||
} | ||
|
||
getSettingsMenuItems(): ContextMenuItem[] { | ||
return []; | ||
} | ||
} | ||
|
||
type TsunamiViewProps = { | ||
model: TsunamiViewModel; | ||
}; | ||
|
||
const TsunamiView = memo(({ model }: TsunamiViewProps) => { | ||
const shellProcFullStatus = jotai.useAtomValue(model.shellProcFullStatus); | ||
const blockData = jotai.useAtomValue(model.blockAtom); | ||
const isRestarting = jotai.useAtomValue(model.isRestarting); | ||
|
||
useEffect(() => { | ||
model.resyncController(); | ||
}, [model]); | ||
|
||
const appPath = blockData?.meta?.["tsunami:apppath"]; | ||
const controller = blockData?.meta?.controller; | ||
|
||
// Check for configuration errors | ||
const errors = []; | ||
if (!appPath) { | ||
errors.push("App path must be set (tsunami:apppath)"); | ||
} | ||
if (controller !== "tsunami") { | ||
errors.push("Invalid controller (must be 'tsunami')"); | ||
} | ||
|
||
// Show errors if any exist | ||
if (errors.length > 0) { | ||
return ( | ||
<div className="w-full h-full flex flex-col items-center justify-center gap-4"> | ||
<h1 className="text-4xl font-bold text-main-text-color">Tsunami</h1> | ||
<div className="flex flex-col gap-2"> | ||
{errors.map((error, index) => ( | ||
<div key={index} className="text-sm" style={{ color: "var(--color-error)" }}> | ||
{error} | ||
</div> | ||
))} | ||
</div> | ||
</div> | ||
); | ||
} | ||
|
||
// Check if we should show the iframe | ||
const shouldShowIframe = | ||
shellProcFullStatus?.shellprocstatus === "running" && | ||
shellProcFullStatus?.tsunamiport && | ||
shellProcFullStatus.tsunamiport !== 0; | ||
|
||
if (shouldShowIframe) { | ||
const iframeUrl = `http://localhost:${shellProcFullStatus.tsunamiport}/?clientid=wave:${model.blockId}`; | ||
return <iframe src={iframeUrl} className="w-full h-full border-0" title="Tsunami Application" name={`tsunami:${model.blockId}`} />; | ||
} | ||
|
||
const status = shellProcFullStatus?.shellprocstatus ?? "init"; | ||
const isNotRunning = status === "done" || status === "init"; | ||
|
||
return ( | ||
<div className="w-full h-full flex flex-col items-center justify-center gap-4"> | ||
<h1 className="text-4xl font-bold text-main-text-color">Tsunami</h1> | ||
{appPath && <div className="text-sm text-main-text-color opacity-70">{appPath}</div>} | ||
{isNotRunning && !isRestarting && ( | ||
<button | ||
onClick={() => model.forceRestartController()} | ||
className="px-4 py-2 bg-accent-color text-primary-text-color rounded hover:bg-accent-color/80 transition-colors cursor-pointer" | ||
> | ||
Start | ||
</button> | ||
)} | ||
{isRestarting && <div className="text-sm text-success-color">Starting...</div>} | ||
</div> | ||
); | ||
}); | ||
|
||
TsunamiView.displayName = "TsunamiView"; | ||
|
||
export { TsunamiViewModel }; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
*.old |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.