mirror of
https://github.com/wavetermdev/waveterm.git
synced 2024-12-21 16:38:23 +01:00
Bootstrap layout on first launch (#186)
This commit is contained in:
parent
8ebde7e766
commit
74e86ef0cc
@ -149,6 +149,7 @@ tasks:
|
|||||||
- "pkg/wstore/*.go"
|
- "pkg/wstore/*.go"
|
||||||
- "pkg/wshrpc/**/*.go"
|
- "pkg/wshrpc/**/*.go"
|
||||||
- "pkg/tsgen/**/*.go"
|
- "pkg/tsgen/**/*.go"
|
||||||
|
- "pkg/eventbus/eventbus.go"
|
||||||
generates:
|
generates:
|
||||||
- frontend/types/gotypes.d.ts
|
- frontend/types/gotypes.d.ts
|
||||||
- pkg/wshrpc/wshclient/wshclient.go
|
- pkg/wshrpc/wshclient/wshclient.go
|
||||||
|
@ -11,6 +11,7 @@ import { getLayoutStateAtomForTab } from "frontend/layout/lib/layoutAtom";
|
|||||||
import { layoutTreeStateReducer } from "frontend/layout/lib/layoutState";
|
import { layoutTreeStateReducer } from "frontend/layout/lib/layoutState";
|
||||||
|
|
||||||
import { handleIncomingRpcMessage } from "@/app/store/wshrpc";
|
import { handleIncomingRpcMessage } from "@/app/store/wshrpc";
|
||||||
|
import { LayoutTreeInsertNodeAtIndexAction } from "@/layout/lib/model";
|
||||||
import { getWSServerEndpoint, getWebServerEndpoint } from "@/util/endpoints";
|
import { getWSServerEndpoint, getWebServerEndpoint } from "@/util/endpoints";
|
||||||
import * as layoututil from "@/util/layoututil";
|
import * as layoututil from "@/util/layoututil";
|
||||||
import { produce } from "immer";
|
import { produce } from "immer";
|
||||||
@ -247,28 +248,49 @@ function handleWSEventMessage(msg: WSEventType) {
|
|||||||
}
|
}
|
||||||
if (msg.eventtype == "layoutaction") {
|
if (msg.eventtype == "layoutaction") {
|
||||||
const layoutAction: WSLayoutActionData = msg.data;
|
const layoutAction: WSLayoutActionData = msg.data;
|
||||||
if (layoutAction.actiontype == LayoutTreeActionType.InsertNode) {
|
switch (layoutAction.actiontype) {
|
||||||
const insertNodeAction: LayoutTreeInsertNodeAction<TabLayoutData> = {
|
case LayoutTreeActionType.InsertNode: {
|
||||||
type: LayoutTreeActionType.InsertNode,
|
const insertNodeAction: LayoutTreeInsertNodeAction<TabLayoutData> = {
|
||||||
node: newLayoutNode<TabLayoutData>(undefined, undefined, undefined, {
|
type: LayoutTreeActionType.InsertNode,
|
||||||
blockId: layoutAction.blockid,
|
node: newLayoutNode<TabLayoutData>(undefined, undefined, undefined, {
|
||||||
}),
|
blockId: layoutAction.blockid,
|
||||||
};
|
}),
|
||||||
runLayoutAction(layoutAction.tabid, insertNodeAction);
|
};
|
||||||
} else if (layoutAction.actiontype == LayoutTreeActionType.DeleteNode) {
|
runLayoutAction(layoutAction.tabid, insertNodeAction);
|
||||||
const layoutStateAtom = getLayoutStateAtomForTab(
|
break;
|
||||||
layoutAction.tabid,
|
}
|
||||||
WOS.getWaveObjectAtom<Tab>(WOS.makeORef("tab", layoutAction.tabid))
|
case LayoutTreeActionType.DeleteNode: {
|
||||||
);
|
const layoutStateAtom = getLayoutStateAtomForTab(
|
||||||
const curState = globalStore.get(layoutStateAtom);
|
layoutAction.tabid,
|
||||||
const leafId = layoututil.findLeafIdFromBlockId(curState, layoutAction.blockid);
|
WOS.getWaveObjectAtom<Tab>(WOS.makeORef("tab", layoutAction.tabid))
|
||||||
const deleteNodeAction = {
|
);
|
||||||
type: LayoutTreeActionType.DeleteNode,
|
const curState = globalStore.get(layoutStateAtom);
|
||||||
nodeId: leafId,
|
const leafId = layoututil.findLeafIdFromBlockId(curState, layoutAction.blockid);
|
||||||
};
|
const deleteNodeAction = {
|
||||||
runLayoutAction(layoutAction.tabid, deleteNodeAction);
|
type: LayoutTreeActionType.DeleteNode,
|
||||||
} else {
|
nodeId: leafId,
|
||||||
console.log("unsupported layout action", layoutAction);
|
};
|
||||||
|
runLayoutAction(layoutAction.tabid, deleteNodeAction);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case LayoutTreeActionType.InsertNodeAtIndex: {
|
||||||
|
if (!layoutAction.indexarr) {
|
||||||
|
console.error("Cannot apply eventbus layout action InsertNodeAtIndex, indexarr field is missing.");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
const insertAction: LayoutTreeInsertNodeAtIndexAction<TabLayoutData> = {
|
||||||
|
type: LayoutTreeActionType.InsertNodeAtIndex,
|
||||||
|
node: newLayoutNode<TabLayoutData>(undefined, layoutAction.nodesize, undefined, {
|
||||||
|
blockId: layoutAction.blockid,
|
||||||
|
}),
|
||||||
|
indexArr: layoutAction.indexarr,
|
||||||
|
};
|
||||||
|
runLayoutAction(layoutAction.tabid, insertAction);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
console.log("unsupported layout action", layoutAction);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -26,6 +26,9 @@ class ClientServiceType {
|
|||||||
AgreeTos(): Promise<void> {
|
AgreeTos(): Promise<void> {
|
||||||
return WOS.callBackendService("client", "AgreeTos", Array.from(arguments))
|
return WOS.callBackendService("client", "AgreeTos", Array.from(arguments))
|
||||||
}
|
}
|
||||||
|
BootstrapStarterLayout(): Promise<void> {
|
||||||
|
return WOS.callBackendService("client", "BootstrapStarterLayout", Array.from(arguments))
|
||||||
|
}
|
||||||
FocusWindow(arg2: string): Promise<void> {
|
FocusWindow(arg2: string): Promise<void> {
|
||||||
return WOS.callBackendService("client", "FocusWindow", Array.from(arguments))
|
return WOS.callBackendService("client", "FocusWindow", Array.from(arguments))
|
||||||
}
|
}
|
||||||
@ -89,6 +92,9 @@ class ObjectServiceType {
|
|||||||
CreateBlock(blockDef: BlockDef, rtOpts: RuntimeOpts): Promise<string> {
|
CreateBlock(blockDef: BlockDef, rtOpts: RuntimeOpts): Promise<string> {
|
||||||
return WOS.callBackendService("object", "CreateBlock", Array.from(arguments))
|
return WOS.callBackendService("object", "CreateBlock", Array.from(arguments))
|
||||||
}
|
}
|
||||||
|
CreateBlock_NoUI(arg2: string, arg3: BlockDef, arg4: RuntimeOpts): Promise<Block> {
|
||||||
|
return WOS.callBackendService("object", "CreateBlock_NoUI", Array.from(arguments))
|
||||||
|
}
|
||||||
|
|
||||||
// @returns object updates
|
// @returns object updates
|
||||||
DeleteBlock(blockId: string): Promise<void> {
|
DeleteBlock(blockId: string): Promise<void> {
|
||||||
|
@ -226,6 +226,34 @@ export function findNextInsertLocation<T>(
|
|||||||
return { node: insertLoc?.node, index: insertLoc?.index };
|
return { node: insertLoc?.node, index: insertLoc?.index };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Traverse the layout tree using the supplied index array to find the node to insert at.
|
||||||
|
* @param node The node to start the search from.
|
||||||
|
* @param indexArr The array of indices to aid in the traversal.
|
||||||
|
* @returns The node to insert into and the index at which to insert.
|
||||||
|
*/
|
||||||
|
export function findInsertLocationFromIndexArr<T>(
|
||||||
|
node: LayoutNode<T>,
|
||||||
|
indexArr: number[]
|
||||||
|
): { node: LayoutNode<T>; index: number } {
|
||||||
|
function normalizeIndex(index: number) {
|
||||||
|
const childrenLength = node.children?.length ?? 1;
|
||||||
|
const lastChildIndex = childrenLength - 1;
|
||||||
|
if (index < 0) {
|
||||||
|
return childrenLength - Math.max(index, -childrenLength);
|
||||||
|
}
|
||||||
|
return Math.min(index, lastChildIndex);
|
||||||
|
}
|
||||||
|
if (indexArr.length == 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const nextIndex = normalizeIndex(indexArr.shift());
|
||||||
|
if (indexArr.length == 0 || !node.children) {
|
||||||
|
return { node, index: nextIndex };
|
||||||
|
}
|
||||||
|
return findInsertLocationFromIndexArr<T>(node.children[nextIndex], indexArr);
|
||||||
|
}
|
||||||
|
|
||||||
function findNextInsertLocationHelper<T>(
|
function findNextInsertLocationHelper<T>(
|
||||||
node: LayoutNode<T>,
|
node: LayoutNode<T>,
|
||||||
maxChildren: number,
|
maxChildren: number,
|
||||||
|
@ -6,6 +6,7 @@ import {
|
|||||||
addChildAt,
|
addChildAt,
|
||||||
addIntermediateNode,
|
addIntermediateNode,
|
||||||
balanceNode,
|
balanceNode,
|
||||||
|
findInsertLocationFromIndexArr,
|
||||||
findNextInsertLocation,
|
findNextInsertLocation,
|
||||||
findNode,
|
findNode,
|
||||||
findParent,
|
findParent,
|
||||||
@ -19,6 +20,7 @@ import {
|
|||||||
LayoutTreeComputeMoveNodeAction,
|
LayoutTreeComputeMoveNodeAction,
|
||||||
LayoutTreeDeleteNodeAction,
|
LayoutTreeDeleteNodeAction,
|
||||||
LayoutTreeInsertNodeAction,
|
LayoutTreeInsertNodeAction,
|
||||||
|
LayoutTreeInsertNodeAtIndexAction,
|
||||||
LayoutTreeMagnifyNodeToggleAction,
|
LayoutTreeMagnifyNodeToggleAction,
|
||||||
LayoutTreeMoveNodeAction,
|
LayoutTreeMoveNodeAction,
|
||||||
LayoutTreeResizeNodeAction,
|
LayoutTreeResizeNodeAction,
|
||||||
@ -97,6 +99,10 @@ function layoutTreeStateReducerInner<T>(layoutTreeState: LayoutTreeState<T>, act
|
|||||||
insertNode(layoutTreeState, action as LayoutTreeInsertNodeAction<T>);
|
insertNode(layoutTreeState, action as LayoutTreeInsertNodeAction<T>);
|
||||||
layoutTreeState.generation++;
|
layoutTreeState.generation++;
|
||||||
break;
|
break;
|
||||||
|
case LayoutTreeActionType.InsertNodeAtIndex:
|
||||||
|
insertNodeAtIndex(layoutTreeState, action as LayoutTreeInsertNodeAtIndexAction<T>);
|
||||||
|
layoutTreeState.generation++;
|
||||||
|
break;
|
||||||
case LayoutTreeActionType.DeleteNode:
|
case LayoutTreeActionType.DeleteNode:
|
||||||
deleteNode(layoutTreeState, action as LayoutTreeDeleteNodeAction);
|
deleteNode(layoutTreeState, action as LayoutTreeDeleteNodeAction);
|
||||||
layoutTreeState.generation++;
|
layoutTreeState.generation++;
|
||||||
@ -370,7 +376,7 @@ function moveNode<T>(layoutTreeState: LayoutTreeState<T>, action: LayoutTreeMove
|
|||||||
|
|
||||||
function insertNode<T>(layoutTreeState: LayoutTreeState<T>, action: LayoutTreeInsertNodeAction<T>) {
|
function insertNode<T>(layoutTreeState: LayoutTreeState<T>, action: LayoutTreeInsertNodeAction<T>) {
|
||||||
if (!action?.node) {
|
if (!action?.node) {
|
||||||
console.error("no insert node action provided");
|
console.error("insertNode cannot run, no insert node action provided");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (!layoutTreeState.rootNode) {
|
if (!layoutTreeState.rootNode) {
|
||||||
@ -386,6 +392,28 @@ function insertNode<T>(layoutTreeState: LayoutTreeState<T>, action: LayoutTreeIn
|
|||||||
layoutTreeState.leafs = leafs;
|
layoutTreeState.leafs = leafs;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function insertNodeAtIndex<T>(layoutTreeState: LayoutTreeState<T>, action: LayoutTreeInsertNodeAtIndexAction<T>) {
|
||||||
|
if (!action?.node || !action?.indexArr) {
|
||||||
|
console.error("insertNodeAtIndex cannot run, either node or indexArr field is missing");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!layoutTreeState.rootNode) {
|
||||||
|
const { node: balancedNode, leafs } = balanceNode(action.node);
|
||||||
|
layoutTreeState.rootNode = balancedNode;
|
||||||
|
layoutTreeState.leafs = leafs;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const insertLoc = findInsertLocationFromIndexArr(layoutTreeState.rootNode, action.indexArr);
|
||||||
|
if (!insertLoc) {
|
||||||
|
console.error("insertNodeAtIndex unable to find insert location");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
addChildAt(insertLoc.node, insertLoc.index + 1, action.node);
|
||||||
|
const { node: newRootNode, leafs } = balanceNode(layoutTreeState.rootNode);
|
||||||
|
layoutTreeState.rootNode = newRootNode;
|
||||||
|
layoutTreeState.leafs = leafs;
|
||||||
|
}
|
||||||
|
|
||||||
function swapNode<T>(layoutTreeState: LayoutTreeState<T>, action: LayoutTreeSwapNodeAction) {
|
function swapNode<T>(layoutTreeState: LayoutTreeState<T>, action: LayoutTreeSwapNodeAction) {
|
||||||
console.log("swapNode", layoutTreeState, action);
|
console.log("swapNode", layoutTreeState, action);
|
||||||
|
|
||||||
|
@ -41,6 +41,7 @@ export enum LayoutTreeActionType {
|
|||||||
ClearPendingAction = "clearpending",
|
ClearPendingAction = "clearpending",
|
||||||
ResizeNode = "resize",
|
ResizeNode = "resize",
|
||||||
InsertNode = "insert",
|
InsertNode = "insert",
|
||||||
|
InsertNodeAtIndex = "insertatindex",
|
||||||
DeleteNode = "delete",
|
DeleteNode = "delete",
|
||||||
MagnifyNodeToggle = "magnify",
|
MagnifyNodeToggle = "magnify",
|
||||||
}
|
}
|
||||||
@ -104,6 +105,22 @@ export interface LayoutTreeInsertNodeAction<T> extends LayoutTreeAction {
|
|||||||
node: LayoutNode<T>;
|
node: LayoutNode<T>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Action for inserting a node into the layout tree at the specified index.
|
||||||
|
*/
|
||||||
|
export interface LayoutTreeInsertNodeAtIndexAction<T> extends LayoutTreeAction {
|
||||||
|
type: LayoutTreeActionType.InsertNodeAtIndex;
|
||||||
|
/**
|
||||||
|
* The node to insert.
|
||||||
|
*/
|
||||||
|
node: LayoutNode<T>;
|
||||||
|
/**
|
||||||
|
* The array of indices to traverse when inserting the node.
|
||||||
|
* The last index is the index within the parent node where the node should be inserted.
|
||||||
|
*/
|
||||||
|
indexArr: number[];
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Action for deleting a node from the layout tree.
|
* Action for deleting a node from the layout tree.
|
||||||
*/
|
*/
|
||||||
|
2
frontend/types/gotypes.d.ts
vendored
2
frontend/types/gotypes.d.ts
vendored
@ -472,6 +472,8 @@ declare global {
|
|||||||
tabid: string;
|
tabid: string;
|
||||||
actiontype: string;
|
actiontype: string;
|
||||||
blockid: string;
|
blockid: string;
|
||||||
|
nodesize?: number;
|
||||||
|
indexarr?: number[];
|
||||||
};
|
};
|
||||||
|
|
||||||
// webcmd.WSRpcCommand
|
// webcmd.WSRpcCommand
|
||||||
|
@ -60,6 +60,8 @@ type WSLayoutActionData struct {
|
|||||||
TabId string `json:"tabid"`
|
TabId string `json:"tabid"`
|
||||||
ActionType string `json:"actiontype"`
|
ActionType string `json:"actiontype"`
|
||||||
BlockId string `json:"blockid"`
|
BlockId string `json:"blockid"`
|
||||||
|
NodeSize uint `json:"nodesize,omitempty"`
|
||||||
|
IndexArr []int `json:"indexarr,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
var globalLock = &sync.Mutex{}
|
var globalLock = &sync.Mutex{}
|
||||||
|
@ -6,8 +6,11 @@ package clientservice
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"log"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/wavetermdev/thenextwave/pkg/eventbus"
|
||||||
|
"github.com/wavetermdev/thenextwave/pkg/service/objectservice"
|
||||||
"github.com/wavetermdev/thenextwave/pkg/util/utilfn"
|
"github.com/wavetermdev/thenextwave/pkg/util/utilfn"
|
||||||
"github.com/wavetermdev/thenextwave/pkg/wstore"
|
"github.com/wavetermdev/thenextwave/pkg/wstore"
|
||||||
)
|
)
|
||||||
@ -86,5 +89,102 @@ func (cs *ClientService) AgreeTos(ctx context.Context) (wstore.UpdatesRtnType, e
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("error updating client data: %w", err)
|
return nil, fmt.Errorf("error updating client data: %w", err)
|
||||||
}
|
}
|
||||||
|
cs.BootstrapStarterLayout(ctx)
|
||||||
return wstore.ContextGetUpdatesRtn(ctx), nil
|
return wstore.ContextGetUpdatesRtn(ctx), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type PortableLayout []struct {
|
||||||
|
IndexArr []int
|
||||||
|
Size uint
|
||||||
|
BlockDef *wstore.BlockDef
|
||||||
|
}
|
||||||
|
|
||||||
|
func (cs *ClientService) BootstrapStarterLayout(ctx context.Context) error {
|
||||||
|
ctx, cancelFn := context.WithTimeout(ctx, 2*time.Second)
|
||||||
|
defer cancelFn()
|
||||||
|
client, err := wstore.DBGetSingleton[*wstore.Client](ctx)
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("unable to find client: %v\n", err)
|
||||||
|
return fmt.Errorf("unable to find client: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(client.WindowIds) < 1 {
|
||||||
|
return fmt.Errorf("error bootstrapping layout, no windows exist")
|
||||||
|
}
|
||||||
|
|
||||||
|
windowId := client.WindowIds[0]
|
||||||
|
|
||||||
|
window, err := wstore.DBMustGet[*wstore.Window](ctx, windowId)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("error getting window: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
tabId := window.ActiveTabId
|
||||||
|
|
||||||
|
starterLayout := PortableLayout{
|
||||||
|
{IndexArr: []int{0}, BlockDef: &wstore.BlockDef{
|
||||||
|
Meta: wstore.MetaMapType{
|
||||||
|
wstore.MetaKey_View: "term",
|
||||||
|
wstore.MetaKey_Controller: "shell",
|
||||||
|
},
|
||||||
|
}},
|
||||||
|
{IndexArr: []int{1}, BlockDef: &wstore.BlockDef{
|
||||||
|
Meta: wstore.MetaMapType{
|
||||||
|
wstore.MetaKey_View: "cpuplot",
|
||||||
|
},
|
||||||
|
}},
|
||||||
|
{IndexArr: []int{1, 1}, BlockDef: &wstore.BlockDef{
|
||||||
|
Meta: wstore.MetaMapType{
|
||||||
|
wstore.MetaKey_View: "web",
|
||||||
|
wstore.MetaKey_Url: "https://github.com/wavetermdev/waveterm",
|
||||||
|
},
|
||||||
|
}},
|
||||||
|
{IndexArr: []int{1, 2}, BlockDef: &wstore.BlockDef{
|
||||||
|
Meta: wstore.MetaMapType{
|
||||||
|
wstore.MetaKey_View: "preview",
|
||||||
|
wstore.MetaKey_File: "~",
|
||||||
|
},
|
||||||
|
}},
|
||||||
|
{IndexArr: []int{2}, BlockDef: &wstore.BlockDef{
|
||||||
|
Meta: wstore.MetaMapType{
|
||||||
|
wstore.MetaKey_View: "term",
|
||||||
|
wstore.MetaKey_Controller: "shell",
|
||||||
|
},
|
||||||
|
}},
|
||||||
|
{IndexArr: []int{2, 1}, BlockDef: &wstore.BlockDef{
|
||||||
|
Meta: wstore.MetaMapType{
|
||||||
|
wstore.MetaKey_View: "waveai",
|
||||||
|
},
|
||||||
|
}},
|
||||||
|
{IndexArr: []int{2, 2}, BlockDef: &wstore.BlockDef{
|
||||||
|
Meta: wstore.MetaMapType{
|
||||||
|
wstore.MetaKey_View: "web",
|
||||||
|
wstore.MetaKey_Url: "https://www.youtube.com/embed/cKqsw_sAsU8",
|
||||||
|
},
|
||||||
|
}},
|
||||||
|
}
|
||||||
|
|
||||||
|
objsvc := &objectservice.ObjectService{}
|
||||||
|
|
||||||
|
for i := 0; i < len(starterLayout); i++ {
|
||||||
|
layoutAction := starterLayout[i]
|
||||||
|
|
||||||
|
blockData, err := objsvc.CreateBlock_NoUI(ctx, tabId, layoutAction.BlockDef, &wstore.RuntimeOpts{})
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("unable to create block for starter layout: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
eventbus.SendEventToWindow(windowId, eventbus.WSEventType{
|
||||||
|
EventType: eventbus.WSEvent_LayoutAction,
|
||||||
|
Data: &eventbus.WSLayoutActionData{
|
||||||
|
ActionType: "insertatindex",
|
||||||
|
TabId: tabId,
|
||||||
|
BlockId: blockData.OID,
|
||||||
|
IndexArr: layoutAction.IndexArr,
|
||||||
|
NodeSize: layoutAction.Size,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
@ -178,6 +178,22 @@ func (svc *ObjectService) CreateBlock_Meta() tsgenmeta.MethodMeta {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (svc *ObjectService) CreateBlock_NoUI(ctx context.Context, tabId string, blockDef *wstore.BlockDef, rtOpts *wstore.RuntimeOpts) (*wstore.Block, error) {
|
||||||
|
blockData, err := wstore.CreateBlock(ctx, tabId, blockDef, rtOpts)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("error creating block: %w", err)
|
||||||
|
}
|
||||||
|
controllerName := blockData.Meta.GetString(wstore.MetaKey_Controller, "")
|
||||||
|
if controllerName != "" {
|
||||||
|
err = blockcontroller.StartBlockController(ctx, tabId, blockData.OID)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("error starting block controller: %w", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return blockData, nil
|
||||||
|
}
|
||||||
|
|
||||||
func (svc *ObjectService) CreateBlock(uiContext wstore.UIContext, blockDef *wstore.BlockDef, rtOpts *wstore.RuntimeOpts) (string, wstore.UpdatesRtnType, error) {
|
func (svc *ObjectService) CreateBlock(uiContext wstore.UIContext, blockDef *wstore.BlockDef, rtOpts *wstore.RuntimeOpts) (string, wstore.UpdatesRtnType, error) {
|
||||||
if uiContext.ActiveTabId == "" {
|
if uiContext.ActiveTabId == "" {
|
||||||
return "", nil, fmt.Errorf("no active tab")
|
return "", nil, fmt.Errorf("no active tab")
|
||||||
@ -185,17 +201,12 @@ func (svc *ObjectService) CreateBlock(uiContext wstore.UIContext, blockDef *wsto
|
|||||||
ctx, cancelFn := context.WithTimeout(context.Background(), DefaultTimeout)
|
ctx, cancelFn := context.WithTimeout(context.Background(), DefaultTimeout)
|
||||||
defer cancelFn()
|
defer cancelFn()
|
||||||
ctx = wstore.ContextWithUpdates(ctx)
|
ctx = wstore.ContextWithUpdates(ctx)
|
||||||
blockData, err := wstore.CreateBlock(ctx, uiContext.ActiveTabId, blockDef, rtOpts)
|
|
||||||
|
blockData, err := svc.CreateBlock_NoUI(ctx, uiContext.ActiveTabId, blockDef, rtOpts)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", nil, fmt.Errorf("error creating block: %w", err)
|
return "", nil, err
|
||||||
}
|
|
||||||
controllerName := blockData.Meta.GetString(wstore.MetaKey_Controller, "")
|
|
||||||
if controllerName != "" {
|
|
||||||
err = blockcontroller.StartBlockController(ctx, uiContext.ActiveTabId, blockData.OID)
|
|
||||||
if err != nil {
|
|
||||||
return "", nil, fmt.Errorf("error starting block controller: %w", err)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return blockData.OID, wstore.ContextGetUpdatesRtn(ctx), nil
|
return blockData.OID, wstore.ContextGetUpdatesRtn(ctx), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user