mirror of
https://github.com/wavetermdev/waveterm.git
synced 2024-12-22 16:48:23 +01:00
Merge branch 'red/tabs-new-design' of github.com:wavetermdev/waveterm into red/tabs-new-design
This commit is contained in:
commit
97d5071308
22
.github/dependabot.yml
vendored
22
.github/dependabot.yml
vendored
@ -1,24 +1,5 @@
|
||||
version: 2
|
||||
updates:
|
||||
- package-ecosystem: "npm"
|
||||
directory: "docs/"
|
||||
schedule:
|
||||
interval: "weekly"
|
||||
day: "friday"
|
||||
time: "09:00"
|
||||
timezone: "America/Los_Angeles"
|
||||
groups:
|
||||
docsite-dev-dependencies:
|
||||
dependency-type: "development"
|
||||
exclude-patterns:
|
||||
- "*docusaurus*"
|
||||
docsite-docusaurus:
|
||||
patterns:
|
||||
- "*docusaurus*"
|
||||
docsite-prod-dependencies:
|
||||
dependency-type: "production"
|
||||
exclude-patterns:
|
||||
- "*docusaurus*"
|
||||
- package-ecosystem: "npm"
|
||||
directory: "/"
|
||||
schedule:
|
||||
@ -43,6 +24,9 @@ updates:
|
||||
electron:
|
||||
patterns:
|
||||
- "*electron*"
|
||||
docusaurus:
|
||||
patterns:
|
||||
- "*docusaurus*"
|
||||
- package-ecosystem: "gomod"
|
||||
directory: "/"
|
||||
schedule:
|
||||
|
@ -87,7 +87,7 @@ tasks:
|
||||
- "dist/docsite/**/*"
|
||||
cmds:
|
||||
- cd docs && yarn build-embedded
|
||||
- task: copyfiles:'docs/build':'dist/docsite'
|
||||
- task: copyfiles:'docs/build/':'dist/docsite'
|
||||
deps:
|
||||
- yarn
|
||||
|
||||
|
@ -140,6 +140,7 @@ func beforeSendActivityUpdate(ctx context.Context) {
|
||||
activity := telemetry.ActivityUpdate{}
|
||||
activity.NumTabs, _ = wstore.DBGetCount[*waveobj.Tab](ctx)
|
||||
activity.NumBlocks, _ = wstore.DBGetCount[*waveobj.Block](ctx)
|
||||
activity.Blocks, _ = wstore.DBGetBlockViewCounts(ctx)
|
||||
activity.NumWindows, _ = wstore.DBGetCount[*waveobj.Window](ctx)
|
||||
activity.NumSSHConn = conncontroller.GetNumSSHHasConnected()
|
||||
activity.NumWSLConn = wsl.GetNumWSLHasConnected()
|
||||
|
@ -9,7 +9,7 @@ title: "Customization"
|
||||
<img
|
||||
title="Tab Context Menu"
|
||||
style={{ float: "right", margin: "0 0 10px 10px" }}
|
||||
src="/img/tab-context-menu.png"
|
||||
src="./img/tab-context-menu.png"
|
||||
width="300"
|
||||
/>
|
||||
|
||||
@ -24,7 +24,7 @@ It is also possible to create your own themes using custom colors, gradients, im
|
||||
<img
|
||||
title="Terminal Context Menu"
|
||||
style={{ float: "right", margin: "0 0 10px 10px" }}
|
||||
src="/img/terminal-context-menu.png"
|
||||
src="./img/terminal-context-menu.png"
|
||||
width="300"
|
||||
/>
|
||||
|
||||
@ -53,7 +53,7 @@ There is no UI to edit your default terminal font family. But, it _can_ be overr
|
||||
<img
|
||||
title="Terminal Context Menu"
|
||||
style={{ float: "right", margin: "0 0 10px 10px" }}
|
||||
src="/img/custom-widgets.png"
|
||||
src="./img/custom-widgets.png"
|
||||
width="120"
|
||||
/>
|
||||
|
||||
|
@ -49,7 +49,7 @@ You can move blocks by clicking on the block header and dragging the block aroun
|
||||
There are 7 different drop targets for any given block. A block is divided into quadrants along its diagonals. If the block is tiling as a row (left-to-right), dropping a block into the left or right quadrant will place the dropped block in the same level as the targeted block. This can be considered dropping the block inline. If you drop the block out of line (in quadrants corresponding to opposite tiling direction), the block will either be placed one level above or one level below the targeted block. Dropping the block towards the outside will place it in the same level as the target block's parent, while dropping it towards the center of the block will create a new level, where both the target block and the dropped block will be moved. The middle fifth of the block is reserved for the swap action. Dropping a block here will cause the target block and the dropped block to swap positions in the layout.
|
||||
|
||||
<video width="100%" height="100%" playsinline autoplay muted controls>
|
||||
<source src="/img/drag-move-24fps-crf43.mp4" type="video/mp4" />
|
||||
<source src="./img/drag-move-24fps-crf43.mp4" type="video/mp4" />
|
||||
</video>
|
||||
|
||||
#### Possible block movements
|
||||
@ -72,7 +72,7 @@ All block movements except for Swap will cause the rest of the layout to shift t
|
||||
### Resize a block
|
||||
|
||||
<video width="100%" height="100%" playsinline autoplay muted controls>
|
||||
<source src="/img/resize-24fps-crf43.mp4" type="video/mp4" />
|
||||
<source src="./img/resize-24fps-crf43.mp4" type="video/mp4" />
|
||||
</video>
|
||||
|
||||
![screenshot showing the line that appears when the cursor hovers over the margin of a block, indicating which blocks
|
||||
|
@ -84,10 +84,17 @@ The following configuration keys are available for use in presets:
|
||||
| display:name | string | the name to use when displaying the preset in a menu (required) |
|
||||
| display:order | float | the order in which the preset should be displayed in a menu (optional) |
|
||||
|
||||
:::info
|
||||
|
||||
Configs in a preset are applied in order to override the default config values, which will persist for the remainder of the tab or block's lifetime. Setting `bg:*` or `ai:*` to `"true"` will clear the values of any previously overridden Background or AI configurations, respectively, setting them back to their defaults. You almost always want to add these keys to your presets in order to create a clean slate and prevent previously set values from leaking in.
|
||||
|
||||
:::
|
||||
|
||||
#### AI configurations
|
||||
|
||||
| Key Name | Type | Function |
|
||||
| ------------- | ------ | -------------------------------------------------------------------------------------------------- |
|
||||
| ai:\* | bool | reset all existing ai keys |
|
||||
| ai:preset | string | the default AI preset to use |
|
||||
| ai:baseurl | string | Set the AI Base Url (must be OpenAI compatible) |
|
||||
| ai:apitoken | string | your AI api token |
|
||||
@ -103,15 +110,12 @@ The following configuration keys are available for use in presets:
|
||||
|
||||
| Key Name | Type | Function |
|
||||
| -------------------- | ------ | ----------------------------------------------------------------------------------------------- |
|
||||
| bg:\* | bool | reset all existing bg keys |
|
||||
| bg:opacity | float | the opacity of the background |
|
||||
| bg:blendmode | string | the [blend mode](https://developer.mozilla.org/en-US/docs/Web/CSS/blend-mode) of the background |
|
||||
| bg:bordercolor | string | the color of the border |
|
||||
| bg:activebordercolor | string | the color of the border when a block is active |
|
||||
|
||||
#### Clear key
|
||||
|
||||
Configs in a preset are applied in order to override the default config values, which will persist for the remainder of the tab or block's lifetime. Setting `bg:*` or `ai:*` to `"true"` will clear the values of any previously overridden Background or AI configurations, respectively, setting them back to their defaults.
|
||||
|
||||
#### Unset a default value
|
||||
|
||||
To unset a default value in a preset, add an override that sets it to an empty string, like `""`.
|
||||
|
@ -50,7 +50,7 @@ When telemetry is active, we collect the following data. It is stored in the `te
|
||||
| NumBlocks | The number of existing blocks open on a given day |
|
||||
| NumTabs | The number of existing tabs open on a given day. |
|
||||
| NewTab | The number of new tabs created on a given day |
|
||||
| NumWindows | The number of existing windows open on a give day. |
|
||||
| NumWindows | The number of existing windows open on a given day. |
|
||||
| NewTab | The number of new tabs opened on a given day. |
|
||||
| NumStartup | The number of times waveterm has been started on a given day. |
|
||||
| NumShutdown | The number of times waveterm has been shut down on a given day. |
|
||||
@ -61,6 +61,7 @@ When telemetry is active, we collect the following data. It is stored in the `te
|
||||
| NumWSLConns | The number of distinct WSL connections that have been made to distinct distros |
|
||||
| Renderers | The number of new block views of each type are open on a given day. |
|
||||
| WshCmds | The number of wsh commands of each type run on a given day |
|
||||
| Blocks | The number of blocks of different view types open on a given day |
|
||||
| Conn | The number of successful remote connections made (and errors) on a given day |
|
||||
|
||||
## Associated Data
|
||||
|
@ -15,13 +15,13 @@
|
||||
"typecheck": "tsc"
|
||||
},
|
||||
"dependencies": {
|
||||
"@docusaurus/core": "^3.6.1",
|
||||
"@docusaurus/plugin-content-docs": "^3.6.1",
|
||||
"@docusaurus/plugin-debug": "^3.6.1",
|
||||
"@docusaurus/plugin-ideal-image": "^3.6.1",
|
||||
"@docusaurus/plugin-sitemap": "^3.6.1",
|
||||
"@docusaurus/theme-classic": "^3.6.1",
|
||||
"@docusaurus/theme-search-algolia": "^3.6.1",
|
||||
"@docusaurus/core": "^3.6.3",
|
||||
"@docusaurus/plugin-content-docs": "^3.6.3",
|
||||
"@docusaurus/plugin-debug": "^3.6.3",
|
||||
"@docusaurus/plugin-ideal-image": "^3.6.3",
|
||||
"@docusaurus/plugin-sitemap": "^3.6.3",
|
||||
"@docusaurus/theme-classic": "^3.6.3",
|
||||
"@docusaurus/theme-search-algolia": "^3.6.3",
|
||||
"@mdx-js/react": "^3.0.0",
|
||||
"@waveterm/docusaurus-og": "https://github.com/wavetermdev/docusaurus-og",
|
||||
"clsx": "^2.1.1",
|
||||
@ -30,18 +30,18 @@
|
||||
"react-dom": "^18.0.0",
|
||||
"remark-gfm": "^4.0.0",
|
||||
"remark-typescript-code-import": "^1.0.1",
|
||||
"ua-parser-js": "^1.0.39"
|
||||
"ua-parser-js": "^2.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@docusaurus/module-type-aliases": "3.6.1",
|
||||
"@docusaurus/tsconfig": "3.6.1",
|
||||
"@docusaurus/types": "3.6.1",
|
||||
"@docusaurus/module-type-aliases": "3.6.3",
|
||||
"@docusaurus/tsconfig": "3.6.3",
|
||||
"@docusaurus/types": "3.6.3",
|
||||
"@eslint/js": "^9.15.0",
|
||||
"@mdx-js/typescript-plugin": "^0.0.6",
|
||||
"@types/eslint": "^9.6.1",
|
||||
"@types/eslint-config-prettier": "^6.11.3",
|
||||
"@types/ua-parser-js": "^0.7.39",
|
||||
"eslint": "^9.13.0",
|
||||
"eslint": "^9.15.0",
|
||||
"eslint-config-prettier": "^9.1.0",
|
||||
"eslint-plugin-mdx": "^3.1.5",
|
||||
"prettier": "^3.3.3",
|
||||
@ -52,8 +52,8 @@
|
||||
"remark-mdx": "^3.1.0",
|
||||
"remark-preset-lint-consistent": "^6.0.0",
|
||||
"remark-preset-lint-recommended": "^7.0.0",
|
||||
"typescript": "^5.6.3",
|
||||
"typescript-eslint": "^8.14.0"
|
||||
"typescript": "^5.7.2",
|
||||
"typescript-eslint": "^8.15.0"
|
||||
},
|
||||
"resolutions": {
|
||||
"path-to-regexp@npm:2.2.1": "^3",
|
||||
|
@ -15,7 +15,6 @@ const baseUrlRegex = /http[s]?:\/\/([^:\/])+(:\d+)?/;
|
||||
class HelpViewModel extends WebViewModel {
|
||||
constructor(blockId: string, nodeModel: BlockNodeModel) {
|
||||
super(blockId, nodeModel);
|
||||
this.getSettingsMenuItems = undefined;
|
||||
this.viewText = atom((get) => {
|
||||
// force a dependency on meta.url so we re-render the buttons when the url changes
|
||||
get(this.blockAtom)?.meta?.url || get(this.homepageUrl);
|
||||
@ -58,6 +57,23 @@ class HelpViewModel extends WebViewModel {
|
||||
return newUrl;
|
||||
};
|
||||
}
|
||||
|
||||
getSettingsMenuItems(): ContextMenuItem[] {
|
||||
return [
|
||||
{
|
||||
label: this.webviewRef.current?.isDevToolsOpened() ? "Close DevTools" : "Open DevTools",
|
||||
click: async () => {
|
||||
if (this.webviewRef.current) {
|
||||
if (this.webviewRef.current.isDevToolsOpened()) {
|
||||
this.webviewRef.current.closeDevTools();
|
||||
} else {
|
||||
this.webviewRef.current.openDevTools();
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
function makeHelpViewModel(blockId: string, nodeModel: BlockNodeModel) {
|
||||
|
1
frontend/types/gotypes.d.ts
vendored
1
frontend/types/gotypes.d.ts
vendored
@ -32,6 +32,7 @@ declare global {
|
||||
buildtime?: string;
|
||||
displays?: ActivityDisplayType[];
|
||||
renderers?: {[key: string]: number};
|
||||
blocks?: {[key: string]: number};
|
||||
wshcmds?: {[key: string]: number};
|
||||
conn?: {[key: string]: number};
|
||||
};
|
||||
|
2
go.mod
2
go.mod
@ -16,7 +16,7 @@ require (
|
||||
github.com/kevinburke/ssh_config v1.2.0
|
||||
github.com/mattn/go-sqlite3 v1.14.24
|
||||
github.com/mitchellh/mapstructure v1.5.0
|
||||
github.com/sashabaranov/go-openai v1.35.6
|
||||
github.com/sashabaranov/go-openai v1.35.7
|
||||
github.com/sawka/txwrap v0.2.0
|
||||
github.com/shirou/gopsutil/v4 v4.24.10
|
||||
github.com/skeema/knownhosts v1.3.0
|
||||
|
4
go.sum
4
go.sum
@ -58,8 +58,8 @@ github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZN
|
||||
github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c h1:ncq/mPwQF4JjgDlrVEn3C11VoGHZN7m8qihwgMEtzYw=
|
||||
github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE=
|
||||
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||
github.com/sashabaranov/go-openai v1.35.6 h1:oi0rwCvyxMxgFALDGnyqFTyCJm6n72OnEG3sybIFR0g=
|
||||
github.com/sashabaranov/go-openai v1.35.6/go.mod h1:lj5b/K+zjTSFxVLijLSTDZuP7adOgerWeFyZLUhAKRg=
|
||||
github.com/sashabaranov/go-openai v1.35.7 h1:icyrRbkYoKPa4rbO1WSInpJu3qDQrPEnsoJVZ6QymdI=
|
||||
github.com/sashabaranov/go-openai v1.35.7/go.mod h1:lj5b/K+zjTSFxVLijLSTDZuP7adOgerWeFyZLUhAKRg=
|
||||
github.com/sawka/txwrap v0.2.0 h1:V3LfvKVLULxcYSxdMguLwFyQFMEU9nFDJopg0ZkL+94=
|
||||
github.com/sawka/txwrap v0.2.0/go.mod h1:wwQ2SQiN4U+6DU/iVPhbvr7OzXAtgZlQCIGuvOswEfA=
|
||||
github.com/shirou/gopsutil/v4 v4.24.10 h1:7VOzPtfw/5YDU+jLEoBwXwxJbQetULywoSV4RYY7HkM=
|
||||
|
30
package.json
30
package.json
@ -30,19 +30,19 @@
|
||||
"@chromatic-com/storybook": "^3.2.2",
|
||||
"@eslint/js": "^9.15.0",
|
||||
"@rollup/plugin-node-resolve": "^15.3.0",
|
||||
"@storybook/addon-essentials": "^8.4.4",
|
||||
"@storybook/addon-interactions": "^8.4.4",
|
||||
"@storybook/addon-links": "^8.4.4",
|
||||
"@storybook/blocks": "^8.4.4",
|
||||
"@storybook/react": "^8.4.4",
|
||||
"@storybook/react-vite": "^8.4.4",
|
||||
"@storybook/test": "^8.4.4",
|
||||
"@storybook/theming": "^8.4.4",
|
||||
"@storybook/addon-essentials": "^8.4.5",
|
||||
"@storybook/addon-interactions": "^8.4.5",
|
||||
"@storybook/addon-links": "^8.4.5",
|
||||
"@storybook/blocks": "^8.4.5",
|
||||
"@storybook/react": "^8.4.5",
|
||||
"@storybook/react-vite": "^8.4.5",
|
||||
"@storybook/test": "^8.4.5",
|
||||
"@storybook/theming": "^8.4.5",
|
||||
"@types/color": "^4.2.0",
|
||||
"@types/css-tree": "^2",
|
||||
"@types/debug": "^4",
|
||||
"@types/electron": "^1.6.12",
|
||||
"@types/node": "^22.8.7",
|
||||
"@types/node": "^22.9.1",
|
||||
"@types/papaparse": "^5",
|
||||
"@types/pngjs": "^6.0.5",
|
||||
"@types/prop-types": "^15",
|
||||
@ -60,7 +60,7 @@
|
||||
"electron": "^33.2.0",
|
||||
"electron-builder": "^25.1.8",
|
||||
"electron-vite": "^2.3.0",
|
||||
"eslint": "^9.14.0",
|
||||
"eslint": "^9.15.0",
|
||||
"eslint-config-prettier": "^9.1.0",
|
||||
"prettier": "^3.3.3",
|
||||
"prettier-plugin-jsdoc": "^1.3.0",
|
||||
@ -68,18 +68,18 @@
|
||||
"rollup-plugin-flow": "^1.1.1",
|
||||
"sass": "^1.81.0",
|
||||
"semver": "^7.6.3",
|
||||
"storybook": "^8.4.4",
|
||||
"storybook": "^8.4.5",
|
||||
"storybook-dark-mode": "^4.0.2",
|
||||
"ts-node": "^10.9.2",
|
||||
"tslib": "^2.8.1",
|
||||
"tsx": "^4.19.2",
|
||||
"typescript": "^5.6.3",
|
||||
"typescript-eslint": "^8.14.0",
|
||||
"typescript": "^5.7.2",
|
||||
"typescript-eslint": "^8.15.0",
|
||||
"vite": "^5.4.11",
|
||||
"vite-plugin-image-optimizer": "^1.1.8",
|
||||
"vite-plugin-static-copy": "^2.1.0",
|
||||
"vite-plugin-svgr": "^4.3.0",
|
||||
"vite-tsconfig-paths": "^5.1.2",
|
||||
"vite-tsconfig-paths": "^5.1.3",
|
||||
"vitest": "^2.1.5"
|
||||
},
|
||||
"dependencies": {
|
||||
@ -140,7 +140,7 @@
|
||||
"use-device-pixel-ratio": "^1.1.2",
|
||||
"winston": "^3.17.0",
|
||||
"ws": "^8.18.0",
|
||||
"yaml": "^2.6.0"
|
||||
"yaml": "^2.6.1"
|
||||
},
|
||||
"resolutions": {
|
||||
"send@npm:0.18.0": "0.19.0",
|
||||
|
@ -44,6 +44,7 @@ type ActivityUpdate struct {
|
||||
BuildTime string `json:"buildtime,omitempty"`
|
||||
Displays []ActivityDisplayType `json:"displays,omitempty"`
|
||||
Renderers map[string]int `json:"renderers,omitempty"`
|
||||
Blocks map[string]int `json:"blocks,omitempty"`
|
||||
WshCmds map[string]int `json:"wshcmds,omitempty"`
|
||||
Conn map[string]int `json:"conn,omitempty"`
|
||||
}
|
||||
@ -77,6 +78,7 @@ type TelemetryData struct {
|
||||
SetTabTheme int `json:"settabtheme,omitempty"`
|
||||
Displays []ActivityDisplayType `json:"displays,omitempty"`
|
||||
Renderers map[string]int `json:"renderers,omitempty"`
|
||||
Blocks map[string]int `json:"blocks,omitempty"`
|
||||
WshCmds map[string]int `json:"wshcmds,omitempty"`
|
||||
Conn map[string]int `json:"conn,omitempty"`
|
||||
}
|
||||
@ -185,6 +187,9 @@ func UpdateActivity(ctx context.Context, update ActivityUpdate) error {
|
||||
if len(update.Displays) > 0 {
|
||||
tdata.Displays = update.Displays
|
||||
}
|
||||
if len(update.Blocks) > 0 {
|
||||
tdata.Blocks = update.Blocks
|
||||
}
|
||||
query = `UPDATE db_activity
|
||||
SET tdata = ?,
|
||||
clientversion = ?,
|
||||
|
@ -471,10 +471,26 @@ func UseEffect(ctx context.Context, fn func() func(), deps []any) {
|
||||
|
||||
func numToString[T any](value T) (string, bool) {
|
||||
switch v := any(value).(type) {
|
||||
case int, int8, int16, int32, int64:
|
||||
return strconv.FormatInt(v.(int64), 10), true
|
||||
case uint, uint8, uint16, uint32, uint64:
|
||||
return strconv.FormatUint(v.(uint64), 10), true
|
||||
case int:
|
||||
return strconv.FormatInt(int64(v), 10), true
|
||||
case int8:
|
||||
return strconv.FormatInt(int64(v), 10), true
|
||||
case int16:
|
||||
return strconv.FormatInt(int64(v), 10), true
|
||||
case int32:
|
||||
return strconv.FormatInt(int64(v), 10), true
|
||||
case int64:
|
||||
return strconv.FormatInt(v, 10), true
|
||||
case uint:
|
||||
return strconv.FormatUint(uint64(v), 10), true
|
||||
case uint8:
|
||||
return strconv.FormatUint(uint64(v), 10), true
|
||||
case uint16:
|
||||
return strconv.FormatUint(uint64(v), 10), true
|
||||
case uint32:
|
||||
return strconv.FormatUint(uint64(v), 10), true
|
||||
case uint64:
|
||||
return strconv.FormatUint(v, 10), true
|
||||
case float32:
|
||||
return strconv.FormatFloat(float64(v), 'f', -1, 32), true
|
||||
case float64:
|
||||
|
@ -8,6 +8,7 @@ import (
|
||||
"fmt"
|
||||
"log"
|
||||
"reflect"
|
||||
"regexp"
|
||||
"time"
|
||||
|
||||
"github.com/wavetermdev/waveterm/pkg/filestore"
|
||||
@ -44,6 +45,26 @@ func DBGetCount[T waveobj.WaveObj](ctx context.Context) (int, error) {
|
||||
})
|
||||
}
|
||||
|
||||
var viewRe = regexp.MustCompile(`^[a-z0-9]{1,20}$`)
|
||||
|
||||
func DBGetBlockViewCounts(ctx context.Context) (map[string]int, error) {
|
||||
return WithTxRtn(ctx, func(tx *TxWrap) (map[string]int, error) {
|
||||
query := `SELECT COALESCE(json_extract(data, '$.meta.view'), '') AS view FROM db_block`
|
||||
views := tx.SelectStrings(query)
|
||||
rtn := make(map[string]int)
|
||||
for _, view := range views {
|
||||
if view == "" {
|
||||
continue
|
||||
}
|
||||
if !viewRe.MatchString(view) {
|
||||
continue
|
||||
}
|
||||
rtn[view]++
|
||||
}
|
||||
return rtn, nil
|
||||
})
|
||||
}
|
||||
|
||||
type idDataType struct {
|
||||
OId string
|
||||
Version int
|
||||
|
@ -10,3 +10,5 @@ steps:
|
||||
text: Get Started
|
||||
description: button to complete onboarding
|
||||
action: click
|
||||
- command: assert
|
||||
expect: the cpu usage graph is being displayed
|
||||
|
Loading…
Reference in New Issue
Block a user