initial commit for right panel

This commit is contained in:
Srinath Narayanan 2021-07-30 12:25:40 +05:30
parent 6d46e48490
commit 09cb9c80bd
7 changed files with 78 additions and 22 deletions

View File

@ -1,6 +1,7 @@
import {
Dropdown,
IDropdownOption,
DocumentCard,
DocumentCardDetails,
Dropdown, IDropdownOption,
IStackTokens,
Label,
Link,
@ -12,19 +13,19 @@ import {
Stack,
Text,
TextField,
Toggle,
Toggle
} from "@fluentui/react";
import { TFunction } from "i18next";
import * as React from "react";
import {
ChoiceItem,
Description,
DescriptionType,
Info,
DescriptionType, Info,
InputType,
InputTypeValue,
NumberUiType,
SmartUiInput,
Style
} from "../../../SelfServe/SelfServeTypes";
import { ToolTipLabelComponent } from "../Settings/SettingsSubComponents/ToolTipLabelComponent";
import * as InputUtils from "./InputUtils";
@ -87,6 +88,7 @@ interface Node {
info?: Info;
input?: AnyDisplay;
children?: Node[];
style?: Style
}
export interface SmartUiDescriptor {
@ -194,6 +196,14 @@ export class SmartUiComponent extends React.Component<SmartUiComponentProps, Sma
if (description.type === DescriptionType.Text) {
return descriptionElement;
} else if (description.type === DescriptionType.Card) {
return (
<DocumentCard styles={{ root: { display: "inline-block", padding: 10 } }}>
<DocumentCardDetails>
{descriptionElement}
</DocumentCardDetails>
</DocumentCard>
)
}
const messageBarType =
description.type === DescriptionType.InfoMessageBar ? MessageBarType.info : MessageBarType.warning;
@ -396,18 +406,29 @@ export class SmartUiComponent extends React.Component<SmartUiComponentProps, Sma
}
}
private renderNode(node: Node): JSX.Element {
private renderNode(node: Node, isSectionFloatRight: boolean): JSX.Element {
const containerStackTokens: IStackTokens = { childrenGap: 10 };
const isNodeFloatRight = node.style?.isFloatRight === true;
console.log(isSectionFloatRight, isNodeFloatRight, node.id)
return (
<Stack tokens={containerStackTokens} className="widgetRendererContainer">
<Stack.Item>{node.input && this.renderElement(node.input, node.info as Info)}</Stack.Item>
{node.children && node.children.map((child) => <div key={child.id}>{this.renderNode(child)}</div>)}
{isSectionFloatRight === isNodeFloatRight ?
<>
<Stack.Item>{node.input && this.renderElement(node.input, node.info as Info)}</Stack.Item>
</>
: <></>
}
{node.children && node.children.map((child) => <div key={child.id}>{this.renderNode(child, isSectionFloatRight)}</div>)}
</Stack>
);
}
render(): JSX.Element {
return this.renderNode(this.props.descriptor.root);
return (
<Stack horizontal tokens={{ childrenGap: 50 }}>
{this.renderNode(this.props.descriptor.root, false)}
{this.renderNode(this.props.descriptor.root, true)}
</Stack>
);
}
}

View File

@ -2,7 +2,7 @@
* @module SelfServe/Decorators
*/
import { ChoiceItem, Description, Info, NumberUiType, OnChangeCallback, RefreshParams } from "./SelfServeTypes";
import { ChoiceItem, Description, Info, NumberUiType, OnChangeCallback, RefreshParams, Style } from "./SelfServeTypes";
import { addPropertyToMap, buildSmartUiDescriptor, DecoratorProperties } from "./SelfServeUtils";
type ValueOf<T> = T[keyof T];
@ -162,6 +162,14 @@ export const PropertyInfo = (info: (() => Promise<Info>) | Info): PropertyDecora
return addToMap({ name: "info", value: info });
};
/**
* Indicates that the UI element corresponding to the property should have an Info bubble. The Info
* bubble is the icon that looks like an "i" which users click on to get more information about the UI element.
*/
export const Styles = (style: (() => Promise<Style>) | Style): PropertyDecorator => {
return addToMap({ name: "style", value: style });
};
/**
* Indicates that this property should correspond to a UI element with the given parameters.
*/

View File

