---
title: Webview setup
---
classDiagram
AltimateWebviewProvider <|-- InsightsPanel : extends
<<Baseclass>> AltimateWebviewProvider
note for InsightsPanel "Mandatory overrides: \n viewType\n viewType\n description"
note for InsightsPanel "Optional overrides: \n handleCommand"
AltimateWebviewProvider <|-- DocumentationEditor : extends
AltimateWebviewProvider : +String viewType
AltimateWebviewProvider : #String viewPath
AltimateWebviewProvider : #String description
AltimateWebviewProvider: #renderWebviewView()
AltimateWebviewProvider: #handleCommand()
class InsightsPanel{
#handleCommand
}
class DocumentationEditor{
#handleCommand
}
class Webview_panels["webview_panels/src/main.tsx"]
Webview_panels <|-- AltimateWebviewProvider : renders
<<reactapp>> Webview_panels
note for Webview_panels "AppConstants.tsx defines routes for each panel \n main.tsx will render route defined in viewPath variable in Provider"
click AltimateWebviewProvider href "../src/webview_provider/altimateWebviewProvider.ts" ""
click InsightsPanel href "../src/webview_provider/insightsPanel.ts" ""
click Webview_panels href "./src/main.tsx" ""
- Base class for rendering webview
- Also handles security practices like CSP and noonce as recommended here
- Each new panel needs to have its own provider which extends this class and should override
viewPath
description
viewType
- each panel can also override
handleCommand
function to handle incoming messages from webview
- Uses react-router-dom for handling different routes for each panel
- Route will be determined by the
viewPath
value set inAltimateWebviewProvider
- Uses reduxjstoolkit with useReducer in AppProvider
- This helps us to setup reducers in more readable and maintainable way
- This comes with RTK Query similar to react-query
- useListeners - common place to listen for incoming messages
- Component specific message can be listened within component/respective hook
- Assets are stored here ./src/assets
- can be accessed via
index.ts
in the same directory
- can be accessed via
- In
package.json
, add an entry inviewsContainers -> panel
with expected values- add corresponding entry in
views -> dbt_view
- add corresponding entry in
- Create new provider in ../src/webview_provider by extending
AltimateWebviewProvider
withviewType
same as the one added in package.json above - Add the new provider in ../src/webview_provider/index.ts
- Add new route in ./src/AppConstants.tsx
- Use the new view route added in AppConstants in new webview provider created in step 2 and update value for
viewPath
variable - Update the value for
panelDescription
in provider - Launch the extension and test the new panel
- UI components are built in ./src/uiCore package. Any new UI component should be imported only from this package. This will enable us to apply consistent styling, create ui toolkit and ability to switch to new UI library easily if needed
reactstrap
(which is the current ui library) import is restricted in components insrc/modules
, to avoid importing the ui components directly from reactstrap. Instead export the necessary component from ./src/uiCore and use it in components- Storybook is integrated and ui tool kit is built in storybook to check the available UI components, typography, colors. If you add any new component to uiCore, add that component to above storybook.
- use
panelLogger
for logging from webview panels. We can make this to use console or any logger in future
- From webview react app, call
postMessageToDataPilot({ test: '123' });
inuseAppContext
- This message will be received by
altimateWebviewProvider
and posted toSharedStateService
datapilotPanel
will listen for message fromSharedStateService
and relays that to data pilot webview panel- Datapilot storybook is available here
- Webview panel does not make api calls directly. Instead the request will be sent to webview providers and in turn call backend apis
- For achieving this, helper methods are available
- requestExecutor - handles sending messages to providers
executeRequestInSync
can be used for getting response back from provider for an actionexecuteRequestInAsync
can be used for just sending message to provider without need for response
- requestExecutor - handles sending messages to providers
- vscode api integration is added using manual mock as in here.
- Sample code (use
vscode
field inparameters
to pass your mock data):export const QueryAnalysisDefaultView = { render: (): JSX.Element => { return <DataPilotPanel />; }, parameters: { vscode: { data: { key: "value" }, timer: 3000, }, }, }
- use
executeStreamRequest
defined in requestExecutor to send an api request (which could send streaming response) through webview provider and addprogress
callback - In webview providers (ex: datapilotPanel), handle the incoming command and trigger backend api request using
fetchAsStream
defined in StreamingService StreamingService
will take care of sending chunks to webview_panels which will be listened byresponse
message event andprogress
will be called with chunks- Once the stream is completed,
executeStreamRequest
will resolve to the response