Skip to content

Latest commit

 

History

History
447 lines (362 loc) · 25.1 KB

portalfx-assets.md

File metadata and controls

447 lines (362 loc) · 25.1 KB

Assets

Assets are generic entities tracked within the portal. As generic entities, assets can identify subscription resources (e.g. websites), higher-level entities (e.g. AAD directory), lower-level entities (e.g. TFS work items), or things not even remotely associated with subscriptions (e.g. users). As an example, subscriptions, resource groups, and deployments are all tracked as assets.

Assets are used for the following experiences:

  • Notifications should be linked to an asset
  • The Browse menu lists browseable asset types
  • Browse > Recent only shows assets based on the asset type specified on a blade
  • The All Resources view only shows resources that have asset types that implement Browse v2
  • The resource group list only shows resources that have asset types with a defined ResourceType
  • Defining permissions in PDL requires asset types
  • References to deleted assets can be cleaned up with notifyAssetDeleted()
  • Overriding behavior for resource kinds

All asset types have the following requirements:

  1. The asset type blade must have a single id parameter that is the asset id
  2. The asset type part must be the same as the blade's pinned part
  3. The asset type part and blade's pinned part must open the asset type's blade
  4. Must call notifyAssetDeleted() when the resource has been deleted or is not found

Asset types that represent Azure Resource Manager (ARM) resource types also have the following requirements:

  1. The asset id must be the string resource id
  2. The ARM RP manifest should include a RP, resource type, and resource kind metadata

Defining your asset type

To define your asset type, simply add the following snippet to PDL:

<AssetType
    Name="MyAsset"
    ServiceDisplayName="{Resource MyAsset.service, Module=ClientResources}"
    SingularDisplayName="{Resource MyAsset.singular, Module=ClientResources}"
    PluralDisplayName="{Resource MyAsset.plural, Module=ClientResources}"
    LowerSingularDisplayName="{Resource MyAsset.lowerSingular, Module=ClientResources}"
    LowerPluralDisplayName="{Resource MyAsset.lowerPlural, Module=ClientResources}"
    Keywords="{Resource MyAsset.keywords, Module=ClientResources}"
    Description="{Resource MyAsset.description, Module=ClientResources}"
    Icon="{Resource Content.MyExtension.Images.myAsset, Module=./../_generated/Svg}"
    BladeName="MyAssetBlade"
    PartName="MyAssetPart"
    IsPreview="true">
  ...
</AssetType>

The name can be anything that follows standard variable naming guidelines. Just remember: Once you set the asset type name, you can never change it! Asset type names are used as pointers in multiple places (e.g. favorites, recent) and changing the asset type will cause the references to your asset type and resources to fail. Do not change asset type names! You'll be typing this a lot, so keep it succinct, yet clear -- it will be used to identify asset types in telemetry.

In order to provide a modern voice and tone within the portal, asset types have 5 different display names. The portal will use the most appropriate display name given the context. Please keep these rules in mind:

  1. Always specify ServiceDisplayName, if applicable. If your service has an official, registered/trade-marked product name (e.g. App Service), specify the ServiceDisplayName property to ensure the service name is used when possible.
  2. Plural/singular display names must be nouns. These names are used in sentences, which will not flow correctly if you use the service name when you should have a noun (e.g. "No Data Lake Store to display"). Instead, set ServiceDisplayName to get the appropriate handling as well as natural, grammatically correct sentences throughout the portal.
  3. Display names must be sentence-cased. This applies to all text, including blade, tile, and section headers. The Microsoft Style Guide dictates that all text should be sentence-cased unless it is a product or service name. Note that nouns are not service names, even if they use the same words (e.g. the "Logic Apps" service should have a LowerPluralDisplayName of "logic apps"). Conversly, a service name can be used to prefix a noun (e.g. "Traffic Manager profiles").
  4. Do not lower-case acronyms. If your asset type display name includes an acronym or starts with a product name that is always capitalized, use the same values for upper and lower display name properties (e.g. PluralDisplayName and LowerPluralDisplayName may both use SQL databases).
  5. Plural and singular names should never be the same. Do not share strings between singular and plural display names. There is no scenario where these should be the same.
  6. Do not specify extraneous keywords in the name. If you want customers to find your service or resource type when they search for another word (e.g. firewall), add that to the comma-delimited list of Keywords. These will be used when filtering in the More Services menu as well as global search.