@ -1,4 +1,4 @@
import { IsDisplayable, OnChange, PropertyInfo, RefreshOptions, Values } from "../Decorators";
import { IsDisplayable, OnChange, PropertyInfo, RefreshOptions, Styles, Values } from "../Decorators";
import { selfServeTraceStart, selfServeTraceSuccess } from "../SelfServeTelemetryProcessor";
import {
ChoiceItem,
@ -10,7 +10,7 @@ import {
OnSaveResult,
RefreshResult,
SelfServeBaseClass,
SmartUiInput,
SmartUiInput
} from "../SelfServeTypes";
import {
getMaxCollectionThroughput,
@ -19,7 +19,7 @@ import {
getMinDatabaseThroughput,
initialize,
onRefreshSelfServeExample,
update,
update
} from "./SelfServeExample.rp";
import { AccountProps, Regions } from "./SelfServeExample.types";
@ -203,6 +203,20 @@ export default class SelfServeExample extends SelfServeBaseClass {
})
enableLogging: boolean;
@Styles({ isFloatRight: true })
@Values({
labelTKey: "DescriptionLabel",
description: {
textTKey: "DescriptionText",
type: DescriptionType.Card,
link: {
href: "https://aka.ms/cosmos-create-account-portal",
textTKey: "DecriptionLinkText",
},
},
})
rightDescription: string;
@Values({
labelTKey: "Account Name",
placeholderTKey: "AccountNamePlaceHolder",

View File

@ -7,7 +7,7 @@ import {
Spinner,
SpinnerSize,
Stack,
Text,
Text
} from "@fluentui/react";
import { TFunction } from "i18next";
import promiseRetry, { AbortError } from "p-retry";
@ -32,7 +32,7 @@ import {
SelfServeComponentTelemetryType,
SelfServeDescriptor,
SmartUiInput,
StringInput,
StringInput
} from "./SelfServeTypes";
interface SelfServeNotification {
@ -186,6 +186,7 @@ export class SelfServeComponent extends React.Component<SelfServeComponentProps,
baselineValues: Map<string, SmartUiInput>
): Promise<void> => {
currentNode.info = await this.getResolvedValue(currentNode.info);
currentNode.style = await this.getResolvedValue(currentNode.style);
if (currentNode.input) {
currentNode.input = await this.getResolvedInput(currentNode.input, currentValues, baselineValues);

View File

@ -55,6 +55,7 @@ export interface Node {
info?: (() => Promise<Info>) | Info;
input?: AnyDisplay;
children?: Node[];
style?: (() => Promise<Style>) | Style;
}
/**@internal */
@ -82,6 +83,13 @@ export type AnyDisplay = NumberInput | BooleanInput | StringInput | ChoiceInput
/**@internal */
export type InputTypeValue = "number" | "string" | "boolean" | "object";
/**
* Describes the styling of the UI element.
*/
export interface Style {
isFloatRight: boolean
}
export type initializeCallback =
/**
* @returns Promise of Map of propertyName => {@linkcode SmartUiInput} which will become the current state of the UI.
@ -228,6 +236,7 @@ export enum DescriptionType {
* Show the description as a Warning Message bar.
*/
WarningMessageBar,
Card
}
/**

View File

@ -20,6 +20,7 @@ import {
SelfServeDescriptor,
SmartUiInput,
StringInput,
Style
} from "./SelfServeTypes";
/**
@ -92,6 +93,7 @@ export interface DecoratorProperties {
description?: (() => Promise<Description>) | Description;
isDynamicDescription?: boolean;
refreshParams?: RefreshParams;
style?: (() => Promise<Style>) | Style;
onChange?: (
newValue: InputType,
currentState: Map<string, SmartUiInput>,
@ -197,6 +199,7 @@ const addToDescriptor = (
info: value.info,
input: getInput(value),
children: [],
style: value.style
} as Node;
context.delete(key);
root.children.push(element);

View File

@ -1,28 +1,27 @@
import { IsDisplayable, OnChange, PropertyInfo, RefreshOptions, Values } from "../Decorators";
import { IsDisplayable, OnChange, PropertyInfo, RefreshOptions, Styles, Values } from "../Decorators";
import { selfServeTrace } from "../SelfServeTelemetryProcessor";
import {
ChoiceItem,
Description,
DescriptionType,
Info,
DescriptionType, Info,
InputType,
NumberUiType,
OnSaveResult,
RefreshResult,
SelfServeBaseClass,
SmartUiInput,
SmartUiInput
} from "../SelfServeTypes";
import { BladeType, generateBladeLink } from "../SelfServeUtils";
import {
deleteDedicatedGatewayResource,
getCurrentProvisioningState,
refreshDedicatedGatewayProvisioning,
updateDedicatedGatewayResource,
updateDedicatedGatewayResource
} from "./SqlX.rp";
const costPerHourValue: Description = {
textTKey: "CostText",
type: DescriptionType.Text,
type: DescriptionType.Card,
link: {
href: "https://aka.ms/cosmos-db-dedicated-gateway-pricing",
textTKey: "DedicatedGatewayPricing",
@ -338,6 +337,7 @@ export default class SqlX extends SelfServeBaseClass {
})
instances: number;
@Styles({ isFloatRight: true })
@Values({
labelTKey: "Cost",
isDynamicDescription: true,