Implemented keydown events

This commit is contained in:
vaidankarswapnil 2021-08-10 18:22:34 +05:30
parent e1d32bde36
commit d70dd6bc7e
7 changed files with 136 additions and 110 deletions

View File

@ -95,7 +95,6 @@ export const TableEntity: FunctionComponent<TableEntityProps> = ({
<Stack horizontal tokens={sectionStackTokens}>
<TextField
label={entityPropertyLabel && entityPropertyLabel}
id="entityPropertyId"
autoFocus
disabled={isPropertyTypeDisable}
placeholder={entityPropertyPlaceHolder}
@ -109,7 +108,6 @@ export const TableEntity: FunctionComponent<TableEntityProps> = ({
onChange={onEntityTypeChange}
options={options}
disabled={isPropertyTypeDisable}
id="entityTypeId"
styles={dropdownStyles}
/>
<EntityValue
@ -126,12 +124,12 @@ export const TableEntity: FunctionComponent<TableEntityProps> = ({
/>
{!isEntityValueDisable && (
<TooltipHost content="Edit property" id="editTooltip">
<Image {...imageProps} src={EditIcon} alt="editEntity" id="editEntity" onClick={onEditEntity} />
<Image {...imageProps} src={EditIcon} alt="editEntity" onClick={onEditEntity} />
</TooltipHost>
)}
{isDeleteOptionVisible && userContext.apiType !== "Cassandra" && (
<TooltipHost content="Delete property" id="deleteTooltip">
<Image {...imageProps} src={DeleteIcon} alt="delete entity" id="deleteEntity" onClick={onDeleteEntity} />
<Image {...imageProps} src={DeleteIcon} alt="delete entity" onClick={onDeleteEntity} />
</TooltipHost>
)}
</Stack>

View File

@ -1,7 +1,6 @@
import { IDropdownOption, Image, IPanelProps, IRenderFunction, Label, Stack, Text, TextField } from "@fluentui/react";
import { useBoolean } from "@fluentui/react-hooks";
import React, { FunctionComponent, useEffect, useState } from "react";
import * as _ from "underscore";
import AddPropertyIcon from "../../../../images/Add-property.svg";
import RevertBackIcon from "../../../../images/RevertBack.svg";
import { TableEntity } from "../../../Common/TableEntity";
@ -12,7 +11,6 @@ import * as DataTableUtilities from "../../Tables/DataTable/DataTableUtilities";
import TableEntityListViewModel from "../../Tables/DataTable/TableEntityListViewModel";
import * as Entities from "../../Tables/Entities";
import { CassandraAPIDataClient, CassandraTableKey, TableDataClient } from "../../Tables/TableDataClient";
import * as TableEntityProcessor from "../../Tables/TableEntityProcessor";
import * as Utilities from "../../Tables/Utilities";
import NewQueryTablesTab from "../../Tabs/QueryTablesTab/QueryTablesTab";
// import QueryTablesTab from "../../Tabs/QueryTablesTab";
@ -110,42 +108,11 @@ export const AddTableEntityPanel: FunctionComponent<AddTableEntityPanelProps> =
const entity: Entities.ITableEntity = entityFromAttributes(entities);
const newEntity: Entities.ITableEntity = await tableDataClient.createDocument(queryTablesTab.collection, entity);
await tableEntityListViewModel.addEntityToCache(newEntity);
if (!tryInsertNewHeaders(tableEntityListViewModel, newEntity)) {
// tableEntityListViewModel.redrawTableThrottled();
reloadEntities();
}
// await tableEntityListViewModel.addEntityToCache(newEntity);
reloadEntities();
closeSidePanel();
};
const tryInsertNewHeaders = (viewModel: TableEntityListViewModel, newEntity: Entities.ITableEntity): boolean => {
let newHeaders: string[] = [];
const keys = Object.keys(newEntity);
keys &&
keys.forEach((key: string) => {
if (
!_.contains(viewModel.headers, key) &&
key !== TableEntityProcessor.keyProperties.attachments &&
key !== TableEntityProcessor.keyProperties.etag &&
key !== TableEntityProcessor.keyProperties.resourceId &&
key !== TableEntityProcessor.keyProperties.self &&
(!(userContext.apiType === "Cassandra") || key !== TableConstants.EntityKeyNames.RowKey)
) {
newHeaders.push(key);
}
});
let newHeadersInserted = false;
if (newHeaders.length) {
if (!DataTableUtilities.checkForDefaultHeader(viewModel.headers)) {
newHeaders = viewModel.headers.concat(newHeaders);
}
viewModel.updateHeaders(newHeaders, /* notifyColumnChanges */ true, /* enablePrompt */ false);
newHeadersInserted = true;
}
return newHeadersInserted;
};
/* Add new entity row */
const addNewEntity = (): void => {
const cloneEntities: EntityRowType[] = [...entities];

View File

@ -24,7 +24,6 @@ abstract class DataTableViewModel {
/* Observables */
public items = ko.observableArray<Entities.ITableEntity>();
public items1: Entities.ITableEntity[];
public selected = ko.observableArray<Entities.ITableEntity>();
public table: DataTables.DataTable;
@ -53,7 +52,6 @@ abstract class DataTableViewModel {
constructor() {
this.items([]);
this.items1 = [];
this.selected([]);
// Late bound
this.dataTableOperationManager = null;
@ -176,7 +174,6 @@ abstract class DataTableViewModel {
var renderData = this.cache.data.slice(startIndex, endIndex);
this.items(renderData);
this.items1 = renderData;
if (this.queryTablesTab.onLoadStartKey != null && this.queryTablesTab.onLoadStartKey != undefined) {
TelemetryProcessor.traceSuccess(

View File

@ -155,11 +155,10 @@ export default class TableEntityListViewModel extends DataTableViewModel {
* fnCallback - is the render callback with data to render.
* oSetting: current settings used for table initialization.
*/
public renderNextPageAndupdateCache(sSource?: any, aoData?: any, fnCallback?: any, oSettings?: any): Promise<void> {
var tablePageSize: number;
var draw: number;
public renderNextPageAndupdateCache(sSource?: any, aoData?: any, fnCallback?: any): Promise<void> {
var tablePageSize: number = 100;
var prefetchNeeded = true;
var columnSortOrder: any;
// var columnSortOrder: any;
// Threshold(pages) for triggering cache prefetch.
// If number remaining pages in cache falls below prefetchThreshold prefetch will be triggered.
var prefetchThreshold = 10;
@ -170,11 +169,12 @@ export default class TableEntityListViewModel extends DataTableViewModel {
// Check if prefetch needed.
if (this.tablePageStartIndex + tablePageSize <= this.cache.length || this.allDownloaded) {
prefetchNeeded = false;
if (columnSortOrder && (!this.cache.sortOrder || !_.isEqual(this.cache.sortOrder, columnSortOrder))) {
this.sortColumns(columnSortOrder, oSettings);
}
// this.renderPage(this.tablePageStartIndex, tablePageSize);
this.renderPage(0, 100);
// if (columnSortOrder && (!this.cache.sortOrder || !_.isEqual(this.cache.sortOrder, columnSortOrder))) {
// this.sortColumns(columnSortOrder, oSettings);
// }
this.tablePageStartIndex = 0;
this.renderPage(this.tablePageStartIndex, tablePageSize);
// this.renderPage(0, 100);
if (
!this.allDownloaded &&
this.tablePageStartIndex > 0 && // This is a case now that we can hit this as we re-construct table when we update column
@ -195,10 +195,10 @@ export default class TableEntityListViewModel extends DataTableViewModel {
tableQuery,
this.tablePageStartIndex,
tablePageSize,
downloadSize,
draw,
oSettings,
columnSortOrder
downloadSize
// draw,
// oSettings,
// columnSortOrder
);
}
return undefined;
@ -358,11 +358,12 @@ export default class TableEntityListViewModel extends DataTableViewModel {
tableQuery: Entities.ITableQuery,
tablePageStartIndex: number,
tablePageSize: number,
downloadSize: number,
draw: number,
oSettings: any,
columnSortOrder: any
downloadSize: number
// draw: number,/
// oSettings: any,
// columnSortOrder: any
): void {
console.log("🚀 ~ file: TableEntityListViewModel.ts ~ line 366 ~ TableEntityListViewModel ~ prefetchAndRender");
this.queryErrorMessage(null);
if (this.cache.serverCallInProgress) {
return;
@ -452,6 +453,7 @@ export default class TableEntityListViewModel extends DataTableViewModel {
downloadSize: number,
currentRetry: number = 0
): Q.Promise<any> {
console.log("🚀 ~ file: TableEntityListViewModel.ts ~ line 456 ~ TableEntityListViewModel ~ prefetchData");
if (!this.cache.serverCallInProgress) {
this.cache.serverCallInProgress = true;
this.allDownloaded = false;

View File

@ -474,7 +474,7 @@ export default class QueryBuilderViewModel {
return true;
};
public onAddNewClauseKeyDown = (source: any, event: KeyboardEvent): boolean => {
public onAddNewClauseKeyDown = (event: React.KeyboardEvent<HTMLDivElement>): boolean => {
if (event.keyCode === KeyCodes.Enter || event.keyCode === KeyCodes.Space) {
this.addClauseIndex(this.clauseArray().length - 1, null);
event.stopPropagation();

View File

@ -38,6 +38,8 @@ export interface IQueryTableEntityClauseProps {
onQueryTableEntityCheck: (ev?: React.FormEvent<HTMLElement | HTMLInputElement>, checked?: boolean) => void;
onDropdownChange: (selectedOption: IDropdownOption, selectedOptionType: string) => void;
onEntityValueChange: (event: React.FormEvent<HTMLElement>, newInput?: string) => void;
onAddNewClauseKeyDown?: (ev: React.KeyboardEvent<HTMLImageElement>) => void;
onDeleteCaluseKeyDown?: (ev: React.KeyboardEvent<HTMLImageElement>) => void;
}
export const QueryTableEntityClause: FunctionComponent<IQueryTableEntityClauseProps> = ({
@ -61,6 +63,8 @@ export const QueryTableEntityClause: FunctionComponent<IQueryTableEntityClausePr
onDeleteClause,
onDropdownChange,
onEntityValueChange,
onAddNewClauseKeyDown,
onDeleteCaluseKeyDown,
}: IQueryTableEntityClauseProps): JSX.Element => {
const cancelImageProps: IImageProps = {
width: 14,
@ -87,7 +91,15 @@ export const QueryTableEntityClause: FunctionComponent<IQueryTableEntityClausePr
<>
<Stack horizontal tokens={sectionStackTokens}>
<TooltipHost content="Add new clause" id="addNewClause">
<Image {...addImageProps} src={AddIcon} alt="Add new clause" id="addNewClause" onClick={onAddNewClause} />
<Image
{...addImageProps}
src={AddIcon}
alt="Add new clause"
id="addNewClause"
onClick={onAddNewClause}
onKeyDown={onAddNewClauseKeyDown}
tabIndex={0}
/>
</TooltipHost>
<TooltipHost content="Delete clause" id="deleteClause">
<Image
@ -96,6 +108,8 @@ export const QueryTableEntityClause: FunctionComponent<IQueryTableEntityClausePr
alt="delete clause"
id="deleteClause"
onClick={onDeleteClause}
onKeyDown={onDeleteCaluseKeyDown}
tabIndex={0}
/>
</TooltipHost>
<Checkbox checked={isQueryTableEntityChecked} onChange={onQueryTableEntityCheck} />
@ -106,7 +120,7 @@ export const QueryTableEntityClause: FunctionComponent<IQueryTableEntityClausePr
onDropdownChange(selectedOption, "selectedOperation")
}
options={operationOptions}
id="operatorOptionId"
// id="operatorOptionId"
styles={dropdownStyles}
/>
<Dropdown
@ -115,7 +129,7 @@ export const QueryTableEntityClause: FunctionComponent<IQueryTableEntityClausePr
onDropdownChange(selectedOption, "selectedField")
}
options={fieldOptions}
id="fieldOptionId"
// id="fieldOptionId"
styles={dropdownStyles}
/>
<Dropdown
@ -124,7 +138,7 @@ export const QueryTableEntityClause: FunctionComponent<IQueryTableEntityClausePr
onDropdownChange(selectedOption, "selectedEntityType")
}
options={entityTypeOptions}
id="entityOptionId"
// id="entityOptionId"
disabled={validateEntityTypeOption()}
styles={dropdownStyles}
/>
@ -134,7 +148,7 @@ export const QueryTableEntityClause: FunctionComponent<IQueryTableEntityClausePr
onDropdownChange(selectedOption, "selectedOperator")
}
options={operatorOptions}
id="operatorOptionId"
// id="operatorOptionId"
styles={dropdownStyles}
/>
{isTimeStampSelected ? (
@ -144,7 +158,7 @@ export const QueryTableEntityClause: FunctionComponent<IQueryTableEntityClausePr
onDropdownChange(selectedOption, "selectedTimestamp")
}
options={timestampOptions}
id="operatorOptionId"
// id="operatorOptionId"
styles={dropdownStyles}
/>
) : (

View File

@ -28,6 +28,7 @@ import QueryTextIcon from "../../../../images/Query-Text.svg";
import StatusWraning from "../../../../images/QueryBuilder/StatusWarning_16x.png";
import TriangleDown from "../../../../images/Triangle-down.svg";
import TriangleRight from "../../../../images/Triangle-right.svg";
import { NormalizedEventKey } from "../../../Common/Constants";
import { queryDocuments } from "../../../Common/dataAccess/queryDocuments";
import { handleError } from "../../../Common/ErrorHandlingUtils";
import * as HeadersUtility from "../../../Common/HeadersUtility";
@ -97,12 +98,12 @@ class QueryTablesTabComponent extends Component<IQueryTablesTabComponentProps, I
this.tableDataClient = this.container.tableDataClient;
this.tableEntityListViewModel2(new TableEntityListViewModel(this.tableCommands, props.queryTablesTab));
const tableEntityListViewModel = new TableEntityListViewModel(this.tableCommands, props.queryTablesTab);
const queryBuilderViewModel = new QueryViewModel(this.props.queryTablesTab).queryBuilderViewModel();
// const queryBuilderViewModel = new QueryViewModel(this.props.queryTablesTab).queryBuilderViewModel();
const entityTypeOptions = queryBuilderViewModel.edmTypes();
const timestampOptions = queryBuilderViewModel.timeOptions();
const operatorsOptions = queryBuilderViewModel.operators();
const operationOptions = queryBuilderViewModel.clauseRules();
// const entityTypeOptions = queryBuilderViewModel.edmTypes();
// const timestampOptions = queryBuilderViewModel.timeOptions();
// const operatorsOptions = queryBuilderViewModel.operators();
// const operationOptions = queryBuilderViewModel.clauseRules();
this.state = {
tableEntityListViewModel,
@ -161,31 +162,32 @@ class QueryTablesTabComponent extends Component<IQueryTablesTabComponentProps, I
selection: this.createSelection(),
entities: [],
headers: [],
queryTableRows: [
{
isQueryTableEntityChecked: false,
selectedOperator: "=",
id: "1",
selectedField: userContext.apiType === "Cassandra" ? "email" : "PartitionKey",
selectedOperation: "",
entityValue: "",
selectedEntityType: "String",
isTimeStampSelected: false,
selectedTimestamp: "Last hour",
operatorOptions: getformattedOptions(operatorsOptions),
fieldOptions: getformattedOptions(tableEntityListViewModel.headers),
entityTypeOptions: getformattedOptions(entityTypeOptions),
operationOptions: getformattedOptions(operationOptions),
timestampOptions: getformattedOptions(timestampOptions),
clauseGroup: queryBuilderViewModel.queryClauses,
isValue: true,
isLocal: false,
isTimestamp: false,
isCustomRangeTimestamp: false,
customTimeValue: "",
timeValue: "",
},
],
queryTableRows: [],
// queryTableRows: [
// {
// isQueryTableEntityChecked: false,
// selectedOperator: "=",
// id: "1",
// selectedField: userContext.apiType === "Cassandra" ? "email" : "PartitionKey",
// selectedOperation: "",
// entityValue: "",
// selectedEntityType: "String",
// isTimeStampSelected: false,
// selectedTimestamp: "Last hour",
// operatorOptions: getformattedOptions(operatorsOptions),
// fieldOptions: getformattedOptions(tableEntityListViewModel.headers),
// entityTypeOptions: getformattedOptions(entityTypeOptions),
// operationOptions: getformattedOptions(operationOptions),
// timestampOptions: getformattedOptions(timestampOptions),
// clauseGroup: queryBuilderViewModel.queryClauses,
// isValue: true,
// isLocal: false,
// isTimestamp: false,
// isCustomRangeTimestamp: false,
// customTimeValue: "",
// timeValue: "",
// },
// ],
isLoading: true,
queryErrorMessage: "",
hasQueryError: false,
@ -259,7 +261,7 @@ class QueryTablesTabComponent extends Component<IQueryTablesTabComponentProps, I
public loadFilterExample(): void {
const { queryTableRows, headers, entities } = this.state;
const queryTableRowsClone = [...queryTableRows];
queryTableRowsClone[0].fieldOptions = getformattedOptions(headers);
// queryTableRowsClone[0].fieldOptions = getformattedOptions(headers);
this.setState({
operators: this.state.queryViewModel.queryBuilderViewModel().operators(),
queryTableRows: queryTableRowsClone,
@ -304,7 +306,7 @@ class QueryTablesTabComponent extends Component<IQueryTablesTabComponentProps, I
public async loadEntities(isInitialLoad: boolean): Promise<void> {
const { tableEntityListViewModel, selectedQueryText } = this.state;
tableEntityListViewModel.renderNextPageAndupdateCache();
// tableEntityListViewModel.renderNextPageAndupdateCache();
let headers: string[] = [];
//eslint-disable-next-line
let documents: any = {};
@ -362,6 +364,10 @@ class QueryTablesTabComponent extends Component<IQueryTablesTabComponentProps, I
});
const documentItems = this.generateDetailsList(entities);
console.log(
"🚀 ~ file: QueryTablesTabComponent.tsx ~ line 367 ~ QueryTablesTabComponent ~ documentItems",
documentItems
);
this.setState(
{
@ -373,9 +379,10 @@ class QueryTablesTabComponent extends Component<IQueryTablesTabComponentProps, I
entities: entities,
originalItems: documentItems,
queryText: this.state.queryViewModel.queryText(),
// queryTableRows: headers.length === 0 ? [] : this.state.queryTableRows,
},
() => {
if (isInitialLoad) {
if (isInitialLoad && headers.length > 0) {
this.loadFilterExample();
this.onItemsSelectionChanged(true);
}
@ -628,6 +635,22 @@ class QueryTablesTabComponent extends Component<IQueryTablesTabComponentProps, I
this.state.queryViewModel.toggleAdvancedOptions();
}
public toggleAdvancedOptionsKeyDown(event: React.KeyboardEvent<HTMLDivElement>): void {
if (event.key === NormalizedEventKey.Space || event.key === NormalizedEventKey.Enter) {
this.toggleAdvancedOptions();
event.stopPropagation();
}
}
public selectQueryOptionsKeyDown(event: React.KeyboardEvent<HTMLAnchorElement>): void {
if (event.key === NormalizedEventKey.Space || event.key === NormalizedEventKey.Enter) {
this.state.queryViewModel.selectQueryOptions(this.state.headers, (selectMessage: string) =>
this.getSelectMessage(selectMessage)
);
event.stopPropagation();
}
}
public selectEditor(): void {
this.setState({
isEditorActive: true,
@ -684,6 +707,13 @@ class QueryTablesTabComponent extends Component<IQueryTablesTabComponentProps, I
this.setState({ queryTableRows: cloneQueryTableRows });
};
public onDeleteClauseKeyDown(event: React.KeyboardEvent<HTMLDivElement>, indexToRemove: number): void {
if (event.key === NormalizedEventKey.Space || event.key === NormalizedEventKey.Enter) {
this.onDeleteClause(indexToRemove);
event.stopPropagation();
}
}
onAddNewClause = (): void => {
const { queryTableRows, queryViewModel, headers } = this.state;
this.state.queryViewModel.queryBuilderViewModel().addNewClause();
@ -717,6 +747,15 @@ class QueryTablesTabComponent extends Component<IQueryTablesTabComponentProps, I
this.setState({ queryTableRows: cloneQueryTableRows });
};
public onAddNewClauseKeyDown(event: React.KeyboardEvent<HTMLDivElement>): void {
console.log("🚀 ~ file: QueryTablesTabComponent.tsx ~ line 723 ~ QueryTablesTabComponent ~ event", event);
if (event.key === NormalizedEventKey.Space || event.key === NormalizedEventKey.Enter) {
this.state.queryViewModel.queryBuilderViewModel().onAddNewClauseKeyDown(event);
this.onAddNewClause();
event.stopPropagation();
}
}
private onEntityValueChange = (newInput: string, index: number) => {
const { queryTableRows } = this.state;
const cloneQueryTableRows: IQueryTableRowsType[] = [...queryTableRows];
@ -816,10 +855,22 @@ class QueryTablesTabComponent extends Component<IQueryTablesTabComponentProps, I
onDropdownChange={(selectedOption: IDropdownOption, selectedOptionType: string) =>
this.onDropdownChange(selectedOption, selectedOptionType, index)
}
onAddNewClauseKeyDown={(event: React.KeyboardEvent<HTMLImageElement>) =>
this.onAddNewClauseKeyDown(event)
}
onDeleteCaluseKeyDown={(event: React.KeyboardEvent<HTMLImageElement>) =>
this.onDeleteClauseKeyDown(event, index)
}
/>
))}
</>
<div className="addClause" role="button" onClick={this.onAddNewClause} tabIndex={0}>
<div
className="addClause"
role="button"
onClick={this.onAddNewClause}
onKeyDown={(ev: React.KeyboardEvent<HTMLDivElement>) => this.onAddNewClauseKeyDown(ev)}
tabIndex={0}
>
<div className="addClause-heading">
<span className="clause-table addClause-title">
<img
@ -838,15 +889,12 @@ class QueryTablesTabComponent extends Component<IQueryTablesTabComponentProps, I
</div>
)}
<div className="advanced-options-panel">
<div className="advanced-heading" onClick={() => this.toggleAdvancedOptions()}>
<span
className="advanced-title"
role="button"
aria-expanded={this.state.isExpanded}
// onKeyDown = {() => this.state.queryViewModel.ontoggleAdvancedOptionsKeyDown}
// data-bind="click:toggleAdvancedOptions, event: { keydown: ontoggleAdvancedOptionsKeyDown }, attr:{ 'aria-expanded': isExpanded() ? 'true' : 'false' }"
tabIndex={0}
>
<div
className="advanced-heading"
onClick={() => this.toggleAdvancedOptions()}
onKeyDown={(event: React.KeyboardEvent<HTMLDivElement>) => this.toggleAdvancedOptionsKeyDown(event)}
>
<span className="advanced-title" role="button" aria-expanded={this.state.isExpanded} tabIndex={0}>
{!this.state.isExpanded && (
<div className="themed-images" id="ExpandChevronRight">
<img
@ -890,7 +938,6 @@ class QueryTablesTabComponent extends Component<IQueryTablesTabComponentProps, I
</div>
<a
className="select-options-link"
// data-bind="click: selectQueryOptions, event: { keydown: onselectQueryOptionsKeyDown }"
tabIndex={0}
role="link"
onClick={() =>
@ -898,6 +945,7 @@ class QueryTablesTabComponent extends Component<IQueryTablesTabComponentProps, I
this.getSelectMessage(selectMessage)
)
}
onKeyDown={(event: React.KeyboardEvent<HTMLAnchorElement>) => this.selectQueryOptionsKeyDown(event)}
>
<span>Choose Columns... </span>
</a>