microsoft / azure-devops-extension-sdk

Client SDK for developing Azure DevOps extensions
MIT License
123 stars 38 forks source link

Target Date for Widget support? #22

Open mmaist opened 4 years ago

mmaist commented 4 years ago

Is there a target date for when widgets will be supported by this newer SDK? I am hesitant to develop on the old SDK and then have to port over to this one, but if the support for widgets isn't coming anytime soon then I'll just bite the bullet.

Liran-Dobrish commented 4 years ago

i need this feature also, any idea when it might be added?

meetpatel-promact commented 4 years ago

I also want to know when it will be available, don't want to use the older SDK for the widget contribution.

yuriburger commented 4 years ago

same here, would be nice to use the new SDK with widgets

bworline commented 4 years ago

While you're waiting for official support:

I was able to get it to work for a widget and a widget configuration.

I had to make a file that essentially contained the missing bits from vss-web-extension-sdk (several typings from tfs.d.ts and vss.d.ts and a wee bit of implementation from vss.sdk.js - WidgetStatusHelper, WidgetConfigurationSave, ConfigurationEvent) that I couldn't find in azure-devops-extension-sdk.

When you call SDK.register, pass an IWidget or IConfigurableWidget for a widget, and an IWidgetConfiguration for a widget configuration.

missingSdkBits.zip

rmouser commented 3 years ago

Agreed, I also want this because the VSS API forces an ugly coding style, and results in less robust extensions.

igormcsouza commented 3 years ago

Hello @bworline !! We are trying here to use your file, but we cannot find out where to put this informations or how to call it out to work! Can you give a little of explanation on it!?

htekdev commented 2 years ago

Just started a PR that includes the changes needed to integrate vss-web-extension-sdk into azure-devops-extension-sdk. This would enable widgets using the advised react.js sdk toolkit

https://github.com/microsoft/azure-devops-extension-sdk/pull/51

Based on my review, everything is there to create a dashboard widget using new SDK. The part that is missing is the logic that consumes the requirejs modules that allow the "legacy" SDK to inject "Dashboard Widget" styles and to use the widget service.

After trying several attempts to move over that logic it seemed simplyer to just "merge" the init phase with both using the same channel. This allows both old and new sdks to be used together. Due to this I was able to create a new method

const WidgetHelpers = await SDK.requireModule<ITFSDashboardsWidgetHelpers>("TFS/Dashboards/WidgetHelpers")

Which is the same as the legacy way:

VSS.require(["TFS/Dashboards/WidgetHelpers"], function (WidgetHelpers: typeof wh) { 
...
})

Now with all of this, I was able to prove everything works with the following full file examples:

vss-extension.json:

{
    "contributions": [
        {
            "id": "AnnotationStatusWidgetV2",
            "type": "ms.vss-dashboards-web.widget",
            "targets": [
                "ms.vss-dashboards-web.widget-catalog"
            ],
            "properties": {
                "name": "Hello World Widget",
                "description": "My first widget",
                "catalogIconUrl": "pipeline-run-annotation-config-hub/img/CatalogIcon.png",
                "previewImageUrl": "pipeline-run-annotation-config-hub/img/preview.png",                            
                "uri": "pipeline-run-annotation-config-hub/dist/AnnotationStatusWidget/AnnotationStatusWidget.html",
                "supportedSizes": [
                     {
                            "rowSpan": 1,
                            "columnSpan": 2
                        }
                    ],
                "supportedScopes": ["project_team"]
            }
        }
    ],
    "scopes": ["vso.work"]
}

Example AnnotationStatusWidget.html:

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
    <body>
        <div class="widget">
            <div id="root"></div>
        </div>
        <script type="text/javascript" src="AnnotationStatusWidget.js" charset="utf-8"></script>
    </body>
</html>

Example AnnotationStatusWidget.tsx:

import { showRootComponent } from "../../Common";
import * as React from "react";
import * as SDK from "@htekdev/azure-devops-extension-sdk";
import { getAnnotatedRuns, IAnnotatedPipelineRunItem } from "@htekdev/pipeline-run-sdk";
import { FrameworkProvider } from "../../Libs";
import { ITFSDashboardsWidgetHelpers, ITFSDashboardsWidgetContracts } from "@htekdev/azure-devops-extension-sdk";
import {WidgetSettings} from "TFS/Dashboards/WidgetContracts"

