diff --git a/extensions/resource-deployment/src/ui/resourceTypePickerDialog.ts b/extensions/resource-deployment/src/ui/resourceTypePickerDialog.ts index 2a82ff1592..f2d070a4b2 100644 --- a/extensions/resource-deployment/src/ui/resourceTypePickerDialog.ts +++ b/extensions/resource-deployment/src/ui/resourceTypePickerDialog.ts @@ -73,7 +73,16 @@ export class ResourceTypePickerDialog extends DialogBase { return { id: resourceType.name, label: resourceType.displayName, - icon: resourceType.icon + icon: resourceType.icon, + descriptions: [ + { + textValue: resourceType.displayName, + textStyles: { + 'font-size': '12px', + 'font-weight': 700 + } + } + ] }; }), iconHeight: '50px', diff --git a/extensions/sql-migration/src/wizard/skuRecommendationPage.ts b/extensions/sql-migration/src/wizard/skuRecommendationPage.ts index ad663ae80a..afb47e108f 100644 --- a/extensions/sql-migration/src/wizard/skuRecommendationPage.ts +++ b/extensions/sql-migration/src/wizard/skuRecommendationPage.ts @@ -105,14 +105,42 @@ export class SKURecommendationPage extends MigrationWizardPage { const rbg = this.view!.modelBuilder.radioCardGroup(); rbg.component().cards = []; + rbg.component().orientation = azdata.Orientation.Vertical; + rbg.component().iconHeight = '30px'; + rbg.component().iconWidth = '30px'; products.forEach((product) => { const imagePath = path.resolve(this.migrationStateModel.getExtensionPath(), 'media', product.icon ?? 'ads.svg'); + const descriptions: azdata.RadioCardDescription[] = [ + { + textValue: product.name, + linkDisplayValue: 'Learn more', + displayLinkCodicon: true, + textStyles: { + 'font-size': '1rem', + 'font-weight': 550, + }, + linkCodiconStyles: { + 'font-size': '1em', + 'color': 'royalblue' + } + }, + { + textValue: '9 databases will be migrated', + linkDisplayValue: 'View/Change', + displayLinkCodicon: true, + linkCodiconStyles: { + 'font-size': '1em', + 'color': 'royalblue' + } + } + ]; + rbg.component().cards.push({ id: product.name, icon: imagePath, - label: product.name + descriptions }); }); diff --git a/src/sql/azdata.d.ts b/src/sql/azdata.d.ts index 6ef61a383f..3b0b0259a8 100644 --- a/src/sql/azdata.d.ts +++ b/src/sql/azdata.d.ts @@ -3040,7 +3040,7 @@ declare module 'azdata' { export enum Orientation { Horizontal = 'horizontal', - Vertical = 'vertial' + Vertical = 'vertical' } export interface ToolbarLayout { diff --git a/src/sql/azdata.proposed.d.ts b/src/sql/azdata.proposed.d.ts index ef88078b5e..672fb262a9 100644 --- a/src/sql/azdata.proposed.d.ts +++ b/src/sql/azdata.proposed.d.ts @@ -202,22 +202,20 @@ declare module 'azdata' { export interface RadioCard { id: string; - label: string; - descriptions?: RadioCardDescription[]; + descriptions: RadioCardDescription[]; icon?: string | vscode.Uri | { light: string | vscode.Uri; dark: string | vscode.Uri }; } export interface RadioCardDescription { - ariaLabel: string; - labelHeader: string; - contents: RadioCardLabelValuePair[]; - valueHeader?: string; + textValue: string; + linkDisplayValue?: string; + displayLinkCodicon?: boolean; + textStyles?: CssStyles; + linkStyles?: CssStyles; + linkCodiconStyles?: CssStyles; } - export interface RadioCardLabelValuePair { - label: string; - value?: string; - } + export type CssStyles = { [key: string]: string | number }; export interface RadioCardGroupComponentProperties extends ComponentProperties, TitledComponentProperties { cards: RadioCard[]; @@ -226,13 +224,20 @@ declare module 'azdata' { iconWidth?: string; iconHeight?: string; selectedCardId?: string; + orientation?: Orientation // Defaults to horizontal } + export type RadioCardSelectionChangedEvent = { cardId: string; card: RadioCard }; + export type RadioCardLinkClickEvent = { cardId: string, card: RadioCard, selectorText: RadioCardDescription }; + export interface RadioCardGroupComponent extends Component, RadioCardGroupComponentProperties { /** * The card object returned from this function is a clone of the internal representation - changes will not impact the original object */ - onSelectionChanged: vscode.Event<{ cardId: string; card?: RadioCard }>; + onSelectionChanged: vscode.Event; + + onLinkClick: vscode.Event; + } export interface SeparatorComponent extends Component { diff --git a/src/sql/workbench/api/common/extHostModelView.ts b/src/sql/workbench/api/common/extHostModelView.ts index 4c2baa4afb..1fad842b54 100644 --- a/src/sql/workbench/api/common/extHostModelView.ts +++ b/src/sql/workbench/api/common/extHostModelView.ts @@ -1696,7 +1696,9 @@ class RadioCardGroupComponentWrapper extends ComponentWrapper implements azdata. constructor(proxy: MainThreadModelViewShape, handle: number, id: string) { super(proxy, handle, ModelComponentTypes.RadioCardGroup, id); this.properties = {}; - this._emitterMap.set(ComponentEventType.onDidChange, new Emitter()); + + this._emitterMap.set(ComponentEventType.onDidChange, new Emitter()); + this._emitterMap.set(ComponentEventType.onDidClick, new Emitter()); } public get iconWidth(): string | undefined { @@ -1746,10 +1748,23 @@ class RadioCardGroupComponentWrapper extends ComponentWrapper implements azdata. this.setProperty('selectedCardId', v); } - public get onSelectionChanged(): vscode.Event { + public get orientation(): azdata.Orientation | undefined { + return this.properties['orientation']; + } + + public set orientation(orientation: azdata.Orientation | undefined) { + this.setProperty('orientation', orientation); + } + + public get onSelectionChanged(): vscode.Event { let emitter = this._emitterMap.get(ComponentEventType.onDidChange); return emitter && emitter.event; } + + public get onLinkClick(): vscode.Event { + let emitter = this._emitterMap.get(ComponentEventType.onDidClick); + return emitter && emitter.event; + } } class TabbedPanelComponentWrapper extends ComponentWrapper implements azdata.TabbedPanelComponent { diff --git a/src/sql/workbench/api/common/sqlExtHostTypes.ts b/src/sql/workbench/api/common/sqlExtHostTypes.ts index 8b677ca6af..ce3d3f37cf 100644 --- a/src/sql/workbench/api/common/sqlExtHostTypes.ts +++ b/src/sql/workbench/api/common/sqlExtHostTypes.ts @@ -374,7 +374,7 @@ export enum CardType { export enum Orientation { Horizontal = 'horizontal', - Vertical = 'vertial' + Vertical = 'vertical' } /** diff --git a/src/sql/workbench/browser/modelComponents/card.component.html b/src/sql/workbench/browser/modelComponents/card.component.html index 7722a5d535..5a1f901845 100644 --- a/src/sql/workbench/browser/modelComponents/card.component.html +++ b/src/sql/workbench/browser/modelComponents/card.component.html @@ -1,5 +1,7 @@ -
+ +
@@ -15,8 +17,10 @@

{{label}}

-
- {{desc.label}}{{desc.value}} +
+ {{desc.label}}{{desc.value}}
diff --git a/src/sql/workbench/browser/modelComponents/media/card.css b/src/sql/workbench/browser/modelComponents/media/card.css index 8b67b22391..073058e838 100644 --- a/src/sql/workbench/browser/modelComponents/media/card.css +++ b/src/sql/workbench/browser/modelComponents/media/card.css @@ -3,7 +3,7 @@ * Licensed under the Source EULA. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -.model-card { +.horizontal .model-card { position: relative; display: inline-block; height: 90%; @@ -16,7 +16,7 @@ border-color: rgb(214, 214, 214); } -.model-card .card-content { +.horizontal .model-card .card-content { position: relative; display: inline-block; height: auto; @@ -26,7 +26,8 @@ min-width: 30px; } -.model-card .card-vertical-button { +.horizontal .model-card .card-vertical-button, +.horizontal .model-card .text-container { position: relative; display: flex; flex-direction: column; @@ -38,17 +39,17 @@ min-width: 130px; } -.model-card .card-label { +.horizontal .model-card .card-label { font-size: 12px; font-weight: bold; } -.model-card .card-value { +.horizontal .model-card .card-value { font-size: 12px; line-height: 18px; } -.model-card .iconContainer { +.horizontal .model-card .icon-container { display: flex; flex-direction: column; justify-content: center; @@ -60,7 +61,7 @@ border-color: rgb(214, 214, 214); } -.model-card .cardIcon { +.horizontal .model-card .icon { display: inline-block; flex-grow: 1; width: 100%; @@ -72,7 +73,7 @@ background-size: contain; } -.model-card .card-status { +.horizontal .model-card .card-status { position: absolute; top: 7px; left: 5px; @@ -81,7 +82,7 @@ height: 22px; } -.model-card .status-content { +.horizontal .model-card .status-content { position: absolute; top: 0px; right: 0px; @@ -91,7 +92,8 @@ text-align: center; } -.model-card-list-item .selection-indicator-container, .model-card .selection-indicator-container { +.horizontal .model-card-list-item .selection-indicator-container, +.horizontal .model-card .selection-indicator-container { position: absolute; top: 5px; right: 5px; @@ -105,7 +107,8 @@ border-style: solid; } -.model-card-list-item .selection-indicator-container, .model-card .selection-indicator-container { +.horizontal .model-card-list-item .selection-indicator-container, +.horizontal .model-card .selection-indicator-container { position: absolute; overflow: hidden; width: 16px; @@ -117,17 +120,18 @@ border-style: solid; } -.model-card-list-item .selection-indicator-container { +.horizontal .model-card-list-item .selection-indicator-container { top: 10px; right: 10px; } -.model-card .selection-indicator-container { +.horizontal .model-card .selection-indicator-container { top: 5px; right: 5px; } -.model-card-list-item .selection-indicator, .model-card .selection-indicator { +.horizontal .model-card-list-item .selection-indicator, +.horizontal .model-card .selection-indicator { margin: 4px; width: 8px; height: 8px; @@ -135,26 +139,26 @@ background-color: rgb(0, 120, 215); } -.model-card .model-table { +.horizontal .model-card .model-table { border-spacing: 5px; } -.model-table .table-row { +.horizontal .model-table .table-row { width: auto; clear: both; } -.model-table .table-cell { +.horizontal .model-table .table-cell { vertical-align: top; padding: 7px; } -.model-table a { +.horizontal .model-table a { cursor: pointer; text-decoration: underline } -.model-card-list-item { +.horizontal .model-card-list-item { display: inline-block; height: 100%; width: 100%; @@ -165,14 +169,14 @@ vertical-align: top; } -.model-card-list-item .list-item-content { +.horizontal .model-card-list-item .list-item-content { height: auto; padding: 5px 26px 5px 5px; min-height: 30px; min-width: 300px; } -.model-card-list-item .list-item-icon { +.horizontal .model-card-list-item .list-item-icon { background-position: 2px 2px; padding-left: 22px; font-size: 15px; @@ -180,40 +184,40 @@ background-size: 16px 16px; } -.model-card-list-item .list-item-description { +.horizontal .model-card-list-item .list-item-description { padding-left: 22px; } -.model-card-description-container { +.horizontal .model-card-description-container { border-top-width: 1px; border-top-style: solid; border-color: rgb(214, 214, 214); padding: 5px; } -.model-card-list-item-description { +.horizontal .model-card-list-item-description { text-align: left; } -.model-card-list-item-description-value { +.horizontal .model-card-list-item-description-value { float: right; } -.card-group { +.horizontal .card-group { display: flex; flex-flow: row; } -.model-card-description-table { +.horizontal .model-card-description-table { margin-bottom: 10px; } -.model-card-description-label-column { +.horizontal .model-card-description-label-column { text-align: left; width: 100%; } -.model-card-description-value-column { +.horizontal .model-card-description-value-column { text-align: right; white-space: nowrap; } diff --git a/src/sql/workbench/browser/modelComponents/media/verticalCard.css b/src/sql/workbench/browser/modelComponents/media/verticalCard.css new file mode 100644 index 0000000000..9e22fdc64e --- /dev/null +++ b/src/sql/workbench/browser/modelComponents/media/verticalCard.css @@ -0,0 +1,86 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the Source EULA. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +/* + !!!!NOTICE!!!! + This CSS file is only to be used with vertical selector. + If you want to reuse some of the stuff here, just copy/paste them. + */ + +.vertical .card-group { + display: flex; + flex-direction: column; +} + +.vertical .model-card { + display: flex; + flex-direction: row; + align-items: center; + padding: 10px; +} + +.vertical .model-card .model-card>* { + margin: 5px; +} + +.vertical .model-card .selection-indicator-container { + width: 16px; + height: 16px; + border-radius: 50%; + background-color: white; + border-width: 1px; + border-color: rgb(214, 214, 214); + border-style: solid; +} + +.vertical .model-card .selection-indicator { + border-radius: 50%; + width: 8px; + height: 8px; + background-color: rgb(0, 120, 215); + margin: 4px; +} + +/* Icon container */ +.vertical .model-card .icon-container { + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; + padding-right: 5px; + padding-left: 5px; +} + +/* The icon itself */ +.vertical .model-card .icon-container .icon { + display: inline-block; + width: 100%; + height: 100%; + max-width: 50px; + max-height: 50px; + background-position: center; + background-repeat: no-repeat; + background-size: contain; +} + +.vertical .model-card .text-container { + display: flex; + flex-direction: column; + padding-left: 5px; +} + +.vertical .model-card .text-container .inner-text-content { + display: flex; + flex-direction: row; + padding-bottom: 5px; +} + +.vertical .model-card .text-value { + padding-right: 5px; +} + +.vertical .model-card .link-value .codicon { + padding-left: 5px; +} diff --git a/src/sql/workbench/browser/modelComponents/radioCardGroup.component.html b/src/sql/workbench/browser/modelComponents/radioCardGroup.component.html index a385554153..6f317e6f5e 100644 --- a/src/sql/workbench/browser/modelComponents/radioCardGroup.component.html +++ b/src/sql/workbench/browser/modelComponents/radioCardGroup.component.html @@ -1,31 +1,27 @@ -
-