The aforementioned display names are used in the following places:

  • The Browse menu shows the ServiceDisplayName in the list of browseable asset types. If ServiceDisplayName is not available, PluralDisplayName will be shown instead
  • The All Resources blade uses the SingularDisplayName in the Type column, when visible
  • Browse v2 uses the LowerPluralDisplayName when there are no resources (e.g. "No web apps to display")
  • Browse v2 uses the LowerPluralDisplayName as the text filter placeholder
  • Global search uses the SingularDisplayName to indicate what type resources are
  • The Azure mobile app uses the PluralDisplayName in the resource type filter (support for ServiceDisplayName coming post-Build)
  • The Azure mobile app uses the SingularDisplayName everywhere the resource type is displayed (i.e. resource list/detail, alert list/ detail)

Filtering functionality within the Browse menu searches over Keywords. Keywords is a comma-separated set of words or phrases which allow users to search for your asset by identifiers other than than the set display names.

Remember, your part and blade should both have a single id input parameter, which is the asset id:

<Part Name="MyAssetPart" ViewModel="MyAssetPartViewModel" AssetType="MyAsset" AssetIdProperty="id" ...>
  <Part.Properties>
    <!-- Required. Must be the only input parameter. -->
    <Property Name="id" Source="{DataInput Property=id}" />
  </Part.Properties>
  <BladeAction Blade="MyAssetBlade">
    <BladeInput Source="id" Parameter="id" />
  </BladeAction>
  ...
</Part>

<Blade Name="MyAssetBlade" ViewModel="MyAssetBladeViewModel" AssetType="MyAsset" AssetIdProperty="id">
  <Blade.Parameters>
    <!-- Required. Must be the only input parameter. -->
    <Parameter Name="id" Type="Key" />
  </Blade.Parameters>
  <Blade.Properties>
    <Property Name="id" Source="{BladeParameter Name=id}" />
  </Blade.Properties>
  ...
</Blade>

If your asset type is in preview, set the IsPreview="true" property. If the asset type is GA, simply remove the property (the default is false).

How to hide your asset in different environments

You can hide your asset in different environments by setting the hideassettypes feature flag in your config to a comma-separated list of asset type names.

Watch the Hiding Asset Types video here

Self hosted

Replace '*' with the desired environment, for documentation regarding enabling feature flags in self hosted extensions click here.

        <Setting name="Microsoft.StbPortal.Website.Configuration.ApplicationConfiguration.DefaultQueryString" value="{
            '*': {
                     'microsoft_azure_compute_hideassettypes':"AzureContainerService,ContainerGroup,ManagedClusters,VirtualWan"
            }
        }" />

Hosting service

If you’re using the hosting service, you can do this by updating your domainname.json (e.g. portal.azure.cn.json file)

    {
        "hideassettypes": "AzureContainerService,ContainerGroup,ManagedClusters,VirtualWan"
    }

Alternatively, you can hide all your assets in a specific environment by specifying:

    {
        "hideassettypes": "*"
    }

Note, wildcard expressions are NOT supported, e.g: "AzureContainer*" will not hide all assets beginning with AzureContainer.

Testing your hidden asset

To test enable your hidden asset for testing purposes, you will need to update the hide asset feature flag to exclude the asset you want to show and ensure you have feature.canmodifyextensions set.

For the desired environment append the following feature flags.

If you want to test showing all hidden assets, you can specify all the assets as a comma seperated list to the 'showassettypes' feature flag.

    ?feature.showassettypes=MyNewAsset
    &microsoft_azure_mynewextension=true
    &feature.canmodifyextensions=true

For example: https://rc.portal.azure.com/?feature.showassettypes=VirtualMachine&microsoft_azure_compute=true&feature.canmodifyextensions=true

Handling empty browse

The framework offers the ability to display a description and links in the case that the users filters return no results.

NOTE: This will also display if the user visits the browse experience and they have not yet created the given resource.

Empty browse

To opt in to this experience you need to provide a description and a link, these are properties that you provide on your Asset.

<AssetType  
    Name="MyAsset"
    ...
    Description="{Resource MyAsset.description, Module=ClientResources}">
    ...
    <Link Title="{Resource MyAsset..linkTitle1, Module=ClientResources}" Uri="http://www.bing.com"/>
    <Link Title="{Resource MyAsset.linkTitle2, Module=ClientResources}" Uri="http://www.bing.com"/>
    ...
  </AssetType>

Blades, parts, and commands

Every blade, part, and command that represents or acts on a single asset instance should specify an AssetType and AssetIdProperty. The AssetType is the Name specified on your <AssetType /> node and the AssetIdProperty is the name of the input property that contains the asset id. Remember, that should be the string resource id, if your asset is an ARM resource.

If a blade, part, or command represents or acts on multiple assets, use the primary asset type/id based on the context. For instance, when displaying information about a child asset that also obtains information about the parent, use the child's asset type/id.

Showing up in the Browse ("More services") menu

To show up in the Browse menu, your asset type must specify the <Browse Type="" /> node. The Type informs the Browse menu how to interact with your asset type. Learn more about Browse integration.

