Add data explorer launcher (#23)
* Initial migration from ADO * Bug fixes * Fix bugs. Make active area smaller and require shift + ctrl + dbl click * Add missing features * Switch from HashMap to Map as it is already polyfilled
This commit is contained in:
parent
f8f1df4183
commit
d70e30c4fc
|
@ -0,0 +1,20 @@
|
|||
.featurePanelComponentContainer {
|
||||
width: 800px;
|
||||
|
||||
.urlContainer {
|
||||
padding: 10px;
|
||||
margin-bottom: 10px;
|
||||
white-space: nowrap;
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
.options {
|
||||
padding: 10px;
|
||||
overflow: auto;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.checkboxRow {
|
||||
width: 390px;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
import React from "react";
|
||||
import { shallow, mount } from "enzyme";
|
||||
|
||||
import { FeaturePanelComponent } from "./FeaturePanelComponent";
|
||||
|
||||
describe("Feature panel", () => {
|
||||
it("renders all flags", () => {
|
||||
const wrapper = shallow(<FeaturePanelComponent />);
|
||||
expect(wrapper).toMatchSnapshot();
|
||||
});
|
||||
});
|
|
@ -0,0 +1,252 @@
|
|||
import * as React from "react";
|
||||
import { Stack } from "office-ui-fabric-react/lib/Stack";
|
||||
import { Dropdown, IDropdownOption, IDropdownStyles } from "office-ui-fabric-react/lib/Dropdown";
|
||||
import { Checkbox } from "office-ui-fabric-react/lib/Checkbox";
|
||||
import { TextField, ITextFieldStyles } from "office-ui-fabric-react/lib/TextField";
|
||||
import { DefaultButton } from "office-ui-fabric-react";
|
||||
import "./FeaturePanelComponent.less";
|
||||
|
||||
export const FeaturePanelComponent: React.FunctionComponent = () => {
|
||||
// Initial conditions
|
||||
const originalParams = new URLSearchParams(window.location.search);
|
||||
const urlParams = new Map(); // Params with lowercase keys
|
||||
originalParams.forEach((value: string, key: string) => urlParams.set(key.toLocaleLowerCase(), value));
|
||||
|
||||
const baseUrlOptions = [
|
||||
{ key: "https://localhost:1234/explorer.html", text: "localhost:1234" },
|
||||
{ key: "https://cosmos.azure.com/explorer.html", text: "cosmos.azure.com" },
|
||||
{ key: "https://portal.azure.com", text: "portal" }
|
||||
];
|
||||
|
||||
const platformOptions = [
|
||||
{ key: "Hosted", text: "Hosted" },
|
||||
{ key: "Portal", text: "Portal" },
|
||||
{ key: "Emulator", text: "Emulator" },
|
||||
{ key: "", text: "None" }
|
||||
];
|
||||
|
||||
// React hooks to keep state
|
||||
const [baseUrl, setBaseUrl] = React.useState<IDropdownOption>(
|
||||
baseUrlOptions.find(o => o.key === window.location.origin + window.location.pathname) || baseUrlOptions[0]
|
||||
);
|
||||
const [platform, setPlatform] = React.useState<IDropdownOption>(
|
||||
urlParams.has("platform")
|
||||
? platformOptions.find(o => o.key === urlParams.get("platform")) || platformOptions[0]
|
||||
: platformOptions[0]
|
||||
);
|
||||
|
||||
const booleanFeatures: {
|
||||
key: string;
|
||||
label: string;
|
||||
value: string;
|
||||
disabled?: () => boolean;
|
||||
reactState?: [boolean, React.Dispatch<React.SetStateAction<boolean>>];
|
||||
onChange?: (_?: React.FormEvent<HTMLElement | HTMLInputElement>, checked?: boolean) => void;
|
||||
}[] = [
|
||||
{ key: "feature.enablechangefeedpolicy", label: "Enable change feed policy", value: "true" },
|
||||
{ key: "feature.enablerupm", label: "Enable RUPM", value: "true" },
|
||||
{ key: "feature.dataexplorerexecutesproc", label: "Execute stored procedure", value: "true" },
|
||||
{ key: "feature.hosteddataexplorerenabled", label: "Hosted Data Explorer (deprecated?)", value: "true" },
|
||||
{ key: "feature.enablettl", label: "Enable TTL", value: "true" },
|
||||
{ key: "feature.enablegallery", label: "Enable Notebook Gallery", value: "true" },
|
||||
{ key: "feature.canexceedmaximumvalue", label: "Can exceed max value", value: "true" },
|
||||
{
|
||||
key: "feature.enablefixedcollectionwithsharedthroughput",
|
||||
label: "Enable fixed collection with shared throughput",
|
||||
value: "true"
|
||||
},
|
||||
{ key: "feature.ttl90days", label: "TTL 90 days", value: "true" },
|
||||
{ key: "feature.enablenotebooks", label: "Enable notebooks", value: "true" },
|
||||
{
|
||||
key: "feature.customportal",
|
||||
label: "Force Production portal (portal only)",
|
||||
value: "false",
|
||||
disabled: (): boolean => baseUrl.key !== "https://portal.azure.com"
|
||||
},
|
||||
{ key: "feature.enablespark", label: "Enable Synapse", value: "true" },
|
||||
{ key: "feature.enableautopilotv2", label: "Enable Auto-pilot V2", value: "true" }
|
||||
];
|
||||
|
||||
const stringFeatures: {
|
||||
key: string;
|
||||
label: string;
|
||||
placeholder: string;
|
||||
disabled?: () => boolean;
|
||||
reactState?: [string, React.Dispatch<React.SetStateAction<string>>];
|
||||
onChange?: (_: React.FormEvent<HTMLInputElement | HTMLTextAreaElement>, newValue?: string) => void;
|
||||
}[] = [
|
||||
{ key: "feature.notebookserverurl", label: "Notebook server URL", placeholder: "https://notebookserver" },
|
||||
{ key: "feature.notebookservertoken", label: "Notebook server token", placeholder: "" },
|
||||
{ key: "feature.notebookbasepath", label: "Notebook base path", placeholder: "" },
|
||||
{ key: "key", label: "Auth key", placeholder: "" },
|
||||
{
|
||||
key: "dataExplorerSource",
|
||||
label: "Data Explorer Source (portal only)",
|
||||
placeholder: "https://localhost:1234/explorer.html",
|
||||
disabled: (): boolean => baseUrl.key !== "https://portal.azure.com"
|
||||
},
|
||||
{ key: "feature.livyendpoint", label: "Livy endpoint", placeholder: "" }
|
||||
];
|
||||
|
||||
booleanFeatures.forEach(
|
||||
f => (f.reactState = React.useState<boolean>(urlParams.has(f.key) ? urlParams.get(f.key) === "true" : false))
|
||||
);
|
||||
stringFeatures.forEach(
|
||||
f => (f.reactState = React.useState<string>(urlParams.has(f.key) ? urlParams.get(f.key) : undefined))
|
||||
);
|
||||
|
||||
const buildUrl = (): string => {
|
||||
const fragments = (platform.key === "" ? [] : [`platform=${platform.key}`])
|
||||
.concat(booleanFeatures.map(f => (f.reactState[0] ? `${f.key}=${f.value}` : "")))
|
||||
.concat(stringFeatures.map(f => (f.reactState[0] ? `${f.key}=${encodeURIComponent(f.reactState[0])}` : "")))
|
||||
.filter(v => v && v.length > 0);
|
||||
|
||||
const paramString = fragments.length < 1 ? "" : `?${fragments.join("&")}`;
|
||||
return `${baseUrl.key}${paramString}`;
|
||||
};
|
||||
|
||||
const onChangeBaseUrl = (event: React.FormEvent<HTMLDivElement>, option?: IDropdownOption): void => {
|
||||
setBaseUrl(option);
|
||||
};
|
||||
|
||||
const onChangePlatform = (event: React.FormEvent<HTMLDivElement>, option?: IDropdownOption): void => {
|
||||
setPlatform(option);
|
||||
};
|
||||
|
||||
booleanFeatures.forEach(
|
||||
f =>
|
||||
(f.onChange = (ev?: React.FormEvent<HTMLElement | HTMLInputElement>, checked?: boolean): void => {
|
||||
f.reactState[1](checked);
|
||||
})
|
||||
);
|
||||
|
||||
stringFeatures.forEach(
|
||||
f =>
|
||||
(f.onChange = (event: React.FormEvent<HTMLInputElement | HTMLTextAreaElement>, newValue?: string): void => {
|
||||
f.reactState[1](newValue);
|
||||
})
|
||||
);
|
||||
|
||||
const onNotebookShortcut = (): void => {
|
||||
booleanFeatures.find(f => f.key === "feature.enablenotebooks").reactState[1](true);
|
||||
stringFeatures
|
||||
.find(f => f.key === "feature.notebookserverurl")
|
||||
.reactState[1]("https://localhost:10001/12345/notebook/");
|
||||
stringFeatures.find(f => f.key === "feature.notebookservertoken").reactState[1]("token");
|
||||
stringFeatures.find(f => f.key === "feature.notebookbasepath").reactState[1](".");
|
||||
setPlatform(platformOptions.find(o => o.key === "Hosted"));
|
||||
};
|
||||
|
||||
const onPortalLocalDEShortcut = (): void => {
|
||||
setBaseUrl(baseUrlOptions.find(o => o.key === "https://portal.azure.com"));
|
||||
setPlatform(platformOptions.find(o => o.key === "Portal"));
|
||||
stringFeatures.find(f => f.key === "dataExplorerSource").reactState[1]("https://localhost:1234/explorer.html");
|
||||
};
|
||||
|
||||
const onReset = (): void => {
|
||||
booleanFeatures.forEach(f => f.reactState[1](false));
|
||||
stringFeatures.forEach(f => f.reactState[1](""));
|
||||
};
|
||||
|
||||
const stackTokens = { childrenGap: 10 };
|
||||
const dropdownStyles: Partial<IDropdownStyles> = { dropdown: { width: 200 } };
|
||||
const textFieldStyles: Partial<ITextFieldStyles> = { fieldGroup: { width: 300 } };
|
||||
|
||||
// Show in 2 columns to keep it compact
|
||||
let halfSize = Math.ceil(booleanFeatures.length / 2);
|
||||
const leftBooleanFeatures = booleanFeatures.slice(0, halfSize);
|
||||
const rightBooleanFeatures = booleanFeatures.slice(halfSize, booleanFeatures.length);
|
||||
|
||||
halfSize = Math.ceil(stringFeatures.length / 2);
|
||||
const leftStringFeatures = stringFeatures.slice(0, halfSize);
|
||||
const rightStringFeatures = stringFeatures.slice(halfSize, stringFeatures.length);
|
||||
|
||||
const anchorOptions = {
|
||||
href: buildUrl(),
|
||||
target: "_blank",
|
||||
rel: "noopener"
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="featurePanelComponentContainer">
|
||||
<div className="urlContainer">
|
||||
<a {...anchorOptions}>{buildUrl()}</a>
|
||||
</div>
|
||||
<Stack className="options" tokens={stackTokens}>
|
||||
<Stack horizontal horizontalAlign="space-between" tokens={stackTokens}>
|
||||
<DefaultButton onClick={onNotebookShortcut}>Notebooks on localhost</DefaultButton>
|
||||
<DefaultButton onClick={onPortalLocalDEShortcut}>Portal points to local DE</DefaultButton>
|
||||
<DefaultButton onClick={onReset}>Reset</DefaultButton>
|
||||
</Stack>
|
||||
<Stack horizontal horizontalAlign="start" tokens={stackTokens}>
|
||||
<Dropdown
|
||||
selectedKey={baseUrl.key}
|
||||
options={baseUrlOptions}
|
||||
onChange={onChangeBaseUrl}
|
||||
label="Base Url"
|
||||
styles={dropdownStyles}
|
||||
/>
|
||||
<Dropdown
|
||||
label="Platform"
|
||||
selectedKey={platform.key}
|
||||
onChange={onChangePlatform}
|
||||
options={platformOptions}
|
||||
styles={dropdownStyles}
|
||||
/>
|
||||
</Stack>
|
||||
<Stack horizontal>
|
||||
<Stack className="checkboxRow" horizontalAlign="space-between">
|
||||
{leftBooleanFeatures.map(f => (
|
||||
<Checkbox
|
||||
key={f.key}
|
||||
label={f.label}
|
||||
checked={f.reactState[0]}
|
||||
onChange={f.onChange}
|
||||
disabled={f.disabled && f.disabled()}
|
||||
/>
|
||||
))}
|
||||
</Stack>
|
||||
<Stack className="checkboxRow" horizontalAlign="space-between">
|
||||
{rightBooleanFeatures.map(f => (
|
||||
<Checkbox
|
||||
key={f.key}
|
||||
label={f.label}
|
||||
checked={f.reactState[0]}
|
||||
onChange={f.onChange}
|
||||
disabled={f.disabled && f.disabled()}
|
||||
/>
|
||||
))}
|
||||
</Stack>
|
||||
</Stack>
|
||||
<Stack horizontal tokens={stackTokens}>
|
||||
<Stack horizontalAlign="space-between">
|
||||
{leftStringFeatures.map(f => (
|
||||
<TextField
|
||||
key={f.key}
|
||||
value={f.reactState[0]}
|
||||
label={f.label}
|
||||
onChange={f.onChange}
|
||||
styles={textFieldStyles}
|
||||
placeholder={f.placeholder}
|
||||
disabled={f.disabled && f.disabled()}
|
||||
/>
|
||||
))}
|
||||
</Stack>
|
||||
<Stack horizontalAlign="space-between">
|
||||
{rightStringFeatures.map(f => (
|
||||
<TextField
|
||||
key={f.key}
|
||||
value={f.reactState[0]}
|
||||
label={f.label}
|
||||
onChange={f.onChange}
|
||||
styles={textFieldStyles}
|
||||
placeholder={f.placeholder}
|
||||
disabled={f.disabled && f.disabled()}
|
||||
/>
|
||||
))}
|
||||
</Stack>
|
||||
</Stack>
|
||||
</Stack>
|
||||
</div>
|
||||
);
|
||||
};
|
|
@ -0,0 +1,18 @@
|
|||
.featurePanelLauncherContainer {
|
||||
.featurePanelLauncherModal {
|
||||
overflow-y: hidden;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
.ms-Dialog-main {
|
||||
overflow: hidden;
|
||||
}
|
||||
}
|
||||
|
||||
.activePatch {
|
||||
position: absolute;
|
||||
height: 20px;
|
||||
width: 20px;
|
||||
top: 20px;
|
||||
left: -20px;
|
||||
}
|
|
@ -0,0 +1,86 @@
|
|||
import * as React from "react";
|
||||
import { FeaturePanelComponent } from "./FeaturePanelComponent";
|
||||
import { getTheme, mergeStyleSets, FontWeights, Modal, IconButton, IIconProps } from "office-ui-fabric-react";
|
||||
import "./FeaturePanelLauncher.less";
|
||||
|
||||
// Modal wrapper
|
||||
export const FeaturePanelLauncher: React.FunctionComponent = (): JSX.Element => {
|
||||
const [isModalOpen, showModal] = React.useState<boolean>(false);
|
||||
|
||||
const onActivate = (event: React.MouseEvent<HTMLSpanElement>): void => {
|
||||
if (!event.shiftKey || !event.ctrlKey) {
|
||||
return;
|
||||
}
|
||||
event.stopPropagation();
|
||||
showModal(true);
|
||||
};
|
||||
|
||||
const theme = getTheme();
|
||||
const contentStyles = mergeStyleSets({
|
||||
container: {
|
||||
display: "flex",
|
||||
flexFlow: "column nowrap",
|
||||
alignItems: "stretch"
|
||||
},
|
||||
header: [
|
||||
// tslint:disable-next-line:deprecation
|
||||
theme.fonts.xLargePlus,
|
||||
{
|
||||
flex: "1 1 auto",
|
||||
borderTop: `4px solid ${theme.palette.themePrimary}`,
|
||||
color: theme.palette.neutralPrimary,
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
fontWeight: FontWeights.semibold,
|
||||
padding: "12px 12px 14px 24px"
|
||||
}
|
||||
],
|
||||
body: {
|
||||
flex: "4 4 auto",
|
||||
overflowY: "hidden",
|
||||
marginBottom: 40,
|
||||
height: "100%",
|
||||
display: "flex"
|
||||
}
|
||||
});
|
||||
|
||||
const iconButtonStyles = {
|
||||
root: {
|
||||
color: theme.palette.neutralPrimary,
|
||||
marginLeft: "auto",
|
||||
marginTop: "4px",
|
||||
marginRight: "2px"
|
||||
},
|
||||
rootHovered: {
|
||||
color: theme.palette.neutralDark
|
||||
}
|
||||
};
|
||||
const cancelIcon: IIconProps = { iconName: "Cancel" };
|
||||
const hideModal = (): void => showModal(false);
|
||||
|
||||
return (
|
||||
<span className="activePatch" onDoubleClick={onActivate}>
|
||||
<Modal
|
||||
className="featurePanelLauncherContainer"
|
||||
titleAriaId="Features"
|
||||
isOpen={isModalOpen}
|
||||
onDismiss={hideModal}
|
||||
isBlocking={false}
|
||||
scrollableContentClassName="featurePanelLauncherModal"
|
||||
>
|
||||
<div className={contentStyles.header}>
|
||||
<span>Data Explorer Launcher</span>
|
||||
<IconButton
|
||||
styles={iconButtonStyles}
|
||||
iconProps={cancelIcon}
|
||||
ariaLabel="Close popup modal"
|
||||
onClick={hideModal}
|
||||
/>
|
||||
</div>
|
||||
<div className={contentStyles.body}>
|
||||
<FeaturePanelComponent />
|
||||
</div>
|
||||
</Modal>
|
||||
</span>
|
||||
);
|
||||
};
|
|
@ -0,0 +1,312 @@
|
|||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`Feature panel renders all flags 1`] = `
|
||||
<div
|
||||
className="featurePanelComponentContainer"
|
||||
>
|
||||
<div
|
||||
className="urlContainer"
|
||||
>
|
||||
<a
|
||||
href="https://localhost:1234/explorer.html?platform=Hosted"
|
||||
rel="noopener"
|
||||
target="_blank"
|
||||
>
|
||||
https://localhost:1234/explorer.html?platform=Hosted
|
||||
</a>
|
||||
</div>
|
||||
<Stack
|
||||
className="options"
|
||||
tokens={
|
||||
Object {
|
||||
"childrenGap": 10,
|
||||
}
|
||||
}
|
||||
>
|
||||
<Stack
|
||||
horizontal={true}
|
||||
horizontalAlign="space-between"
|
||||
tokens={
|
||||
Object {
|
||||
"childrenGap": 10,
|
||||
}
|
||||
}
|
||||
>
|
||||
<CustomizedDefaultButton
|
||||
onClick={[Function]}
|
||||
>
|
||||
Notebooks on localhost
|
||||
</CustomizedDefaultButton>
|
||||
<CustomizedDefaultButton
|
||||
onClick={[Function]}
|
||||
>
|
||||
Portal points to local DE
|
||||
</CustomizedDefaultButton>
|
||||
<CustomizedDefaultButton
|
||||
onClick={[Function]}
|
||||
>
|
||||
Reset
|
||||
</CustomizedDefaultButton>
|
||||
</Stack>
|
||||
<Stack
|
||||
horizontal={true}
|
||||
horizontalAlign="start"
|
||||
tokens={
|
||||
Object {
|
||||
"childrenGap": 10,
|
||||
}
|
||||
}
|
||||
>
|
||||
<StyledWithResponsiveMode
|
||||
label="Base Url"
|
||||
onChange={[Function]}
|
||||
options={
|
||||
Array [
|
||||
Object {
|
||||
"key": "https://localhost:1234/explorer.html",
|
||||
"text": "localhost:1234",
|
||||
},
|
||||
Object {
|
||||
"key": "https://cosmos.azure.com/explorer.html",
|
||||
"text": "cosmos.azure.com",
|
||||
},
|
||||
Object {
|
||||
"key": "https://portal.azure.com",
|
||||
"text": "portal",
|
||||
},
|
||||
]
|
||||
}
|
||||
selectedKey="https://localhost:1234/explorer.html"
|
||||
styles={
|
||||
Object {
|
||||
"dropdown": Object {
|
||||
"width": 200,
|
||||
},
|
||||
}
|
||||
}
|
||||
/>
|
||||
<StyledWithResponsiveMode
|
||||
label="Platform"
|
||||
onChange={[Function]}
|
||||
options={
|
||||
Array [
|
||||
Object {
|
||||
"key": "Hosted",
|
||||
"text": "Hosted",
|
||||
},
|
||||
Object {
|
||||
"key": "Portal",
|
||||
"text": "Portal",
|
||||
},
|
||||
Object {
|
||||
"key": "Emulator",
|
||||
"text": "Emulator",
|
||||
},
|
||||
Object {
|
||||
"key": "",
|
||||
"text": "None",
|
||||
},
|
||||
]
|
||||
}
|
||||
selectedKey="Hosted"
|
||||
styles={
|
||||
Object {
|
||||
"dropdown": Object {
|
||||
"width": 200,
|
||||
},
|
||||
}
|
||||
}
|
||||
/>
|
||||
</Stack>
|
||||
<Stack
|
||||
horizontal={true}
|
||||
>
|
||||
<Stack
|
||||
className="checkboxRow"
|
||||
horizontalAlign="space-between"
|
||||
>
|
||||
<StyledCheckboxBase
|
||||
checked={false}
|
||||
key="feature.enablechangefeedpolicy"
|
||||
label="Enable change feed policy"
|
||||
onChange={[Function]}
|
||||
/>
|
||||
<StyledCheckboxBase
|
||||
checked={false}
|
||||
key="feature.enablerupm"
|
||||
label="Enable RUPM"
|
||||
onChange={[Function]}
|
||||
/>
|
||||
<StyledCheckboxBase
|
||||
checked={false}
|
||||
key="feature.dataexplorerexecutesproc"
|
||||
label="Execute stored procedure"
|
||||
onChange={[Function]}
|
||||
/>
|
||||
<StyledCheckboxBase
|
||||
checked={false}
|
||||
key="feature.hosteddataexplorerenabled"
|
||||
label="Hosted Data Explorer (deprecated?)"
|
||||
onChange={[Function]}
|
||||
/>
|
||||
<StyledCheckboxBase
|
||||
checked={false}
|
||||
key="feature.enablettl"
|
||||
label="Enable TTL"
|
||||
onChange={[Function]}
|
||||
/>
|
||||
<StyledCheckboxBase
|
||||
checked={false}
|
||||
key="feature.enablegallery"
|
||||
label="Enable Notebook Gallery"
|
||||
onChange={[Function]}
|
||||
/>
|
||||
<StyledCheckboxBase
|
||||
checked={false}
|
||||
key="feature.canexceedmaximumvalue"
|
||||
label="Can exceed max value"
|
||||
onChange={[Function]}
|
||||
/>
|
||||
</Stack>
|
||||
<Stack
|
||||
className="checkboxRow"
|
||||
horizontalAlign="space-between"
|
||||
>
|
||||
<StyledCheckboxBase
|
||||
checked={false}
|
||||
key="feature.enablefixedcollectionwithsharedthroughput"
|
||||
label="Enable fixed collection with shared throughput"
|
||||
onChange={[Function]}
|
||||
/>
|
||||
<StyledCheckboxBase
|
||||
checked={false}
|
||||
key="feature.ttl90days"
|
||||
label="TTL 90 days"
|
||||
onChange={[Function]}
|
||||
/>
|
||||
<StyledCheckboxBase
|
||||
checked={false}
|
||||
key="feature.enablenotebooks"
|
||||
label="Enable notebooks"
|
||||
onChange={[Function]}
|
||||
/>
|
||||
<StyledCheckboxBase
|
||||
checked={false}
|
||||
disabled={true}
|
||||
key="feature.customportal"
|
||||
label="Force Production portal (portal only)"
|
||||
onChange={[Function]}
|
||||
/>
|
||||
<StyledCheckboxBase
|
||||
checked={false}
|
||||
key="feature.enablespark"
|
||||
label="Enable Synapse"
|
||||
onChange={[Function]}
|
||||
/>
|
||||
<StyledCheckboxBase
|
||||
checked={false}
|
||||
key="feature.enableautopilotv2"
|
||||
label="Enable Auto-pilot V2"
|
||||
onChange={[Function]}
|
||||
/>
|
||||
</Stack>
|
||||
</Stack>
|
||||
<Stack
|
||||
horizontal={true}
|
||||
tokens={
|
||||
Object {
|
||||
"childrenGap": 10,
|
||||
}
|
||||
}
|
||||
>
|
||||
<Stack
|
||||
horizontalAlign="space-between"
|
||||
>
|
||||
<StyledTextFieldBase
|
||||
key="feature.notebookserverurl"
|
||||
label="Notebook server URL"
|
||||
onChange={[Function]}
|
||||
placeholder="https://notebookserver"
|
||||
styles={
|
||||
Object {
|
||||
"fieldGroup": Object {
|
||||
"width": 300,
|
||||
},
|
||||
}
|
||||
}
|
||||
/>
|
||||
<StyledTextFieldBase
|
||||
key="feature.notebookservertoken"
|
||||
label="Notebook server token"
|
||||
onChange={[Function]}
|
||||
placeholder=""
|
||||
styles={
|
||||
Object {
|
||||
"fieldGroup": Object {
|
||||
"width": 300,
|
||||
},
|
||||
}
|
||||
}
|
||||
/>
|
||||
<StyledTextFieldBase
|
||||
key="feature.notebookbasepath"
|
||||
label="Notebook base path"
|
||||
onChange={[Function]}
|
||||
placeholder=""
|
||||
styles={
|
||||
Object {
|
||||
"fieldGroup": Object {
|
||||
"width": 300,
|
||||
},
|
||||
}
|
||||
}
|
||||
/>
|
||||
</Stack>
|
||||
<Stack
|
||||
horizontalAlign="space-between"
|
||||
>
|
||||
<StyledTextFieldBase
|
||||
key="key"
|
||||
label="Auth key"
|
||||
onChange={[Function]}
|
||||
placeholder=""
|
||||
styles={
|
||||
Object {
|
||||
"fieldGroup": Object {
|
||||
"width": 300,
|
||||
},
|
||||
}
|
||||
}
|
||||
/>
|
||||
<StyledTextFieldBase
|
||||
disabled={true}
|
||||
key="dataExplorerSource"
|
||||
label="Data Explorer Source (portal only)"
|
||||
onChange={[Function]}
|
||||
placeholder="https://localhost:1234/explorer.html"
|
||||
styles={
|
||||
Object {
|
||||
"fieldGroup": Object {
|
||||
"width": 300,
|
||||
},
|
||||
}
|
||||
}
|
||||
/>
|
||||
<StyledTextFieldBase
|
||||
key="feature.livyendpoint"
|
||||
label="Livy endpoint"
|
||||
onChange={[Function]}
|
||||
placeholder=""
|
||||
styles={
|
||||
Object {
|
||||
"fieldGroup": Object {
|
||||
"width": 300,
|
||||
},
|
||||
}
|
||||
}
|
||||
/>
|
||||
</Stack>
|
||||
</Stack>
|
||||
</Stack>
|
||||
</div>
|
||||
`;
|
|
@ -19,6 +19,7 @@
|
|||
}
|
||||
|
||||
>.title {
|
||||
position: relative; // To attach FeaturePanelLauncher as absolute
|
||||
color: @BaseHigh;
|
||||
font-size: 48px;
|
||||
padding-left: 0px;
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
import * as React from "react";
|
||||
import * as Constants from "../../Common/Constants";
|
||||
import { Link } from "office-ui-fabric-react/lib/Link";
|
||||
import { FeaturePanelLauncher } from "../Controls/FeaturePanel/FeaturePanelLauncher";
|
||||
|
||||
export interface SplashScreenItem {
|
||||
iconSrc: string;
|
||||
|
@ -29,7 +30,10 @@ export class SplashScreenComponent extends React.Component<SplashScreenComponent
|
|||
return (
|
||||
<div className="splashScreenContainer">
|
||||
<div className="splashScreen">
|
||||
<div className="title">Welcome to Cosmos DB</div>
|
||||
<div className="title">
|
||||
Welcome to Cosmos DB
|
||||
<FeaturePanelLauncher />
|
||||
</div>
|
||||
<div className="subtitle">Globally distributed, multi-model database service for any scale</div>
|
||||
<div className="mainButtonsContainer">
|
||||
{this.props.mainItems.map((item: SplashScreenItem) => (
|
||||
|
|
Loading…
Reference in New Issue