type AnnotationStatusWidgetProps = {
    ContributionId: string}

const AnnotationStatusWidget : React.FunctionComponent<AnnotationStatusWidgetProps>  = ({ContributionId}) => {
    const [annotatedRuns, setAnnotatedRuns] = React.useState<IAnnotatedPipelineRunItem[]>([]);
    const [error, setError] = React.useState<string | undefined>(undefined)

    const load = React.useCallback(async () => {
        try{
            const annotatedRuns = await getAnnotatedRuns(FrameworkProvider, "project")
            setAnnotatedRuns(annotatedRuns)
        }
        catch(e){
            console.log(e);
            setError(`${e}`);
        }

    }, [])

    const register = React.useCallback(async () => {
        const WidgetHelpers = await SDK.requireModule<ITFSDashboardsWidgetHelpers>("TFS/Dashboards/WidgetHelpers")
        await WidgetHelpers.IncludeWidgetStyles()

        SDK.register(ContributionId, function () { 
            return {
                load: async (widgetSettings: WidgetSettings) => {
                    try{
                        await load();    
                    }
                    catch(e){
                        console.log(e)
                    }
                    finally{
                        return {
                            statusType: 0
                        }
                    }
                }
            }
        });

        await SDK.notifyLoadSucceeded();
    }, [])

    React.useEffect(() => {
        register()
    }, [ContributionId])

    return <>{error ? error : <>{annotatedRuns.length} Annotated Runs</>}</>
}

// Initialize the VSS sdk
SDK.init({
    loaded: false
})

// Initialize the VSS sdk
SDK.ready().then(() => {
    showRootComponent(<AnnotationStatusWidget ContributionId="AnnotationStatusWidgetV2" />);
})
chriswise01 commented 1 year ago

When will this be merged in? This is a key part missing from the SDK.

htekdev commented 1 year ago

@chriswise01 Im not sure... I was told the owner is not active so not sure when this will become available...

I published this version though if you want to consume it: npm install @htekdev/azure-devops-extension-sdk

syedwastil commented 1 year ago

@htekdev

npm install @htekdev/azure-devops-extension-sdk@2.1.24

Can't find it in npm registry.

htekdev commented 1 year ago

@syedwastil so sorry! I had it private. Just published to public registry. Sorry for the delay. https://www.npmjs.com/package/@htekdev/azure-devops-extension-sdk

bworline commented 5 months ago

We have a date for widget support: 1/24/2024.

It was added in build 4.231.0 of azure-devops-extension-api with this PR. It may seem odd to not have been added to this SDK package, but I'm told that all contracts for individual areas are now logically part of azure-devops-extension-api. The old SDK (vss-web-extension-sdk) was a combination of both SDK and contracts.

The azure-devops-extension-sample repo has not been updated with an example widget yet, but for now:

To use the new types, import * as Dashboard from 'azure-devops-extension-api/Dashboard';. When you call SDK.register, pass an object that implements IWidget or IConfigurableWidget for a widget, and an IWidgetConfiguration for a widget configuration.

ImreBoersma commented 3 months ago

@bworline

To use the new types, import * as Dashboard from 'azure-devops-extension-api/Dashboard';. When you call SDK.register, pass an object that implements IWidget or IConfigurableWidget for a widget, and an IWidgetConfiguration for a widget configuration.

Do you have a working example for this? I'm struggling to get this to work in a Vue.JS app. Thanks in advance!

bworline commented 2 months ago

@bworline

To use the new types, import * as Dashboard from 'azure-devops-extension-api/Dashboard';. When you call SDK.register, pass an object that implements IWidget or IConfigurableWidget for a widget, and an IWidgetConfiguration for a widget configuration.

Do you have a working example for this? I'm struggling to get this to work in a Vue.JS app. Thanks in advance!

See https://github.com/microsoft/azure-devops-extension-sample/pull/153