Services that use resource kinds can also be added to the Browse menu, but that must be configured by the Fx team. To do this, create a partner request with the asset type name and kind value.

Showing up in Browse > Recent

The Recent list in the Browse menu shows asset instances that have been interacted with. The portal tracks this via the AssetType and AssetIdProperty on each blade that is launched. See Blades, parts, and commands above for more information.

Showing up in All Resources and resource group resources

The All Resources and resource group blades show all resources except alert rules, autoscale settings, and dashboards. Resources that aren't backed by an asset type use a very basic resource menu blade that exposes properties, RBAC, tags, locks, and activity log.

To implement the most basic asset type, add the asset type definition (including display names, icon, blade, and part), add <Browse Type="ResourceType" /> for no-code Browse, and then include a <ResourceType ResourceTypeName="" ApiVersion="" /> declaration.

Handling permissions for RBAC

To ensure your blades, parts, and commands react to the user not having access, you can add an AssetType, AssetIdProperty, and required Permissions to your blades, parts, and commands. Learn more about Permissions.

Special-casing ARM resource kinds

The portal supports overriding the following default behaviors based on the resource kind value:

  • Hiding resources in Browse and resource groups
  • Displaying separate icons throughout the portal
  • Launching different blades when an asset is opened
  • Merging kinds to display in a single browse view

The kind value can be whatever value makes sense for your scenarios. Just add supported kinds to the AssetType PDL:

<AssetType ...>
  ...
  <ResourceType ...>
    <Kind Name="kind1" />
    <Kind Name="kind2" />
    <Kind Name="kind3" />
  </ResourceType>
</AssetType>

Name is the only required attribute. None of the other attributes for kinds are required. Simply specify the behaviors you want to override from your asset type and you're done.

Attribute Description
Name (Required) Kind value assigned to resource types.
IsDefault (Optional) Ignores the Name value and applies overrides to the default (empty) kind value. Teams are recommended to avoid this, if possible.
BladeName (Optional) Specifies the blade to launch when this kind is opened from a Fx resource list.
CompositeDisplayName (Optional) Overrides the type name shown in resource lists. The ComposityDisplayName is a convention-based reference to multiple RESX strings. For instance, CompositeDisplayName="MyAsset" would map to the following 4 RESX strings: MyAsset_pluralDisplayName, MyAsset_singularDisplayName, MyAsset_lowerPluralDisplayName, and MyAsset_lowerSingularDisplayName.
Icon (Optional) Overrides the asset type's icon.
IsPreview (Optional) Indicates a preview label should be shown in the Browse (More services) menu, if applicable.
Keywords (Optional) Specifies the keywords to use when filtering in the Browse (More services) menu, if applicable.
MarketplaceItemId (Optional) Specifies the Marketplace item id (aka gallery package id) to launch from the "Add" command on the resource type Browse blade, if applicable.
MarketplaceMenuItemId (Optional) Specifies the Marketplace menu item to launch from the "Add" command on the resource type Browse blade, if applicable.
ServiceDisplayName (Optional) Overrides the text to use in the Browse (More services) menu, if applicable.
UseResourceMenu (Optional) Overrides the asset type's UseResourceMenu flag.
Visibility (Optional) Indicates whether the kind should be hidden from resource lists. Values: Hidden.

If different kinds need to opt in to a static resource menu overview item, add the <StaticOverview /> node.

<Kind ...>
  <StaticOverview />
</Kind>

Displaying multiple kinds together in a single browse view

There are two options for displaying multiple kinds as a single view. Both cases require exposing a entry for your asset.

  1. Merging multiple kinds together via any of each kind's browse entry (MergedKind)
  2. Exposing a logical kind (KindGroup) which acts as a single entry point for multiple kinds.

MergedKind

To expose your resources as a merged kind you need to define the kinds you wish to merge as below.

<AssetType Name="Watch">
    <ResourceType ResourceTypeName="Microsoft.Test/watches"
                  ApiVersion="2017-04-01">
      <!--
        The 'garmin-merged' kind has two merged kinds, 'garmin' and 'garmin2'. The 'garmin-merged' kind is not a real
        kind and is not emitted to the manifest as a kind, it is organizational only.
      -->
      <MergedKind Name="garmin-merged">
        <Kind Name="garmin"
              CompositeDisplayName="{Resource AssetTypeNames.Watch.Garmin, Module=ClientResources}"
              Icon="{Svg IsLogo=true, File=../../Svg/Watches/garmin.svg}"
              BladeName="GarminWatchBlade"
              PartName="GarminWatchTile" />
        <Kind Name="garmin2"
              CompositeDisplayName="{Resource AssetTypeNames.Watch.Garmin2, Module=ClientResources}"
              Icon="{Svg IsLogo=true, File=../../Svg/Watches/garmin2.svg}"
              BladeName="Garmin2WatchBlade"
              PartName="Garmin2WatchTile" />
      </MergedKind>
    </ResourceType>
  </AssetType>

