mirror of
https://github.com/Azure/cosmos-explorer.git
synced 2025-12-23 02:41:39 +00:00
Compare commits
1 Commits
dependabot
...
fix_a11y_c
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
877813b7f9 |
@@ -1,8 +1,16 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"
|
||||
<svg
|
||||
width="16"
|
||||
height="16"
|
||||
version="1.1"
|
||||
viewBox="0 0 16 16"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<path
|
||||
d="M14,2.691l-5.301,5.309l5.301,5.309l-0.691,0.691l-5.309,-5.301l-5.309,5.301l-0.691,-0.691l5.301,-5.309l-5.301,-5.309l0.691,-0.691l5.309,5.301l5.309,-5.301l0.691,0.691Z"
|
||||
transform="scale(0.5)" fill="#000" stroke="#000">
|
||||
<path
|
||||
d="M14,2.691l-5.301,5.309l5.301,5.309l-0.691,0.691l-5.309,-5.301l-5.309,5.301l-0.691,-0.691l5.301,-5.309l-5.301,-5.309l0.691,-0.691l5.309,5.301l5.309,-5.301l0.691,0.691Z"
|
||||
transform="scale(0.5)"
|
||||
fill="#000"
|
||||
stroke="#CCC"
|
||||
>
|
||||
</path>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 449 B After Width: | Height: | Size: 503 B |
@@ -2832,8 +2832,6 @@ a:link {
|
||||
|
||||
#explorerNotificationConsole {
|
||||
z-index: 1000;
|
||||
overflow-y:auto;
|
||||
overflow-x: clip;
|
||||
}
|
||||
|
||||
.uniqueIndexesContainer {
|
||||
|
||||
6
package-lock.json
generated
6
package-lock.json
generated
@@ -19065,9 +19065,9 @@
|
||||
}
|
||||
},
|
||||
"nth-check": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.0.1.tgz",
|
||||
"integrity": "sha512-it1vE95zF6dTT9lBsYbxvqh0Soy4SPowchj0UBGj/V6cTPnXXtQOPUbhZ6CmGzAD/rW22LQK6E96pcdJXk4A4w==",
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.0.0.tgz",
|
||||
"integrity": "sha512-i4sc/Kj8htBrAiH1viZ0TgU8Y5XqCaV/FziYK6TBczxmeKm3AEFWqqF3195yKudrarqy7Zu80Ra5dobFjn9X/Q==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"boolbase": "^1.0.0"
|
||||
|
||||
@@ -65,7 +65,7 @@ export interface PriceBreakdown {
|
||||
currencySign: string;
|
||||
}
|
||||
|
||||
export const infoAndToolTipTextStyle: ITextStyles = { root: { fontSize: 14, color: "windowtext" } };
|
||||
export const infoAndToolTipTextStyle: ITextStyles = { root: { fontSize: 14 } };
|
||||
|
||||
export const noLeftPaddingCheckBoxStyle: ICheckboxStyles = {
|
||||
label: {
|
||||
|
||||
@@ -243,7 +243,6 @@ export class TreeNodeComponent extends React.Component<TreeNodeComponentProps, T
|
||||
<div ref={this.contextMenuRef} onContextMenu={this.onRightClick} onKeyPress={this.onMoreButtonKeyPress}>
|
||||
<IconButton
|
||||
name="More"
|
||||
title="More"
|
||||
className="treeMenuEllipsis"
|
||||
ariaLabel={menuItemLabel}
|
||||
menuIconProps={{
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import * as React from "react";
|
||||
import { GraphVizComponent, GraphVizComponentProps } from "./GraphVizComponent";
|
||||
import CollapseArrowIcon from "../../../../images/Collapse_arrow_14x14.svg";
|
||||
import ExpandIcon from "../../../../images/Expand_14x14.svg";
|
||||
import LoadingIndicatorIcon from "../../../../images/LoadingIndicator_3Squares.gif";
|
||||
import { GraphVizComponent, GraphVizComponentProps } from "./GraphVizComponent";
|
||||
|
||||
interface MiddlePaneComponentProps {
|
||||
isTabsContentExpanded: boolean;
|
||||
@@ -17,13 +17,7 @@ export class MiddlePaneComponent extends React.Component<MiddlePaneComponentProp
|
||||
<div className="middlePane">
|
||||
<div className="graphTitle">
|
||||
<span className="paneTitle">Graph</span>
|
||||
<span
|
||||
className="graphExpandCollapseBtn pull-right"
|
||||
onClick={this.props.toggleExpandGraph}
|
||||
role="button"
|
||||
aria-expanded={this.props.isTabsContentExpanded}
|
||||
aria-name="View graph in full screen"
|
||||
>
|
||||
<span className="graphExpandCollapseBtn pull-right" onClick={this.props.toggleExpandGraph}>
|
||||
<img
|
||||
src={this.props.isTabsContentExpanded ? CollapseArrowIcon : ExpandIcon}
|
||||
alt={this.props.isTabsContentExpanded ? "collapse graph content" : "expand graph content"}
|
||||
|
||||
@@ -129,7 +129,7 @@ export class NotificationConsoleComponent extends React.Component<
|
||||
className="expandCollapseButton"
|
||||
role="button"
|
||||
tabIndex={0}
|
||||
aria-label={"console button" + (this.props.isConsoleExpanded ? " expanded" : " collapsed")}
|
||||
aria-label={"console button" + (this.props.isConsoleExpanded ? " collapsed" : " expanded")}
|
||||
aria-expanded={!this.props.isConsoleExpanded}
|
||||
>
|
||||
<img
|
||||
@@ -205,9 +205,7 @@ export class NotificationConsoleComponent extends React.Component<
|
||||
{item.type === ConsoleDataType.Error && <img className="errorIcon" src={ErrorRedIcon} alt="error" />}
|
||||
{item.type === ConsoleDataType.InProgress && <img className="loaderIcon" src={LoaderIcon} alt="in progress" />}
|
||||
<span className="date">{item.date}</span>
|
||||
<span className="message" role="alert" aria-live="assertive">
|
||||
{item.message}
|
||||
</span>
|
||||
<span className="message">{item.message}</span>
|
||||
</div>
|
||||
));
|
||||
}
|
||||
|
||||
@@ -70,7 +70,7 @@ exports[`NotificationConsoleComponent renders the console 1`] = `
|
||||
</div>
|
||||
<div
|
||||
aria-expanded={true}
|
||||
aria-label="console button collapsed"
|
||||
aria-label="console button expanded"
|
||||
className="expandCollapseButton"
|
||||
role="button"
|
||||
tabIndex={0}
|
||||
@@ -236,7 +236,7 @@ exports[`NotificationConsoleComponent renders the console 2`] = `
|
||||
</div>
|
||||
<div
|
||||
aria-expanded={true}
|
||||
aria-label="console button collapsed"
|
||||
aria-label="console button expanded"
|
||||
className="expandCollapseButton"
|
||||
role="button"
|
||||
tabIndex={0}
|
||||
@@ -340,9 +340,7 @@ exports[`NotificationConsoleComponent renders the console 2`] = `
|
||||
date
|
||||
</span>
|
||||
<span
|
||||
aria-live="assertive"
|
||||
className="message"
|
||||
role="alert"
|
||||
>
|
||||
message
|
||||
</span>
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
import {
|
||||
ActionButton,
|
||||
Checkbox,
|
||||
ChoiceGroup,
|
||||
DefaultButton,
|
||||
DirectionalHint,
|
||||
Dropdown,
|
||||
IChoiceGroupOption,
|
||||
Icon,
|
||||
IconButton,
|
||||
IDropdownOption,
|
||||
@@ -125,6 +127,26 @@ export class AddCollectionPanel extends React.Component<AddCollectionPanelProps,
|
||||
};
|
||||
}
|
||||
|
||||
choiceButtonStyles = {
|
||||
flexContainer: [
|
||||
{
|
||||
selectors: {
|
||||
".ms-ChoiceField-wrapper label": {
|
||||
fontSize: 12,
|
||||
paddingTop: 0,
|
||||
},
|
||||
".ms-ChoiceField": {
|
||||
marginTop: 0,
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
};
|
||||
collectionOptions: IChoiceGroupOption[] = [
|
||||
{ key: "create", text: "Create new database" },
|
||||
{ key: "existing", text: "Use existing database" },
|
||||
];
|
||||
|
||||
render(): JSX.Element {
|
||||
const isFirstResourceCreated = useDatabases.getState().isFirstResourceCreated();
|
||||
|
||||
@@ -152,7 +174,7 @@ export class AddCollectionPanel extends React.Component<AddCollectionPanelProps,
|
||||
<Stack hidden={userContext.apiType === "Tables"}>
|
||||
<Stack horizontal>
|
||||
<span className="mandatoryStar">* </span>
|
||||
<Text className="panelTextBold" variant="small">
|
||||
<Text id="databaseId" className="panelTextBold" variant="small">
|
||||
Database {userContext.apiType === "Mongo" ? "name" : "id"}
|
||||
</Text>
|
||||
<TooltipHost
|
||||
@@ -166,32 +188,15 @@ export class AddCollectionPanel extends React.Component<AddCollectionPanelProps,
|
||||
</Stack>
|
||||
|
||||
<Stack horizontal verticalAlign="center">
|
||||
<input
|
||||
className="panelRadioBtn"
|
||||
checked={this.state.createNewDatabase}
|
||||
aria-label="Create new database"
|
||||
aria-checked={this.state.createNewDatabase}
|
||||
name="databaseType"
|
||||
type="radio"
|
||||
role="radio"
|
||||
id="databaseCreateNew"
|
||||
tabIndex={0}
|
||||
onChange={this.onCreateNewDatabaseRadioBtnChange.bind(this)}
|
||||
<ChoiceGroup
|
||||
aria-labelledby="databaseId"
|
||||
styles={this.choiceButtonStyles}
|
||||
options={this.collectionOptions}
|
||||
defaultSelectedKey={this.collectionOptions[0].key}
|
||||
onChange={(_: React.ChangeEvent<HTMLInputElement>, options: IChoiceGroupOption) =>
|
||||
this.handleOnChangeMode(_, options.key.toString())
|
||||
}
|
||||
/>
|
||||
<span className="panelRadioBtnLabel">Create new</span>
|
||||
|
||||
<input
|
||||
className="panelRadioBtn"
|
||||
checked={!this.state.createNewDatabase}
|
||||
aria-label="Use existing database"
|
||||
aria-checked={!this.state.createNewDatabase}
|
||||
name="databaseType"
|
||||
type="radio"
|
||||
role="radio"
|
||||
tabIndex={0}
|
||||
onChange={this.onUseExistingDatabaseRadioBtnChange.bind(this)}
|
||||
/>
|
||||
<span className="panelRadioBtnLabel">Use existing</span>
|
||||
</Stack>
|
||||
|
||||
{this.state.createNewDatabase && (
|
||||
@@ -209,7 +214,6 @@ export class AddCollectionPanel extends React.Component<AddCollectionPanelProps,
|
||||
size={40}
|
||||
className="panelTextField"
|
||||
aria-label="New database id"
|
||||
autoFocus
|
||||
tabIndex={0}
|
||||
value={this.state.newDatabaseId}
|
||||
onChange={(event: React.ChangeEvent<HTMLInputElement>) =>
|
||||
@@ -707,6 +711,14 @@ export class AddCollectionPanel extends React.Component<AddCollectionPanelProps,
|
||||
}
|
||||
}
|
||||
|
||||
private handleOnChangeMode = (event: React.ChangeEvent<HTMLInputElement>, mode: string): void => {
|
||||
if (mode === "create") {
|
||||
this.onCreateNewDatabaseRadioBtnChange(event);
|
||||
} else {
|
||||
this.onUseExistingDatabaseRadioBtnChange(event);
|
||||
}
|
||||
};
|
||||
|
||||
private onCreateNewDatabaseRadioBtnChange(event: React.ChangeEvent<HTMLInputElement>): void {
|
||||
if (event.target.checked && !this.state.createNewDatabase) {
|
||||
this.setState({
|
||||
|
||||
@@ -198,7 +198,6 @@ export const CassandraAddCollectionPane: FunctionComponent<CassandraAddCollectio
|
||||
<Stack className="panelGroupSpacing">
|
||||
<TextField
|
||||
aria-required="true"
|
||||
required={true}
|
||||
autoComplete="off"
|
||||
styles={getTextFieldStyles()}
|
||||
pattern="[^/?#\\]*[^/?# \\]"
|
||||
@@ -286,7 +285,6 @@ export const CassandraAddCollectionPane: FunctionComponent<CassandraAddCollectio
|
||||
underlined
|
||||
styles={getTextFieldStyles({ fontSize: 12, width: 150 })}
|
||||
aria-required="true"
|
||||
required={true}
|
||||
ariaLabel="addCollection-tableId"
|
||||
autoComplete="off"
|
||||
pattern="[^/?#\\]*[^/?# \\]"
|
||||
|
||||
@@ -9,7 +9,6 @@
|
||||
flex-grow: 1;
|
||||
padding: 0 34px;
|
||||
margin: 20px 0;
|
||||
overflow-x: hidden;
|
||||
|
||||
& > :not(.collapsibleSection) {
|
||||
margin-bottom: @DefaultSpace;
|
||||
|
||||
@@ -33,13 +33,7 @@ export const PanelInfoErrorComponent: React.FunctionComponent<PanelInfoErrorProp
|
||||
<Stack className="panelInfoErrorContainer" horizontal verticalAlign="center">
|
||||
{icon}
|
||||
<span className="panelWarningErrorDetailsLinkContainer">
|
||||
<Text
|
||||
role="alert"
|
||||
aria-live="assertive"
|
||||
aria-label={message}
|
||||
className="panelWarningErrorMessage"
|
||||
variant="small"
|
||||
>
|
||||
<Text className="panelWarningErrorMessage" variant="small" aria-label="message">
|
||||
{message}
|
||||
{link && linkText && (
|
||||
<Link target="_blank" href={link}>
|
||||
|
||||
@@ -34,6 +34,6 @@ describe("Right Pane Form", () => {
|
||||
it("should render error in header", () => {
|
||||
render(<RightPaneForm {...props} formError="file already Exist" />);
|
||||
expect(screen.getByLabelText("error")).toBeDefined();
|
||||
expect(screen.getByRole("alert").innerHTML).toEqual("file already Exist");
|
||||
expect(screen.getByLabelText("message").innerHTML).toEqual("file already Exist");
|
||||
});
|
||||
});
|
||||
|
||||
@@ -327,17 +327,13 @@ exports[`Delete Database Confirmation Pane Should call delete database 1`] = `
|
||||
key=".0:$.1"
|
||||
>
|
||||
<Text
|
||||
aria-label="Warning! The action you are about to take cannot be undone. Continuing will permanently delete this resource and all of its children resources."
|
||||
aria-live="assertive"
|
||||
aria-label="message"
|
||||
className="panelWarningErrorMessage"
|
||||
role="alert"
|
||||
variant="small"
|
||||
>
|
||||
<span
|
||||
aria-label="Warning! The action you are about to take cannot be undone. Continuing will permanently delete this resource and all of its children resources."
|
||||
aria-live="assertive"
|
||||
aria-label="message"
|
||||
className="panelWarningErrorMessage css-56"
|
||||
role="alert"
|
||||
>
|
||||
Warning! The action you are about to take cannot be undone. Continuing will permanently delete this resource and all of its children resources.
|
||||
</span>
|
||||
|
||||
@@ -47,9 +47,7 @@
|
||||
<img class="and-or-svg" src="/And-Or.svg" alt="Group selected clauses" />
|
||||
</button>
|
||||
</th>
|
||||
<th class="clause-table-cell header-background">
|
||||
<!-- Grouping indicator -->
|
||||
</th>
|
||||
<th class="clause-table-cell header-background"><!-- Grouping indicator --></th>
|
||||
<th class="clause-table-cell header-background and-or-header">
|
||||
<span data-bind="text: andLabel"></span>
|
||||
</th>
|
||||
@@ -138,7 +136,7 @@
|
||||
class="select-options-link"
|
||||
data-bind="click: selectQueryOptions, event: { keydown: onselectQueryOptionsKeyDown }"
|
||||
tabindex="0"
|
||||
role="button"
|
||||
role="link"
|
||||
>
|
||||
<span>Choose Columns... </span>
|
||||
</a>
|
||||
|
||||
@@ -85,7 +85,7 @@ export function extractFeatures(given = new URLSearchParams(window.location.sear
|
||||
};
|
||||
}
|
||||
|
||||
export function hasFlag(flags: string | undefined, desiredFlag: string | undefined): boolean {
|
||||
export function hasFlag(flags: string, desiredFlag: string): boolean {
|
||||
if (!flags || !desiredFlag) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -151,10 +151,10 @@ export const getReadRegions = async (): Promise<Array<string>> => {
|
||||
});
|
||||
|
||||
if (response.result.location !== undefined) {
|
||||
readRegions.push(response.result.location.split(" ").join("").toLowerCase());
|
||||
readRegions.push(response.result.location.replace(" ", "").toLowerCase());
|
||||
} else {
|
||||
for (const location of response.result.locations) {
|
||||
readRegions.push(location.locationName.split(" ").join("").toLowerCase());
|
||||
readRegions.push(location.locationName.replace(" ", "").toLowerCase());
|
||||
}
|
||||
}
|
||||
return readRegions;
|
||||
|
||||
@@ -139,14 +139,6 @@ const getGeneralPath = (subscriptionId: string, resourceGroup: string, name: str
|
||||
};
|
||||
|
||||
export const getRegions = async (): Promise<Array<string>> => {
|
||||
const telemetryData = {
|
||||
feature: "Calculate approximate cost",
|
||||
function: "getRegions",
|
||||
description: "",
|
||||
selfServeClassName: SqlX.name,
|
||||
};
|
||||
const getRegionsTimestamp = selfServeTraceStart(telemetryData);
|
||||
|
||||
try {
|
||||
const regions = new Array<string>();
|
||||
|
||||
@@ -164,12 +156,8 @@ export const getRegions = async (): Promise<Array<string>> => {
|
||||
regions.push(location.locationName.split(" ").join("").toLowerCase());
|
||||
}
|
||||
}
|
||||
|
||||
selfServeTraceSuccess(telemetryData, getRegionsTimestamp);
|
||||
return regions;
|
||||
} catch (err) {
|
||||
const failureTelemetry = { err, selfServeClassName: SqlX.name };
|
||||
selfServeTraceFailure(failureTelemetry, getRegionsTimestamp);
|
||||
return new Array<string>();
|
||||
}
|
||||
};
|
||||
@@ -179,14 +167,6 @@ const getFetchPricesPathForRegion = (subscriptionId: string): string => {
|
||||
};
|
||||
|
||||
export const getPriceMap = async (regions: Array<string>): Promise<Map<string, Map<string, number>>> => {
|
||||
const telemetryData = {
|
||||
feature: "Calculate approximate cost",
|
||||
function: "getPriceMap",
|
||||
description: "fetch prices API call",
|
||||
selfServeClassName: SqlX.name,
|
||||
};
|
||||
const getPriceMapTimestamp = selfServeTraceStart(telemetryData);
|
||||
|
||||
try {
|
||||
const priceMap = new Map<string, Map<string, number>>();
|
||||
|
||||
@@ -212,12 +192,8 @@ export const getPriceMap = async (regions: Array<string>): Promise<Map<string, M
|
||||
priceMap.set(region, regionPriceMap);
|
||||
}
|
||||
|
||||
selfServeTraceSuccess(telemetryData, getPriceMapTimestamp);
|
||||
return priceMap;
|
||||
} catch (err) {
|
||||
const failureTelemetry = { err, selfServeClassName: SqlX.name };
|
||||
selfServeTraceFailure(failureTelemetry, getPriceMapTimestamp);
|
||||
|
||||
return undefined;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1,10 +1,5 @@
|
||||
import { IsDisplayable, OnChange, PropertyInfo, RefreshOptions, Values } from "../Decorators";
|
||||
import {
|
||||
selfServeTrace,
|
||||
selfServeTraceFailure,
|
||||
selfServeTraceStart,
|
||||
selfServeTraceSuccess,
|
||||
} from "../SelfServeTelemetryProcessor";
|
||||
import { selfServeTrace } from "../SelfServeTelemetryProcessor";
|
||||
import {
|
||||
ChoiceItem,
|
||||
Description,
|
||||
@@ -210,14 +205,6 @@ let priceMap: Map<string, Map<string, number>>;
|
||||
let regions: Array<string>;
|
||||
|
||||
const calculateCost = (skuName: string, instanceCount: number): Description => {
|
||||
const telemetryData = {
|
||||
feature: "Calculate approximate cost",
|
||||
function: "calculateCost",
|
||||
description: "performs final calculation",
|
||||
selfServeClassName: SqlX.name,
|
||||
};
|
||||
const calculateCostTimestamp = selfServeTraceStart(telemetryData);
|
||||
|
||||
try {
|
||||
let costPerHour = 0;
|
||||
for (const region of regions) {
|
||||
@@ -228,22 +215,14 @@ const calculateCost = (skuName: string, instanceCount: number): Description => {
|
||||
costPerHour += incrementalCost;
|
||||
}
|
||||
|
||||
if (costPerHour === 0) {
|
||||
throw new Error("Cost per hour = 0");
|
||||
}
|
||||
|
||||
costPerHour *= instanceCount;
|
||||
costPerHour = Math.round(costPerHour * 100) / 100;
|
||||
|
||||
selfServeTraceSuccess(telemetryData, calculateCostTimestamp);
|
||||
return {
|
||||
textTKey: `${costPerHour} USD`,
|
||||
type: DescriptionType.Text,
|
||||
};
|
||||
} catch (err) {
|
||||
const failureTelemetry = { err, regions, priceMap, selfServeClassName: SqlX.name };
|
||||
selfServeTraceFailure(failureTelemetry, calculateCostTimestamp);
|
||||
|
||||
return costPerHourDefaultValue;
|
||||
}
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user