Cleanup Synapse+Spark Logic (#813)

This commit is contained in:
Steve Faulkner
2021-05-25 14:46:52 -05:00
committed by GitHub
parent 522fdc69ab
commit e7e15c54b3
22 changed files with 46 additions and 6746 deletions

View File

@@ -1,142 +0,0 @@
import { DefaultButton, IButtonStyles, IContextualMenuItem, IContextualMenuProps } from "@fluentui/react";
import * as React from "react";
import { getErrorMessage } from "../../../Common/ErrorHandlingUtils";
import * as Logger from "../../../Common/Logger";
import { ArcadiaWorkspace, SparkPool } from "../../../Contracts/DataModels";
export interface ArcadiaMenuPickerProps {
selectText?: string;
disableSubmenu?: boolean;
selectedSparkPool: string;
workspaces: ArcadiaWorkspaceItem[];
onSparkPoolSelect: (
e: React.MouseEvent<HTMLElement> | React.KeyboardEvent<HTMLElement>,
item: IContextualMenuItem
) => boolean | void;
onCreateNewWorkspaceClicked: () => boolean | void;
onCreateNewSparkPoolClicked: (workspaceResourceId: string) => boolean | void;
}
interface ArcadiaMenuPickerStates {
selectedSparkPool: string;
}
export interface ArcadiaWorkspaceItem extends ArcadiaWorkspace {
sparkPools: SparkPool[];
}
export class ArcadiaMenuPicker extends React.Component<ArcadiaMenuPickerProps, ArcadiaMenuPickerStates> {
constructor(props: ArcadiaMenuPickerProps) {
super(props);
this.state = {
selectedSparkPool: props.selectedSparkPool,
};
}
private _onSparkPoolClicked = (
e: React.MouseEvent<HTMLElement> | React.KeyboardEvent<HTMLElement>,
item: IContextualMenuItem
): boolean | void => {
try {
this.props.onSparkPoolSelect(e, item);
this.setState({
selectedSparkPool: item.text,
});
} catch (error) {
Logger.logError(getErrorMessage(error), "ArcadiaMenuPicker/_onSparkPoolClicked");
throw error;
}
};
private _onCreateNewWorkspaceClicked = (
e: React.MouseEvent<HTMLElement> | React.KeyboardEvent<HTMLElement>,
item: IContextualMenuItem
): boolean | void => {
this.props.onCreateNewWorkspaceClicked();
};
private _onCreateNewSparkPoolClicked = (
e: React.MouseEvent<HTMLElement> | React.KeyboardEvent<HTMLElement>,
item: IContextualMenuItem
): boolean | void => {
this.props.onCreateNewSparkPoolClicked(item.key);
};
public render() {
const { workspaces } = this.props;
let workspaceMenuItems: IContextualMenuItem[] = workspaces.map((workspace) => {
let sparkPoolsMenuProps: IContextualMenuProps = {
items: workspace.sparkPools.map(
(sparkpool): IContextualMenuItem => ({
key: sparkpool.id,
text: sparkpool.name,
onClick: this._onSparkPoolClicked,
})
),
};
if (!sparkPoolsMenuProps.items.length) {
sparkPoolsMenuProps.items.push({
key: workspace.id,
text: "Create new spark pool",
onClick: this._onCreateNewSparkPoolClicked,
});
}
return {
key: workspace.id,
text: workspace.name,
subMenuProps: this.props.disableSubmenu ? undefined : sparkPoolsMenuProps,
};
});
if (!workspaceMenuItems.length) {
workspaceMenuItems.push({
key: "create_workspace",
text: "Create new workspace",
onClick: this._onCreateNewWorkspaceClicked,
});
}
const dropdownStyle: IButtonStyles = {
root: {
backgroundColor: "transparent",
margin: "auto 5px",
padding: "0",
border: "0",
},
rootHovered: {
backgroundColor: "transparent",
},
rootChecked: {
backgroundColor: "transparent",
},
rootFocused: {
backgroundColor: "transparent",
},
rootExpanded: {
backgroundColor: "transparent",
},
flexContainer: {
height: "30px",
border: "1px solid #a6a6a6",
padding: "0 8px",
},
label: {
fontWeight: "400",
fontSize: "12px",
},
};
return (
<DefaultButton
text={this.state.selectedSparkPool || this.props.selectText || "Select a Spark pool"}
persistMenu={true}
className="arcadia-menu-picker"
menuProps={{
items: workspaceMenuItems,
}}
styles={dropdownStyle}
/>
);
}
}

View File

@@ -1,15 +1,12 @@
import * as StringUtils from "../../../Utils/StringUtils";
import { KeyCodes } from "../../../Common/Constants";
import * as TelemetryProcessor from "../../../Shared/Telemetry/TelemetryProcessor";
import { Action, ActionModifiers } from "../../../Shared/Telemetry/TelemetryConstants";
import CollapseChevronDownIcon from "../../../../images/QueryBuilder/CollapseChevronDown_16x.png";
/**
* React component for Command button component.
*/
import * as React from "react";
import { ArcadiaMenuPickerProps } from "../Arcadia/ArcadiaMenuPicker";
import CollapseChevronDownIcon from "../../../../images/QueryBuilder/CollapseChevronDown_16x.png";
import { KeyCodes } from "../../../Common/Constants";
import { Action, ActionModifiers } from "../../../Shared/Telemetry/TelemetryConstants";
import * as TelemetryProcessor from "../../../Shared/Telemetry/TelemetryProcessor";
import * as StringUtils from "../../../Utils/StringUtils";
/**
* Options for this component
@@ -114,15 +111,6 @@ export interface CommandButtonComponentProps {
* Aria-label for the button
*/
ariaLabel: string;
//TODO: generalize customized command bar
/**
* If set to true, will render arcadia picker
*/
isArcadiaPicker?: boolean;
/**
* props to render arcadia picker
*/
arcadiaProps?: ArcadiaMenuPickerProps;
}
export class CommandButtonComponent extends React.Component<CommandButtonComponentProps> {

View File

@@ -1,308 +0,0 @@
import * as ko from "knockout";
import { KeyCodes } from "../../../Common/Constants";
import * as ViewModels from "../../../Contracts/ViewModels";
import { FreeTierLimits } from "../../../Shared/Constants";
import { Action, ActionModifiers } from "../../../Shared/Telemetry/TelemetryConstants";
import * as TelemetryProcessor from "../../../Shared/Telemetry/TelemetryProcessor";
import * as AutoPilotUtils from "../../../Utils/AutoPilotUtils";
import { WaitsForTemplateViewModel } from "../../WaitsForTemplateViewModel";
import ThroughputInputComponentAutoscaleV3 from "./ThroughputInputComponentAutoscaleV3.html";
/**
* Throughput Input:
*
* Creates a set of controls to input, sanitize and increase/decrease throughput
*
* How to use in your markup:
* <throughput-input params="{ value: anObservableToHoldTheValue, minimum: anObservableWithMinimum, maximum: anObservableWithMaximum }">
* </throughput-input>
*
*/
/**
* Parameters for this component
*/
export interface ThroughputInputParams {
/**
* Callback triggered when the template is bound to the component (for testing purposes)
*/
onTemplateReady?: () => void;
/**
* Observable to bind the Throughput value to
*/
value: ViewModels.Editable<number>;
/**
* Text to use as id for testing
*/
testId: string;
/**
* Text to use as aria-label
*/
ariaLabel?: ko.Observable<string>;
/**
* Minimum value in the range
*/
minimum: ko.Observable<number>;
/**
* Maximum value in the range
*/
maximum: ko.Observable<number>;
/**
* Step value for increase/decrease
*/
step?: number;
/**
* Observable to bind the Throughput enabled status
*/
isEnabled?: ko.Observable<boolean>;
/**
* Should show pricing controls
*/
costsVisible: ko.Observable<boolean>;
/**
* RU price
*/
requestUnitsUsageCost: ko.Computed<string>; // Our code assigns to ko.Computed, but unit test assigns to ko.Observable
/**
* State of the spending acknowledge checkbox
*/
spendAckChecked?: ko.Observable<boolean>;
/**
* id of the spending acknowledge checkbox
*/
spendAckId?: ko.Observable<string>;
/**
* spending acknowledge text
*/
spendAckText?: ko.Observable<string>;
/**
* Show spending acknowledge controls
*/
spendAckVisible?: ko.Observable<boolean>;
/**
* Display * to the left of the label
*/
showAsMandatory: boolean;
/**
* If true, it will display a text to prompt users to use unlimited collections to go beyond max for fixed
*/
isFixed: boolean;
/**
* Label of the provisioned throughut control
*/
label: ko.Observable<string>;
/**
* Text of the info bubble for provisioned throughut control
*/
infoBubbleText?: ko.Observable<string>;
/**
* Computed value that decides if value can exceed maximum allowable value
*/
canExceedMaximumValue?: ko.Computed<boolean>;
/**
* CSS classes to apply on input element
*/
cssClass?: string;
isAutoPilotSelected: ko.Observable<boolean>;
throughputAutoPilotRadioId: string;
throughputProvisionedRadioId: string;
throughputModeRadioName: string;
maxAutoPilotThroughputSet: ViewModels.Editable<number>;
autoPilotUsageCost: ko.Computed<string>;
overrideWithAutoPilotSettings: ko.Observable<boolean>;
overrideWithProvisionedThroughputSettings: ko.Observable<boolean>;
freeTierExceedThroughputTooltip?: ko.Observable<string>;
freeTierExceedThroughputWarning?: ko.Observable<string>;
}
export class ThroughputInputViewModel extends WaitsForTemplateViewModel {
public ariaLabel: ko.Observable<string>;
public canExceedMaximumValue: ko.Computed<boolean>;
public step: ko.Computed<number>;
public testId: string;
public value: ViewModels.Editable<number>;
public minimum: ko.Observable<number>;
public maximum: ko.Observable<number>;
public isEnabled: ko.Observable<boolean>;
public cssClass: string;
public decreaseButtonAriaLabel: string;
public increaseButtonAriaLabel: string;
public costsVisible: ko.Observable<boolean>;
public requestUnitsUsageCost: ko.Computed<string>;
public spendAckChecked: ko.Observable<boolean>;
public spendAckId: ko.Observable<string>;
public spendAckText: ko.Observable<string>;
public spendAckVisible: ko.Observable<boolean>;
public showAsMandatory: boolean;
public infoBubbleText: string | ko.Observable<string>;
public label: ko.Observable<string>;
public isFixed: boolean;
public isAutoPilotSelected: ko.Observable<boolean>;
public throughputAutoPilotRadioId: string;
public throughputProvisionedRadioId: string;
public throughputModeRadioName: string;
public maxAutoPilotThroughputSet: ko.Observable<number>;
public autoPilotUsageCost: ko.Computed<string>;
public minAutoPilotThroughput: ko.Observable<number>;
public overrideWithAutoPilotSettings: ko.Observable<boolean>;
public overrideWithProvisionedThroughputSettings: ko.Observable<boolean>;
public isManualThroughputInputFieldRequired: ko.Computed<boolean>;
public isAutoscaleThroughputInputFieldRequired: ko.Computed<boolean>;
public freeTierExceedThroughputTooltip: ko.Observable<string>;
public freeTierExceedThroughputWarning: ko.Observable<string>;
public showFreeTierExceedThroughputTooltip: ko.Computed<boolean>;
public showFreeTierExceedThroughputWarning: ko.Computed<boolean>;
public constructor(options: ThroughputInputParams) {
super();
super.onTemplateReady((isTemplateReady: boolean) => {
if (isTemplateReady && options.onTemplateReady) {
options.onTemplateReady();
}
});
const params: ThroughputInputParams = options;
this.testId = params.testId || "ThroughputValue";
this.ariaLabel = ko.observable((params.ariaLabel && params.ariaLabel()) || "");
this.canExceedMaximumValue = params.canExceedMaximumValue || ko.computed(() => false);
this.isEnabled = params.isEnabled || ko.observable(true);
this.cssClass = params.cssClass || "textfontclr collid migration";
this.minimum = params.minimum;
this.maximum = params.maximum;
this.value = params.value;
this.costsVisible = options.costsVisible;
this.requestUnitsUsageCost = options.requestUnitsUsageCost;
this.spendAckChecked = options.spendAckChecked || ko.observable<boolean>(false);
this.spendAckId = options.spendAckId || ko.observable<string>();
this.spendAckText = options.spendAckText || ko.observable<string>();
this.spendAckVisible = options.spendAckVisible || ko.observable<boolean>(false);
this.showAsMandatory = !!options.showAsMandatory;
this.isFixed = !!options.isFixed;
this.infoBubbleText = options.infoBubbleText || ko.observable<string>();
this.label = options.label || ko.observable<string>();
this.isAutoPilotSelected = options.isAutoPilotSelected || ko.observable<boolean>(false);
this.isAutoPilotSelected.subscribe((value) => {
TelemetryProcessor.trace(Action.ToggleAutoscaleSetting, ActionModifiers.Mark, {
changedSelectedValueTo: value ? ActionModifiers.ToggleAutoscaleOn : ActionModifiers.ToggleAutoscaleOff,
dataExplorerArea: "Scale Tab V1",
});
});
this.throughputAutoPilotRadioId = options.throughputAutoPilotRadioId;
this.throughputProvisionedRadioId = options.throughputProvisionedRadioId;
this.throughputModeRadioName = options.throughputModeRadioName;
this.overrideWithAutoPilotSettings = options.overrideWithAutoPilotSettings || ko.observable<boolean>(false);
this.overrideWithProvisionedThroughputSettings =
options.overrideWithProvisionedThroughputSettings || ko.observable<boolean>(false);
this.maxAutoPilotThroughputSet =
options.maxAutoPilotThroughputSet || ko.observable<number>(AutoPilotUtils.minAutoPilotThroughput);
this.autoPilotUsageCost = options.autoPilotUsageCost;
this.minAutoPilotThroughput = ko.observable<number>(AutoPilotUtils.minAutoPilotThroughput);
this.step = ko.pureComputed(() => {
if (this.isAutoPilotSelected()) {
return AutoPilotUtils.autoPilotIncrementStep;
}
return params.step || ThroughputInputViewModel._defaultStep;
});
this.decreaseButtonAriaLabel = "Decrease throughput by " + this.step().toString();
this.increaseButtonAriaLabel = "Increase throughput by " + this.step().toString();
this.isManualThroughputInputFieldRequired = ko.pureComputed(() => this.isEnabled() && !this.isAutoPilotSelected());
this.isAutoscaleThroughputInputFieldRequired = ko.pureComputed(
() => this.isEnabled() && this.isAutoPilotSelected()
);
this.freeTierExceedThroughputTooltip = options.freeTierExceedThroughputTooltip || ko.observable<string>();
this.freeTierExceedThroughputWarning = options.freeTierExceedThroughputWarning || ko.observable<string>();
this.showFreeTierExceedThroughputTooltip = ko.pureComputed<boolean>(
() => !!this.freeTierExceedThroughputTooltip() && this.value() > FreeTierLimits.RU
);
this.showFreeTierExceedThroughputWarning = ko.pureComputed<boolean>(
() => !!this.freeTierExceedThroughputWarning() && this.value() > FreeTierLimits.RU
);
}
public decreaseThroughput() {
let offerThroughput: number = this._getSanitizedValue();
if (offerThroughput > this.minimum()) {
offerThroughput -= this.step();
if (offerThroughput < this.minimum()) {
offerThroughput = this.minimum();
}
this.value(offerThroughput);
}
}
public increaseThroughput() {
let offerThroughput: number = this._getSanitizedValue();
if (offerThroughput < this.maximum() || this.canExceedMaximumValue()) {
offerThroughput += this.step();
if (offerThroughput > this.maximum() && !this.canExceedMaximumValue()) {
offerThroughput = this.maximum();
}
this.value(offerThroughput);
}
}
public onIncreaseKeyDown = (source: any, event: KeyboardEvent): boolean => {
if (event.keyCode === KeyCodes.Enter || event.keyCode === KeyCodes.Space) {
this.increaseThroughput();
event.stopPropagation();
return false;
}
return true;
};
public onDecreaseKeyDown = (source: any, event: KeyboardEvent): boolean => {
if (event.keyCode === KeyCodes.Enter || event.keyCode === KeyCodes.Space) {
this.decreaseThroughput();
event.stopPropagation();
return false;
}
return true;
};
private _getSanitizedValue(): number {
let throughput = this.value();
if (this.isAutoPilotSelected()) {
throughput = this.maxAutoPilotThroughputSet();
}
return isNaN(throughput) ? 0 : Number(throughput);
}
private static _defaultStep: number = 100;
}
export const ThroughputInputComponentAutoPilotV3 = {
viewModel: ThroughputInputViewModel,
template: ThroughputInputComponentAutoscaleV3,
};

View File

@@ -1,194 +0,0 @@
<div>
<div>
<p class="pkPadding">
<!-- ko if: showAsMandatory -->
<span class="mandatoryStar">*</span>
<!-- /ko -->
<span data-bind="text: label"></span>
<!-- ko if: infoBubbleText -->
<span class="infoTooltip" role="tooltip" tabindex="0">
<img class="infoImg" src="../../../../images/info-bubble.svg" alt="More information" />
<span data-bind="text: infoBubbleText" class="tooltiptext throughputRuInfo"></span>
</span>
<!-- /ko -->
</p>
</div>
<!-- ko if: !isFixed -->
<div class="throughputModeContainer">
<input
class="throughputModeRadio"
aria-label="Autopilot mode"
type="radio"
role="radio"
tabindex="0"
data-bind="
checked: isAutoPilotSelected,
checkedValue: true,
attr: {
id: throughputAutoPilotRadioId,
name: throughputModeRadioName,
'aria-checked': isAutoPilotSelected() ? 'true' : 'false'
}"
/>
<span
class="throughputModeSpace"
data-bind="
attr: {
for: throughputAutoPilotRadioId
}"
>Autoscale
</span>
<input
class="throughputModeRadio nonFirstRadio"
aria-label="Manual mode"
type="radio"
role="radio"
tabindex="0"
data-bind="
checked: isAutoPilotSelected,
checkedValue: false,
attr: {
id: throughputProvisionedRadioId,
name: throughputModeRadioName,
'aria-checked': !isAutoPilotSelected() ? 'true' : 'false'
}"
/>
<span
class="throughputModeSpace"
data-bind="attr: {
for: throughputProvisionedRadioId
}"
>Manual
</span>
</div>
<!-- /ko -->
<div data-bind="visible: isAutoPilotSelected">
<p>
<span
>Provision maximum RU/s required by this resource. Estimate your required RU/s with
<a target="_blank" href="https://cosmos.azure.com/capacitycalculator/">capacity calculator</a>.</span
>
</p>
<p>
<span>Max RU/s</span>
</p>
<div data-bind="setTemplateReady: true">
<input
data-bind="textInput: overrideWithProvisionedThroughputSettings() ? '' : maxAutoPilotThroughputSet, attr:{
disabled: overrideWithProvisionedThroughputSettings(),
step: step,
'class':'migration collid select-font-size',
min: minAutoPilotThroughput,
'aria-label': 'Max request units per second',
type: isAutoscaleThroughputInputFieldRequired() ? 'number' : 'hidden',
css: {
dirty: maxAutoPilotThroughputSet.editableIsDirty
}
}"
/>
</div>
<p data-bind="visible: overrideWithProvisionedThroughputSettings && !overrideWithProvisionedThroughputSettings()">
<span
data-bind="
html: autoPilotUsageCost"
></span>
</p>
<p
data-bind="visible: costsVisible && overrideWithProvisionedThroughputSettings && !overrideWithProvisionedThroughputSettings()"
>
<span data-bind="html: requestUnitsUsageCost"></span>
</p>
<!-- ko if: spendAckVisible -->
<p class="pkPadding">
<input
type="checkbox"
aria-label="acknowledge spend throughput"
data-bind="
attr: {
title: spendAckText,
id: spendAckId
},
checked: spendAckChecked"
/>
<span data-bind="text: spendAckText, attr: { for: spendAckId }"></span>
</p>
<!-- /ko -->
<!-- ko if: isFixed -->
<p>Choose unlimited storage capacity for more than 10,000 RU/s.</p>
<!-- /ko -->
</div>
<div data-bind="visible: !isAutoPilotSelected()">
<p>
<span
>Estimate your required throughput with
<a target="_blank" href="https://cosmos.azure.com/capacitycalculator/">capacity calculator</a></span
>
</p>
<div class="inputTooltip">
<span
data-bind="text: freeTierExceedThroughputTooltip, visible: showFreeTierExceedThroughputTooltip"
class="inputTooltipText"
></span>
</div>
<div data-bind="setTemplateReady: true">
<input
data-bind="
textInput: overrideWithAutoPilotSettings() ? maxAutoPilotThroughputSet : value,
css: {
dirty: value.editableIsDirty
},
enable: isEnabled,
attr:{
type: isManualThroughputInputFieldRequired() ? 'number' : 'hidden',
'data-test': testId,
'class': cssClass,
step: step,
min: minimum,
max: canExceedMaximumValue() ? null : maximum,
'aria-label': ariaLabel,
disabled: overrideWithAutoPilotSettings(),
required: isManualThroughputInputFieldRequired()
}"
/>
</div>
<div class="freeTierInlineWarning" data-bind="visible: showFreeTierExceedThroughputWarning">
<span class="freeTierWarningIcon"><img src="/warning.svg" alt="Warning" /></span>
<span class="freeTierWarningMessage" data-bind="text: freeTierExceedThroughputWarning"></span>
</div>
<p data-bind="visible: costsVisible">
<span data-bind="html: requestUnitsUsageCost"></span>
</p>
<!-- ko if: spendAckVisible -->
<p class="pkPadding">
<input
type="checkbox"
aria-label="acknowledge spend throughput"
data-bind="
attr: {
title: spendAckText,
id: spendAckId
},
checked: spendAckChecked"
/>
<span data-bind="text: spendAckText, attr: { for: spendAckId }"></span>
</p>
<!-- /ko -->
<!-- ko if: isFixed -->
<p>Choose unlimited storage capacity for more than 10,000 RU/s.</p>
<!-- /ko -->
</div>
</div>