KindGroup

To expose your resources as grouped as a single kind you will need to define the below. Note both lg and samsung in the example below will be exposed as entries too.

<AssetType Name="Watch">
    <ResourceType ResourceTypeName="Microsoft.Test/watches"
                  ApiVersion="2017-04-01">
      <Kind Name="lg"
            CompositeDisplayName="{Resource AssetTypeNames.Watch.LG, Module=ClientResources}"
            Icon="{Svg IsLogo=true, File=../../Svg/Watches/lg.svg}"
            BladeName="LgWatchBlade"
            PartName="LgWatchTile" />
      <Kind Name="samsung"
            CompositeDisplayName="{Resource AssetTypeNames.Watch.Samsung, Module=ClientResources}"
            Icon="{Svg IsLogo=true, File=../../Svg/Watches/samsung.svg}"
            BladeName="SamsungWatchBlade"
            PartName="SamsungWatchTile" />
      <!--
        The 'android' kind group wraps the lg and samsung kinds into a single kind. The 'android' kind is an abstract
        kind. There should never be a watch with the kind set to 'android'. Instead it's used to group kinds into
        a single list. However, 'lg' watches and be seen separately, same with 'samsung' watches. The 'android' kind
        will be emitted to the manifest as a kind.
      -->
      <KindGroup Name="android"
            CompositeDisplayName="{Resource AssetTypeNames.Watch.Android, Module=ClientResources}"
            Icon="{Svg IsLogo=true, File=../../Svg/Watches/android.svg}">
        <KindReference KindName="lg" />
        <KindReference KindName="samsung" />
      </KindGroup>
    </ResourceType>
  </AssetType>

Handling deleted resources

The portal includes many references to assets, like pinned parts on the dashboard, recent items, and more. All references are persisted to user settings and available when the user signs in again. When an asset is deleted, the portal needs to be notified that these references need to be cleaned up. To do that, simply call MsPortalFx.UI.AssetManager.notifyAssetDeleted().

It's important to note that assets can obviously be deleted outside the portal. When an asset is deleted outside of the portal and notifyAssetDeleted() cannot be called, these references will not be cleaned up. When the user signs in again, they will still see pinned parts, for instance. These parts will most likely fail to load due to a 404 from your back-end service due to the asset not existing anymore. When you get a 404 for an asset id, always call notifyAssetDeleted() to ensure the portal has a chance to clean up.

Linking notifications to assets

To link a notification to an asset, simply include an asset reference (AssetTriplet) in the notification:

MsPortalFx.Hubs.Notifications.ClientNotification.publish({
    title: resx.myEvent.title,
    description: resx.myEvent.description,
    status: MsPortalFx.Hubs.Notifications.NotificationStatus.Information,
    asset: {
        extensionName: ExtensionDefinition.definitionName,
        assetType: ExtensionDefinition.AssetTypes.MyAsset.name,
        assetId: assetId
    }
});

Learn more about notifications.

ARM RP and resource type metadata

Every ARM resource provider (RP) should have a default RP icon as well as a resource type icon specified in the RP manifest to support the following scenarios:

  • The AAD custom role management UI uses the resource type icon for resource type actions
  • Visual Studio uses the resource type icon in its list of resources
  • The portal uses the RP icon when a blade isn't associated with an asset type and doesn't have an icon
  • When a resource type icon isn't provided, the RP icon is used

When an icon is not specified, each experience will use the MsPortalFx.Base.Images.Polychromatic.ResourceDefault() icon:

To specify an RP icon, add the following portal metadata snippet:

{
    "namespace": "rp.namespace",
    "metadata": {
        "portal": {
            "icon": "<svg>...</svg>"
        }
    },
    ...
}

To specify a resource type icons, add the same snippet to each resource type definition:

{
    "namespace": "rp.namespace",
    "metadata": {
        "portal": {
            "icon": "<svg>...</svg>"
        }
    },
    ...
    "resourceTypes": [
        {
            "resourceType": "instances",
            "metadata": {
                "portal": {
                    "icon": "https://..."
                }
            },
            ...
        },
        ...
    ],
    ...
}

Icons can be either SVG XML or a standard HTTPS URL. SVG XML is preferred for scalability and rendering performance; however, HTTPS URLs are better if your RP manifest is too large.

To retrieve RP manifests for a subscription, call GET /subscriptions/###/providers?$expand=metadata.