mirror of
https://github.com/Azure/cosmos-explorer.git
synced 2025-12-22 10:21:37 +00:00
Added SelfServe UI updates (#559)
* Added SelfServe UI modifications * fixed lint error * addressed PR comments
This commit is contained in:
committed by
GitHub
parent
9db0975f7f
commit
be4e490a64
@@ -1,4 +1,4 @@
|
||||
import { PropertyInfo, OnChange, Values, IsDisplayable, RefreshOptions } from "../Decorators";
|
||||
import { IsDisplayable, OnChange, PropertyInfo, RefreshOptions, Values } from "../Decorators";
|
||||
import {
|
||||
ChoiceItem,
|
||||
Description,
|
||||
@@ -12,14 +12,14 @@ import {
|
||||
SmartUiInput,
|
||||
} from "../SelfServeTypes";
|
||||
import {
|
||||
getMaxCollectionThroughput,
|
||||
getMaxDatabaseThroughput,
|
||||
getMinCollectionThroughput,
|
||||
getMinDatabaseThroughput,
|
||||
initialize,
|
||||
onRefreshSelfServeExample,
|
||||
Regions,
|
||||
update,
|
||||
initialize,
|
||||
getMinDatabaseThroughput,
|
||||
getMaxDatabaseThroughput,
|
||||
getMinCollectionThroughput,
|
||||
getMaxCollectionThroughput,
|
||||
} from "./SelfServeExample.rp";
|
||||
|
||||
const regionDropdownItems: ChoiceItem[] = [
|
||||
@@ -203,11 +203,7 @@ export default class SelfServeExample extends SelfServeBaseClass {
|
||||
public initialize = async (): Promise<Map<string, SmartUiInput>> => {
|
||||
const initializeResponse = await initialize();
|
||||
const defaults = new Map<string, SmartUiInput>();
|
||||
const currentRegionText = `current region selected is ${initializeResponse.regions}`;
|
||||
defaults.set("currentRegionText", {
|
||||
value: { textTKey: currentRegionText, type: DescriptionType.Text } as Description,
|
||||
hidden: false,
|
||||
});
|
||||
defaults.set("currentRegionText", undefined);
|
||||
defaults.set("regions", { value: initializeResponse.regions });
|
||||
defaults.set("enableLogging", { value: initializeResponse.enableLogging });
|
||||
const accountName = initializeResponse.accountName;
|
||||
|
||||
@@ -1,17 +1,17 @@
|
||||
import { Spinner, SpinnerSize } from "office-ui-fabric-react";
|
||||
import { initializeIcons } from "office-ui-fabric-react/lib/Icons";
|
||||
import * as React from "react";
|
||||
import ReactDOM from "react-dom";
|
||||
import { normalizeArmEndpoint } from "../Common/EnvironmentUtility";
|
||||
import { sendMessage } from "../Common/MessageHandler";
|
||||
import { configContext, updateConfigContext } from "../ConfigContext";
|
||||
import { SelfServeFrameInputs } from "../Contracts/ViewModels";
|
||||
import { updateUserContext } from "../UserContext";
|
||||
import { isInvalidParentFrameOrigin } from "../Utils/MessageValidation";
|
||||
import "./SelfServe.less";
|
||||
import { SelfServeComponent } from "./SelfServeComponent";
|
||||
import { SelfServeDescriptor } from "./SelfServeTypes";
|
||||
import { SelfServeType } from "./SelfServeUtils";
|
||||
import { SelfServeFrameInputs } from "../Contracts/ViewModels";
|
||||
import { initializeIcons } from "office-ui-fabric-react/lib/Icons";
|
||||
import { configContext, updateConfigContext } from "../ConfigContext";
|
||||
import { normalizeArmEndpoint } from "../Common/EnvironmentUtility";
|
||||
import { updateUserContext } from "../UserContext";
|
||||
import "./SelfServe.less";
|
||||
import { Spinner, SpinnerSize } from "office-ui-fabric-react";
|
||||
initializeIcons();
|
||||
|
||||
const getDescriptor = async (selfServeType: SelfServeType): Promise<SelfServeDescriptor> => {
|
||||
|
||||
@@ -1,34 +1,36 @@
|
||||
import React from "react";
|
||||
import { TFunction } from "i18next";
|
||||
import {
|
||||
CommandBar,
|
||||
ICommandBarItemProps,
|
||||
IStackTokens,
|
||||
MessageBar,
|
||||
MessageBarType,
|
||||
Separator,
|
||||
Spinner,
|
||||
SpinnerSize,
|
||||
Stack,
|
||||
} from "office-ui-fabric-react";
|
||||
import promiseRetry, { AbortError } from "p-retry";
|
||||
import React from "react";
|
||||
import { Translation } from "react-i18next";
|
||||
import * as _ from "underscore";
|
||||
import { sendMessage } from "../Common/MessageHandler";
|
||||
import { SelfServeMessageTypes } from "../Contracts/SelfServeContracts";
|
||||
import { SmartUiComponent, SmartUiDescriptor } from "../Explorer/Controls/SmartUi/SmartUiComponent";
|
||||
import "../i18n";
|
||||
import { commandBarItemStyles, commandBarStyles, containerStackTokens, separatorStyles } from "./SelfServeStyles";
|
||||
import {
|
||||
AnyDisplay,
|
||||
Node,
|
||||
BooleanInput,
|
||||
ChoiceInput,
|
||||
DescriptionDisplay,
|
||||
InputType,
|
||||
Node,
|
||||
NumberInput,
|
||||
RefreshResult,
|
||||
SelfServeDescriptor,
|
||||
SmartUiInput,
|
||||
DescriptionDisplay,
|
||||
StringInput,
|
||||
NumberInput,
|
||||
BooleanInput,
|
||||
ChoiceInput,
|
||||
} from "./SelfServeTypes";
|
||||
import { SmartUiComponent, SmartUiDescriptor } from "../Explorer/Controls/SmartUi/SmartUiComponent";
|
||||
import { Translation } from "react-i18next";
|
||||
import { TFunction } from "i18next";
|
||||
import "../i18n";
|
||||
import { sendMessage } from "../Common/MessageHandler";
|
||||
import { SelfServeMessageTypes } from "../Contracts/SelfServeContracts";
|
||||
import promiseRetry, { AbortError } from "p-retry";
|
||||
|
||||
interface SelfServeNotification {
|
||||
message: string;
|
||||
@@ -127,7 +129,7 @@ export class SelfServeComponent extends React.Component<SelfServeComponentProps,
|
||||
this.props.descriptor.inputNames.map((inputName) => {
|
||||
let initialValue = initialValues.get(inputName);
|
||||
if (!initialValue) {
|
||||
initialValue = { value: undefined, hidden: false };
|
||||
initialValue = { value: undefined, hidden: false, disabled: false };
|
||||
}
|
||||
currentValues = currentValues.set(inputName, initialValue);
|
||||
baselineValues = baselineValues.set(inputName, initialValue);
|
||||
@@ -311,34 +313,41 @@ export class SelfServeComponent extends React.Component<SelfServeComponentProps,
|
||||
this.performSave();
|
||||
};
|
||||
|
||||
public isDiscardButtonDisabled = (): boolean => {
|
||||
if (this.state.isSaving) {
|
||||
return true;
|
||||
}
|
||||
public isInputModified = (): boolean => {
|
||||
for (const key of this.state.currentValues.keys()) {
|
||||
const currentValue = JSON.stringify(this.state.currentValues.get(key));
|
||||
const baselineValue = JSON.stringify(this.state.baselineValues.get(key));
|
||||
const currentValue = this.state.currentValues.get(key);
|
||||
if (currentValue && currentValue.hidden === undefined) {
|
||||
currentValue.hidden = false;
|
||||
}
|
||||
if (currentValue && currentValue.disabled === undefined) {
|
||||
currentValue.disabled = false;
|
||||
}
|
||||
|
||||
if (currentValue !== baselineValue) {
|
||||
return false;
|
||||
const baselineValue = this.state.baselineValues.get(key);
|
||||
if (baselineValue && baselineValue.hidden === undefined) {
|
||||
baselineValue.hidden = false;
|
||||
}
|
||||
if (baselineValue && baselineValue.disabled === undefined) {
|
||||
baselineValue.disabled = false;
|
||||
}
|
||||
|
||||
if (!_.isEqual(currentValue, baselineValue)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
return false;
|
||||
};
|
||||
|
||||
public isRefreshing = (): boolean => {
|
||||
return this.state.isSaving || this.state.isInitializing || this.state.refreshResult?.isUpdateInProgress;
|
||||
};
|
||||
|
||||
public isDiscardButtonDisabled = (): boolean => {
|
||||
return this.isRefreshing() || !this.isInputModified();
|
||||
};
|
||||
|
||||
public isSaveButtonDisabled = (): boolean => {
|
||||
if (this.state.hasErrors || this.state.isSaving) {
|
||||
return true;
|
||||
}
|
||||
for (const key of this.state.currentValues.keys()) {
|
||||
const currentValue = JSON.stringify(this.state.currentValues.get(key));
|
||||
const baselineValue = JSON.stringify(this.state.baselineValues.get(key));
|
||||
|
||||
if (currentValue !== baselineValue) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
return this.state.hasErrors || this.isRefreshing() || !this.isInputModified();
|
||||
};
|
||||
|
||||
private performRefresh = async (): Promise<void> => {
|
||||
@@ -397,7 +406,6 @@ export class SelfServeComponent extends React.Component<SelfServeComponentProps,
|
||||
key: "save",
|
||||
text: this.getCommonTranslation("Save"),
|
||||
iconProps: { iconName: "Save" },
|
||||
split: true,
|
||||
disabled: this.isSaveButtonDisabled(),
|
||||
onClick: () => this.onSaveButtonClick(),
|
||||
},
|
||||
@@ -405,21 +413,21 @@ export class SelfServeComponent extends React.Component<SelfServeComponentProps,
|
||||
key: "discard",
|
||||
text: this.getCommonTranslation("Discard"),
|
||||
iconProps: { iconName: "Undo" },
|
||||
split: true,
|
||||
disabled: this.isDiscardButtonDisabled(),
|
||||
onClick: () => {
|
||||
this.discard();
|
||||
},
|
||||
buttonStyles: commandBarItemStyles,
|
||||
},
|
||||
{
|
||||
key: "refresh",
|
||||
text: this.getCommonTranslation("Refresh"),
|
||||
disabled: this.state.isInitializing,
|
||||
iconProps: { iconName: "Refresh" },
|
||||
split: true,
|
||||
onClick: () => {
|
||||
this.onRefreshClicked();
|
||||
},
|
||||
buttonStyles: commandBarItemStyles,
|
||||
},
|
||||
];
|
||||
};
|
||||
@@ -432,7 +440,6 @@ export class SelfServeComponent extends React.Component<SelfServeComponentProps,
|
||||
};
|
||||
|
||||
public render(): JSX.Element {
|
||||
const containerStackTokens: IStackTokens = { childrenGap: 5 };
|
||||
if (this.state.compileErrorMessage) {
|
||||
return <MessageBar messageBarType={MessageBarType.error}>{this.state.compileErrorMessage}</MessageBar>;
|
||||
}
|
||||
@@ -445,13 +452,13 @@ export class SelfServeComponent extends React.Component<SelfServeComponentProps,
|
||||
|
||||
return (
|
||||
<div style={{ overflowX: "auto" }}>
|
||||
<Stack tokens={containerStackTokens} styles={{ root: { padding: 10 } }}>
|
||||
<CommandBar styles={{ root: { paddingLeft: 0 } }} items={this.getCommandBarItems()} />
|
||||
<Stack tokens={containerStackTokens}>
|
||||
<Stack.Item>
|
||||
<CommandBar styles={commandBarStyles} items={this.getCommandBarItems()} />
|
||||
<Separator styles={separatorStyles} />
|
||||
</Stack.Item>
|
||||
{this.state.isInitializing ? (
|
||||
<Spinner
|
||||
size={SpinnerSize.large}
|
||||
styles={{ root: { textAlign: "center", justifyContent: "center", width: "100%", height: "100%" } }}
|
||||
/>
|
||||
<Spinner size={SpinnerSize.large} />
|
||||
) : (
|
||||
<>
|
||||
{this.state.notification && (
|
||||
|
||||
20
src/SelfServe/SelfServeStyles.tsx
Normal file
20
src/SelfServe/SelfServeStyles.tsx
Normal file
@@ -0,0 +1,20 @@
|
||||
import { IButtonStyles, ICommandBarStyles, ISeparatorStyles, IStackTokens } from "office-ui-fabric-react";
|
||||
import { StyleConstants } from "../Common/Constants";
|
||||
|
||||
export const commandBarItemStyles: IButtonStyles = { root: { paddingLeft: 20 } };
|
||||
|
||||
export const commandBarStyles: ICommandBarStyles = { root: { paddingLeft: 0 } };
|
||||
|
||||
export const containerStackTokens: IStackTokens = { childrenGap: 5, padding: 10 };
|
||||
|
||||
export const separatorStyles: Partial<ISeparatorStyles> = {
|
||||
root: {
|
||||
selectors: {
|
||||
"::before": {
|
||||
background: StyleConstants.BaseMedium,
|
||||
},
|
||||
},
|
||||
padding: 0,
|
||||
height: 1,
|
||||
},
|
||||
};
|
||||
@@ -1,6 +1,6 @@
|
||||
import "reflect-metadata";
|
||||
import { userContext } from "../UserContext";
|
||||
import {
|
||||
Node,
|
||||
AnyDisplay,
|
||||
BooleanInput,
|
||||
ChoiceInput,
|
||||
@@ -10,13 +10,13 @@ import {
|
||||
Info,
|
||||
InputType,
|
||||
InputTypeValue,
|
||||
Node,
|
||||
NumberInput,
|
||||
RefreshParams,
|
||||
SelfServeDescriptor,
|
||||
SmartUiInput,
|
||||
StringInput,
|
||||
RefreshParams,
|
||||
} from "./SelfServeTypes";
|
||||
import { userContext } from "../UserContext";
|
||||
|
||||
export enum SelfServeType {
|
||||
// No self serve type passed, launch explorer
|
||||
@@ -195,5 +195,5 @@ export const generateBladeLink = (blade: BladeType): string => {
|
||||
const subscriptionId = userContext.subscriptionId;
|
||||
const resourceGroupName = userContext.resourceGroup;
|
||||
const databaseAccountName = userContext.databaseAccount.name;
|
||||
return `www.portal.azure.com/#@microsoft.onmicrosoft.com/resource/subscriptions/${subscriptionId}/resourceGroups/${resourceGroupName}/providers/Microsoft.DocumentDb/databaseAccounts/${databaseAccountName}/${blade}`;
|
||||
return `https://portal.azure.com/#@microsoft.onmicrosoft.com/resource/subscriptions/${subscriptionId}/resourceGroups/${resourceGroupName}/providers/Microsoft.DocumentDb/databaseAccounts/${databaseAccountName}/${blade}`;
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user