mirror of
https://github.com/Azure/cosmos-explorer.git
synced 2024-11-28 16:36:46 +00:00
Move upload items panel to react (#558)
Co-authored-by: Steve Faulkner <471400+southpolesteve@users.noreply.github.com>
This commit is contained in:
parent
458cca8e01
commit
6a69d3a77b
@ -145,7 +145,6 @@ src/Explorer/Panes/Tables/Validators/EntityPropertyNameValidator.ts
|
|||||||
src/Explorer/Panes/Tables/Validators/EntityPropertyValidationCommon.ts
|
src/Explorer/Panes/Tables/Validators/EntityPropertyValidationCommon.ts
|
||||||
src/Explorer/Panes/Tables/Validators/EntityPropertyValueValidator.ts
|
src/Explorer/Panes/Tables/Validators/EntityPropertyValueValidator.ts
|
||||||
src/Explorer/Panes/UploadFilePane.ts
|
src/Explorer/Panes/UploadFilePane.ts
|
||||||
src/Explorer/Panes/UploadItemsPane.ts
|
|
||||||
src/Explorer/SplashScreen/SplashScreen.test.ts
|
src/Explorer/SplashScreen/SplashScreen.test.ts
|
||||||
src/Explorer/Tables/Constants.ts
|
src/Explorer/Tables/Constants.ts
|
||||||
src/Explorer/Tables/DataTable/CacheBase.ts
|
src/Explorer/Tables/DataTable/CacheBase.ts
|
||||||
|
75
src/Common/Upload/index.tsx
Normal file
75
src/Common/Upload/index.tsx
Normal file
@ -0,0 +1,75 @@
|
|||||||
|
import { Image, Stack, TextField } from "office-ui-fabric-react";
|
||||||
|
import React, { ChangeEvent, FunctionComponent, KeyboardEvent, useRef, useState } from "react";
|
||||||
|
import FolderIcon from "../../../images/folder_16x16.svg";
|
||||||
|
import * as Constants from "../../Common/Constants";
|
||||||
|
import { Tooltip } from "../Tooltip";
|
||||||
|
|
||||||
|
interface UploadProps {
|
||||||
|
label: string;
|
||||||
|
accept?: string;
|
||||||
|
tooltip?: string;
|
||||||
|
multiple?: boolean;
|
||||||
|
tabIndex?: number;
|
||||||
|
onUpload: (event: ChangeEvent<HTMLInputElement>) => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const Upload: FunctionComponent<UploadProps> = ({
|
||||||
|
label,
|
||||||
|
accept,
|
||||||
|
tooltip,
|
||||||
|
multiple,
|
||||||
|
tabIndex,
|
||||||
|
...props
|
||||||
|
}: UploadProps) => {
|
||||||
|
const [selectedFilesTitle, setSelectedFilesTitle] = useState<string[]>([]);
|
||||||
|
|
||||||
|
const fileRef = useRef<HTMLInputElement>();
|
||||||
|
|
||||||
|
const onImportLinkKeyPress = (event: KeyboardEvent<HTMLAnchorElement>): void => {
|
||||||
|
if (event.keyCode === Constants.KeyCodes.Enter || event.keyCode === Constants.KeyCodes.Space) {
|
||||||
|
onImportLinkClick();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const onImportLinkClick = (): void => {
|
||||||
|
fileRef?.current?.click();
|
||||||
|
};
|
||||||
|
|
||||||
|
const onUpload = (event: ChangeEvent<HTMLInputElement>): void => {
|
||||||
|
const { files } = event.target;
|
||||||
|
|
||||||
|
const newFileList = [];
|
||||||
|
for (let i = 0; i < files.length; i++) {
|
||||||
|
newFileList.push(files.item(i).name);
|
||||||
|
}
|
||||||
|
if (newFileList) {
|
||||||
|
setSelectedFilesTitle(newFileList);
|
||||||
|
props.onUpload(event);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
const title = label + " to upload";
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<span className="renewUploadItemsHeader">{label}</span>
|
||||||
|
<Tooltip>{tooltip}</Tooltip>
|
||||||
|
<Stack horizontal>
|
||||||
|
<TextField styles={{ fieldGroup: { width: 300 } }} readOnly value={selectedFilesTitle.toString()} />
|
||||||
|
<input
|
||||||
|
type="file"
|
||||||
|
id="importFileInput"
|
||||||
|
style={{ display: "none" }}
|
||||||
|
ref={fileRef}
|
||||||
|
accept={accept}
|
||||||
|
tabIndex={tabIndex}
|
||||||
|
multiple={multiple}
|
||||||
|
title="Upload Icon"
|
||||||
|
onChange={onUpload}
|
||||||
|
role="button"
|
||||||
|
/>
|
||||||
|
<a href="#" id="fileImportLinkNotebook" onClick={onImportLinkClick} onKeyPress={onImportLinkKeyPress}>
|
||||||
|
<Image className="fileImportImg" src={FolderIcon} alt={title} title={title} />
|
||||||
|
</a>
|
||||||
|
</Stack>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
@ -75,7 +75,6 @@ ko.components.register("table-edit-entity-pane", new PaneComponents.TableEditEnt
|
|||||||
ko.components.register("table-column-options-pane", new PaneComponents.TableColumnOptionsPaneComponent());
|
ko.components.register("table-column-options-pane", new PaneComponents.TableColumnOptionsPaneComponent());
|
||||||
ko.components.register("table-query-select-pane", new PaneComponents.TableQuerySelectPaneComponent());
|
ko.components.register("table-query-select-pane", new PaneComponents.TableQuerySelectPaneComponent());
|
||||||
ko.components.register("cassandra-add-collection-pane", new PaneComponents.CassandraAddCollectionPaneComponent());
|
ko.components.register("cassandra-add-collection-pane", new PaneComponents.CassandraAddCollectionPaneComponent());
|
||||||
ko.components.register("upload-items-pane", new PaneComponents.UploadItemsPaneComponent());
|
|
||||||
ko.components.register("load-query-pane", new PaneComponents.LoadQueryPaneComponent());
|
ko.components.register("load-query-pane", new PaneComponents.LoadQueryPaneComponent());
|
||||||
ko.components.register("save-query-pane", new PaneComponents.SaveQueryPaneComponent());
|
ko.components.register("save-query-pane", new PaneComponents.SaveQueryPaneComponent());
|
||||||
ko.components.register("browse-queries-pane", new PaneComponents.BrowseQueriesPaneComponent());
|
ko.components.register("browse-queries-pane", new PaneComponents.BrowseQueriesPaneComponent());
|
||||||
|
@ -386,23 +386,6 @@ exports[`SettingsComponent renders 1`] = `
|
|||||||
"userTableQuery": [Function],
|
"userTableQuery": [Function],
|
||||||
"visible": [Function],
|
"visible": [Function],
|
||||||
},
|
},
|
||||||
UploadItemsPane {
|
|
||||||
"container": [Circular],
|
|
||||||
"fileUploadSummaryText": [Function],
|
|
||||||
"files": [Function],
|
|
||||||
"firstFieldHasFocus": [Function],
|
|
||||||
"formErrors": [Function],
|
|
||||||
"formErrorsDetails": [Function],
|
|
||||||
"id": "uploaditemspane",
|
|
||||||
"isExecuting": [Function],
|
|
||||||
"isTemplateReady": [Function],
|
|
||||||
"onImportLinkKeyPress": [Function],
|
|
||||||
"selectedFilesTitle": [Function],
|
|
||||||
"title": [Function],
|
|
||||||
"uploadFileData": [Function],
|
|
||||||
"uploadFileDataVisible": [Function],
|
|
||||||
"visible": [Function],
|
|
||||||
},
|
|
||||||
LoadQueryPane {
|
LoadQueryPane {
|
||||||
"container": [Circular],
|
"container": [Circular],
|
||||||
"files": [Function],
|
"files": [Function],
|
||||||
@ -1074,37 +1057,6 @@ exports[`SettingsComponent renders 1`] = `
|
|||||||
"title": [Function],
|
"title": [Function],
|
||||||
"visible": [Function],
|
"visible": [Function],
|
||||||
},
|
},
|
||||||
"uploadItemsPane": UploadItemsPane {
|
|
||||||
"container": [Circular],
|
|
||||||
"fileUploadSummaryText": [Function],
|
|
||||||
"files": [Function],
|
|
||||||
"firstFieldHasFocus": [Function],
|
|
||||||
"formErrors": [Function],
|
|
||||||
"formErrorsDetails": [Function],
|
|
||||||
"id": "uploaditemspane",
|
|
||||||
"isExecuting": [Function],
|
|
||||||
"isTemplateReady": [Function],
|
|
||||||
"onImportLinkKeyPress": [Function],
|
|
||||||
"selectedFilesTitle": [Function],
|
|
||||||
"title": [Function],
|
|
||||||
"uploadFileData": [Function],
|
|
||||||
"uploadFileDataVisible": [Function],
|
|
||||||
"visible": [Function],
|
|
||||||
},
|
|
||||||
"uploadItemsPaneAdapter": UploadItemsPaneAdapter {
|
|
||||||
"_updateSelectedFilesTitle": [Function],
|
|
||||||
"container": [Circular],
|
|
||||||
"formError": "",
|
|
||||||
"formErrorDetail": "",
|
|
||||||
"isExecuting": false,
|
|
||||||
"isOpened": false,
|
|
||||||
"parameters": [Function],
|
|
||||||
"reset": [Function],
|
|
||||||
"selectedFiles": undefined,
|
|
||||||
"selectedFilesTitle": "",
|
|
||||||
"updateSelectedFiles": [Function],
|
|
||||||
"uploadFileData": Array [],
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
"databaseId": "test",
|
"databaseId": "test",
|
||||||
"defaultTtl": [Function],
|
"defaultTtl": [Function],
|
||||||
@ -1484,23 +1436,6 @@ exports[`SettingsComponent renders 1`] = `
|
|||||||
"userTableQuery": [Function],
|
"userTableQuery": [Function],
|
||||||
"visible": [Function],
|
"visible": [Function],
|
||||||
},
|
},
|
||||||
UploadItemsPane {
|
|
||||||
"container": [Circular],
|
|
||||||
"fileUploadSummaryText": [Function],
|
|
||||||
"files": [Function],
|
|
||||||
"firstFieldHasFocus": [Function],
|
|
||||||
"formErrors": [Function],
|
|
||||||
"formErrorsDetails": [Function],
|
|
||||||
"id": "uploaditemspane",
|
|
||||||
"isExecuting": [Function],
|
|
||||||
"isTemplateReady": [Function],
|
|
||||||
"onImportLinkKeyPress": [Function],
|
|
||||||
"selectedFilesTitle": [Function],
|
|
||||||
"title": [Function],
|
|
||||||
"uploadFileData": [Function],
|
|
||||||
"uploadFileDataVisible": [Function],
|
|
||||||
"visible": [Function],
|
|
||||||
},
|
|
||||||
LoadQueryPane {
|
LoadQueryPane {
|
||||||
"container": [Circular],
|
"container": [Circular],
|
||||||
"files": [Function],
|
"files": [Function],
|
||||||
@ -2172,37 +2107,6 @@ exports[`SettingsComponent renders 1`] = `
|
|||||||
"title": [Function],
|
"title": [Function],
|
||||||
"visible": [Function],
|
"visible": [Function],
|
||||||
},
|
},
|
||||||
"uploadItemsPane": UploadItemsPane {
|
|
||||||
"container": [Circular],
|
|
||||||
"fileUploadSummaryText": [Function],
|
|
||||||
"files": [Function],
|
|
||||||
"firstFieldHasFocus": [Function],
|
|
||||||
"formErrors": [Function],
|
|
||||||
"formErrorsDetails": [Function],
|
|
||||||
"id": "uploaditemspane",
|
|
||||||
"isExecuting": [Function],
|
|
||||||
"isTemplateReady": [Function],
|
|
||||||
"onImportLinkKeyPress": [Function],
|
|
||||||
"selectedFilesTitle": [Function],
|
|
||||||
"title": [Function],
|
|
||||||
"uploadFileData": [Function],
|
|
||||||
"uploadFileDataVisible": [Function],
|
|
||||||
"visible": [Function],
|
|
||||||
},
|
|
||||||
"uploadItemsPaneAdapter": UploadItemsPaneAdapter {
|
|
||||||
"_updateSelectedFilesTitle": [Function],
|
|
||||||
"container": [Circular],
|
|
||||||
"formError": "",
|
|
||||||
"formErrorDetail": "",
|
|
||||||
"isExecuting": false,
|
|
||||||
"isOpened": false,
|
|
||||||
"parameters": [Function],
|
|
||||||
"reset": [Function],
|
|
||||||
"selectedFiles": undefined,
|
|
||||||
"selectedFilesTitle": "",
|
|
||||||
"updateSelectedFiles": [Function],
|
|
||||||
"uploadFileData": Array [],
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
isAutoPilotSelected={false}
|
isAutoPilotSelected={false}
|
||||||
@ -2595,23 +2499,6 @@ exports[`SettingsComponent renders 1`] = `
|
|||||||
"userTableQuery": [Function],
|
"userTableQuery": [Function],
|
||||||
"visible": [Function],
|
"visible": [Function],
|
||||||
},
|
},
|
||||||
UploadItemsPane {
|
|
||||||
"container": [Circular],
|
|
||||||
"fileUploadSummaryText": [Function],
|
|
||||||
"files": [Function],
|
|
||||||
"firstFieldHasFocus": [Function],
|
|
||||||
"formErrors": [Function],
|
|
||||||
"formErrorsDetails": [Function],
|
|
||||||
"id": "uploaditemspane",
|
|
||||||
"isExecuting": [Function],
|
|
||||||
"isTemplateReady": [Function],
|
|
||||||
"onImportLinkKeyPress": [Function],
|
|
||||||
"selectedFilesTitle": [Function],
|
|
||||||
"title": [Function],
|
|
||||||
"uploadFileData": [Function],
|
|
||||||
"uploadFileDataVisible": [Function],
|
|
||||||
"visible": [Function],
|
|
||||||
},
|
|
||||||
LoadQueryPane {
|
LoadQueryPane {
|
||||||
"container": [Circular],
|
"container": [Circular],
|
||||||
"files": [Function],
|
"files": [Function],
|
||||||
@ -3283,37 +3170,6 @@ exports[`SettingsComponent renders 1`] = `
|
|||||||
"title": [Function],
|
"title": [Function],
|
||||||
"visible": [Function],
|
"visible": [Function],
|
||||||
},
|
},
|
||||||
"uploadItemsPane": UploadItemsPane {
|
|
||||||
"container": [Circular],
|
|
||||||
"fileUploadSummaryText": [Function],
|
|
||||||
"files": [Function],
|
|
||||||
"firstFieldHasFocus": [Function],
|
|
||||||
"formErrors": [Function],
|
|
||||||
"formErrorsDetails": [Function],
|
|
||||||
"id": "uploaditemspane",
|
|
||||||
"isExecuting": [Function],
|
|
||||||
"isTemplateReady": [Function],
|
|
||||||
"onImportLinkKeyPress": [Function],
|
|
||||||
"selectedFilesTitle": [Function],
|
|
||||||
"title": [Function],
|
|
||||||
"uploadFileData": [Function],
|
|
||||||
"uploadFileDataVisible": [Function],
|
|
||||||
"visible": [Function],
|
|
||||||
},
|
|
||||||
"uploadItemsPaneAdapter": UploadItemsPaneAdapter {
|
|
||||||
"_updateSelectedFilesTitle": [Function],
|
|
||||||
"container": [Circular],
|
|
||||||
"formError": "",
|
|
||||||
"formErrorDetail": "",
|
|
||||||
"isExecuting": false,
|
|
||||||
"isOpened": false,
|
|
||||||
"parameters": [Function],
|
|
||||||
"reset": [Function],
|
|
||||||
"selectedFiles": undefined,
|
|
||||||
"selectedFilesTitle": "",
|
|
||||||
"updateSelectedFiles": [Function],
|
|
||||||
"uploadFileData": Array [],
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
"databaseId": "test",
|
"databaseId": "test",
|
||||||
"defaultTtl": [Function],
|
"defaultTtl": [Function],
|
||||||
@ -3693,23 +3549,6 @@ exports[`SettingsComponent renders 1`] = `
|
|||||||
"userTableQuery": [Function],
|
"userTableQuery": [Function],
|
||||||
"visible": [Function],
|
"visible": [Function],
|
||||||
},
|
},
|
||||||
UploadItemsPane {
|
|
||||||
"container": [Circular],
|
|
||||||
"fileUploadSummaryText": [Function],
|
|
||||||
"files": [Function],
|
|
||||||
"firstFieldHasFocus": [Function],
|
|
||||||
"formErrors": [Function],
|
|
||||||
"formErrorsDetails": [Function],
|
|
||||||
"id": "uploaditemspane",
|
|
||||||
"isExecuting": [Function],
|
|
||||||
"isTemplateReady": [Function],
|
|
||||||
"onImportLinkKeyPress": [Function],
|
|
||||||
"selectedFilesTitle": [Function],
|
|
||||||
"title": [Function],
|
|
||||||
"uploadFileData": [Function],
|
|
||||||
"uploadFileDataVisible": [Function],
|
|
||||||
"visible": [Function],
|
|
||||||
},
|
|
||||||
LoadQueryPane {
|
LoadQueryPane {
|
||||||
"container": [Circular],
|
"container": [Circular],
|
||||||
"files": [Function],
|
"files": [Function],
|
||||||
@ -4381,37 +4220,6 @@ exports[`SettingsComponent renders 1`] = `
|
|||||||
"title": [Function],
|
"title": [Function],
|
||||||
"visible": [Function],
|
"visible": [Function],
|
||||||
},
|
},
|
||||||
"uploadItemsPane": UploadItemsPane {
|
|
||||||
"container": [Circular],
|
|
||||||
"fileUploadSummaryText": [Function],
|
|
||||||
"files": [Function],
|
|
||||||
"firstFieldHasFocus": [Function],
|
|
||||||
"formErrors": [Function],
|
|
||||||
"formErrorsDetails": [Function],
|
|
||||||
"id": "uploaditemspane",
|
|
||||||
"isExecuting": [Function],
|
|
||||||
"isTemplateReady": [Function],
|
|
||||||
"onImportLinkKeyPress": [Function],
|
|
||||||
"selectedFilesTitle": [Function],
|
|
||||||
"title": [Function],
|
|
||||||
"uploadFileData": [Function],
|
|
||||||
"uploadFileDataVisible": [Function],
|
|
||||||
"visible": [Function],
|
|
||||||
},
|
|
||||||
"uploadItemsPaneAdapter": UploadItemsPaneAdapter {
|
|
||||||
"_updateSelectedFilesTitle": [Function],
|
|
||||||
"container": [Circular],
|
|
||||||
"formError": "",
|
|
||||||
"formErrorDetail": "",
|
|
||||||
"isExecuting": false,
|
|
||||||
"isOpened": false,
|
|
||||||
"parameters": [Function],
|
|
||||||
"reset": [Function],
|
|
||||||
"selectedFiles": undefined,
|
|
||||||
"selectedFilesTitle": "",
|
|
||||||
"updateSelectedFiles": [Function],
|
|
||||||
"uploadFileData": Array [],
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
geospatialConfigType="Geometry"
|
geospatialConfigType="Geometry"
|
||||||
|
@ -70,7 +70,6 @@ import { QuerySelectPane } from "./Panes/Tables/QuerySelectPane";
|
|||||||
import { TableColumnOptionsPane } from "./Panes/Tables/TableColumnOptionsPane";
|
import { TableColumnOptionsPane } from "./Panes/Tables/TableColumnOptionsPane";
|
||||||
import { UploadFilePane } from "./Panes/UploadFilePane";
|
import { UploadFilePane } from "./Panes/UploadFilePane";
|
||||||
import { UploadItemsPane } from "./Panes/UploadItemsPane";
|
import { UploadItemsPane } from "./Panes/UploadItemsPane";
|
||||||
import { UploadItemsPaneAdapter } from "./Panes/UploadItemsPaneAdapter";
|
|
||||||
import { CassandraAPIDataClient, TableDataClient, TablesAPIDataClient } from "./Tables/TableDataClient";
|
import { CassandraAPIDataClient, TableDataClient, TablesAPIDataClient } from "./Tables/TableDataClient";
|
||||||
import NotebookV2Tab, { NotebookTabOptions } from "./Tabs/NotebookV2Tab";
|
import NotebookV2Tab, { NotebookTabOptions } from "./Tabs/NotebookV2Tab";
|
||||||
import TabsBase from "./Tabs/TabsBase";
|
import TabsBase from "./Tabs/TabsBase";
|
||||||
@ -212,8 +211,6 @@ export default class Explorer {
|
|||||||
public querySelectPane: QuerySelectPane;
|
public querySelectPane: QuerySelectPane;
|
||||||
public newVertexPane: NewVertexPane;
|
public newVertexPane: NewVertexPane;
|
||||||
public cassandraAddCollectionPane: CassandraAddCollectionPane;
|
public cassandraAddCollectionPane: CassandraAddCollectionPane;
|
||||||
public uploadItemsPane: UploadItemsPane;
|
|
||||||
public uploadItemsPaneAdapter: UploadItemsPaneAdapter;
|
|
||||||
public loadQueryPane: LoadQueryPane;
|
public loadQueryPane: LoadQueryPane;
|
||||||
public saveQueryPane: ContextualPaneBase;
|
public saveQueryPane: ContextualPaneBase;
|
||||||
public browseQueriesPane: BrowseQueriesPane;
|
public browseQueriesPane: BrowseQueriesPane;
|
||||||
@ -623,15 +620,6 @@ export default class Explorer {
|
|||||||
container: this,
|
container: this,
|
||||||
});
|
});
|
||||||
|
|
||||||
this.uploadItemsPane = new UploadItemsPane({
|
|
||||||
id: "uploaditemspane",
|
|
||||||
visible: ko.observable<boolean>(false),
|
|
||||||
|
|
||||||
container: this,
|
|
||||||
});
|
|
||||||
|
|
||||||
this.uploadItemsPaneAdapter = new UploadItemsPaneAdapter(this);
|
|
||||||
|
|
||||||
this.loadQueryPane = new LoadQueryPane({
|
this.loadQueryPane = new LoadQueryPane({
|
||||||
id: "loadquerypane",
|
id: "loadquerypane",
|
||||||
visible: ko.observable<boolean>(false),
|
visible: ko.observable<boolean>(false),
|
||||||
@ -688,7 +676,6 @@ export default class Explorer {
|
|||||||
this.querySelectPane,
|
this.querySelectPane,
|
||||||
this.newVertexPane,
|
this.newVertexPane,
|
||||||
this.cassandraAddCollectionPane,
|
this.cassandraAddCollectionPane,
|
||||||
this.uploadItemsPane,
|
|
||||||
this.loadQueryPane,
|
this.loadQueryPane,
|
||||||
this.saveQueryPane,
|
this.saveQueryPane,
|
||||||
this.browseQueriesPane,
|
this.browseQueriesPane,
|
||||||
@ -2445,6 +2432,10 @@ export default class Explorer {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public openUploadItemsPanePane(): void {
|
||||||
|
this.openSidePanel("Upload", <UploadItemsPane explorer={this} closePanel={this.closeSidePanel} />);
|
||||||
|
}
|
||||||
|
|
||||||
public openSettingPane(): void {
|
public openSettingPane(): void {
|
||||||
this.openSidePanel("Settings", <SettingsPane explorer={this} closePanel={this.closeSidePanel} />);
|
this.openSidePanel("Settings", <SettingsPane explorer={this} closePanel={this.closeSidePanel} />);
|
||||||
}
|
}
|
||||||
|
@ -16,7 +16,6 @@ import TableColumnOptionsPaneTemplate from "./Tables/TableColumnOptionsPane.html
|
|||||||
import TableEditEntityPaneTemplate from "./Tables/TableEditEntityPane.html";
|
import TableEditEntityPaneTemplate from "./Tables/TableEditEntityPane.html";
|
||||||
import TableQuerySelectPaneTemplate from "./Tables/TableQuerySelectPane.html";
|
import TableQuerySelectPaneTemplate from "./Tables/TableQuerySelectPane.html";
|
||||||
import UploadFilePaneTemplate from "./UploadFilePane.html";
|
import UploadFilePaneTemplate from "./UploadFilePane.html";
|
||||||
import UploadItemsPaneTemplate from "./UploadItemsPane.html";
|
|
||||||
|
|
||||||
export class PaneComponent {
|
export class PaneComponent {
|
||||||
constructor(data: any) {
|
constructor(data: any) {
|
||||||
@ -123,15 +122,6 @@ export class CassandraAddCollectionPaneComponent {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export class UploadItemsPaneComponent {
|
|
||||||
constructor() {
|
|
||||||
return {
|
|
||||||
viewModel: PaneComponent,
|
|
||||||
template: UploadItemsPaneTemplate,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export class LoadQueryPaneComponent {
|
export class LoadQueryPaneComponent {
|
||||||
constructor() {
|
constructor() {
|
||||||
return {
|
return {
|
||||||
|
@ -362,23 +362,6 @@ exports[`Settings Pane should render Default properly 1`] = `
|
|||||||
"userTableQuery": [Function],
|
"userTableQuery": [Function],
|
||||||
"visible": [Function],
|
"visible": [Function],
|
||||||
},
|
},
|
||||||
UploadItemsPane {
|
|
||||||
"container": [Circular],
|
|
||||||
"fileUploadSummaryText": [Function],
|
|
||||||
"files": [Function],
|
|
||||||
"firstFieldHasFocus": [Function],
|
|
||||||
"formErrors": [Function],
|
|
||||||
"formErrorsDetails": [Function],
|
|
||||||
"id": "uploaditemspane",
|
|
||||||
"isExecuting": [Function],
|
|
||||||
"isTemplateReady": [Function],
|
|
||||||
"onImportLinkKeyPress": [Function],
|
|
||||||
"selectedFilesTitle": [Function],
|
|
||||||
"title": [Function],
|
|
||||||
"uploadFileData": [Function],
|
|
||||||
"uploadFileDataVisible": [Function],
|
|
||||||
"visible": [Function],
|
|
||||||
},
|
|
||||||
LoadQueryPane {
|
LoadQueryPane {
|
||||||
"container": [Circular],
|
"container": [Circular],
|
||||||
"files": [Function],
|
"files": [Function],
|
||||||
@ -1050,37 +1033,6 @@ exports[`Settings Pane should render Default properly 1`] = `
|
|||||||
"title": [Function],
|
"title": [Function],
|
||||||
"visible": [Function],
|
"visible": [Function],
|
||||||
},
|
},
|
||||||
"uploadItemsPane": UploadItemsPane {
|
|
||||||
"container": [Circular],
|
|
||||||
"fileUploadSummaryText": [Function],
|
|
||||||
"files": [Function],
|
|
||||||
"firstFieldHasFocus": [Function],
|
|
||||||
"formErrors": [Function],
|
|
||||||
"formErrorsDetails": [Function],
|
|
||||||
"id": "uploaditemspane",
|
|
||||||
"isExecuting": [Function],
|
|
||||||
"isTemplateReady": [Function],
|
|
||||||
"onImportLinkKeyPress": [Function],
|
|
||||||
"selectedFilesTitle": [Function],
|
|
||||||
"title": [Function],
|
|
||||||
"uploadFileData": [Function],
|
|
||||||
"uploadFileDataVisible": [Function],
|
|
||||||
"visible": [Function],
|
|
||||||
},
|
|
||||||
"uploadItemsPaneAdapter": UploadItemsPaneAdapter {
|
|
||||||
"_updateSelectedFilesTitle": [Function],
|
|
||||||
"container": [Circular],
|
|
||||||
"formError": "",
|
|
||||||
"formErrorDetail": "",
|
|
||||||
"isExecuting": false,
|
|
||||||
"isOpened": false,
|
|
||||||
"parameters": [Function],
|
|
||||||
"reset": [Function],
|
|
||||||
"selectedFiles": undefined,
|
|
||||||
"selectedFilesTitle": "",
|
|
||||||
"updateSelectedFiles": [Function],
|
|
||||||
"uploadFileData": Array [],
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
formError=""
|
formError=""
|
||||||
@ -1548,23 +1500,6 @@ exports[`Settings Pane should render Gremlin properly 1`] = `
|
|||||||
"userTableQuery": [Function],
|
"userTableQuery": [Function],
|
||||||
"visible": [Function],
|
"visible": [Function],
|
||||||
},
|
},
|
||||||
UploadItemsPane {
|
|
||||||
"container": [Circular],
|
|
||||||
"fileUploadSummaryText": [Function],
|
|
||||||
"files": [Function],
|
|
||||||
"firstFieldHasFocus": [Function],
|
|
||||||
"formErrors": [Function],
|
|
||||||
"formErrorsDetails": [Function],
|
|
||||||
"id": "uploaditemspane",
|
|
||||||
"isExecuting": [Function],
|
|
||||||
"isTemplateReady": [Function],
|
|
||||||
"onImportLinkKeyPress": [Function],
|
|
||||||
"selectedFilesTitle": [Function],
|
|
||||||
"title": [Function],
|
|
||||||
"uploadFileData": [Function],
|
|
||||||
"uploadFileDataVisible": [Function],
|
|
||||||
"visible": [Function],
|
|
||||||
},
|
|
||||||
LoadQueryPane {
|
LoadQueryPane {
|
||||||
"container": [Circular],
|
"container": [Circular],
|
||||||
"files": [Function],
|
"files": [Function],
|
||||||
@ -2236,37 +2171,6 @@ exports[`Settings Pane should render Gremlin properly 1`] = `
|
|||||||
"title": [Function],
|
"title": [Function],
|
||||||
"visible": [Function],
|
"visible": [Function],
|
||||||
},
|
},
|
||||||
"uploadItemsPane": UploadItemsPane {
|
|
||||||
"container": [Circular],
|
|
||||||
"fileUploadSummaryText": [Function],
|
|
||||||
"files": [Function],
|
|
||||||
"firstFieldHasFocus": [Function],
|
|
||||||
"formErrors": [Function],
|
|
||||||
"formErrorsDetails": [Function],
|
|
||||||
"id": "uploaditemspane",
|
|
||||||
"isExecuting": [Function],
|
|
||||||
"isTemplateReady": [Function],
|
|
||||||
"onImportLinkKeyPress": [Function],
|
|
||||||
"selectedFilesTitle": [Function],
|
|
||||||
"title": [Function],
|
|
||||||
"uploadFileData": [Function],
|
|
||||||
"uploadFileDataVisible": [Function],
|
|
||||||
"visible": [Function],
|
|
||||||
},
|
|
||||||
"uploadItemsPaneAdapter": UploadItemsPaneAdapter {
|
|
||||||
"_updateSelectedFilesTitle": [Function],
|
|
||||||
"container": [Circular],
|
|
||||||
"formError": "",
|
|
||||||
"formErrorDetail": "",
|
|
||||||
"isExecuting": false,
|
|
||||||
"isOpened": false,
|
|
||||||
"parameters": [Function],
|
|
||||||
"reset": [Function],
|
|
||||||
"selectedFiles": undefined,
|
|
||||||
"selectedFilesTitle": "",
|
|
||||||
"updateSelectedFiles": [Function],
|
|
||||||
"uploadFileData": Array [],
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
formError=""
|
formError=""
|
||||||
|
@ -1,130 +0,0 @@
|
|||||||
<div data-bind="visible: visible, event: { keydown: onPaneKeyDown }">
|
|
||||||
<div
|
|
||||||
class="contextual-pane-out"
|
|
||||||
data-bind="
|
|
||||||
click: cancel,
|
|
||||||
clickBubble: false"
|
|
||||||
></div>
|
|
||||||
<div class="contextual-pane" id="uploaditemspane">
|
|
||||||
<!-- Upload items form -- Start -->
|
|
||||||
<div class="contextual-pane-in">
|
|
||||||
<form class="paneContentContainer" data-bind="submit: submit">
|
|
||||||
<!-- Upload items header - Start -->
|
|
||||||
<div class="firstdivbg headerline">
|
|
||||||
<span role="heading" aria-level="2" data-bind="text: title"></span>
|
|
||||||
<div
|
|
||||||
class="closeImg"
|
|
||||||
role="button"
|
|
||||||
aria-label="Close pane"
|
|
||||||
tabindex="0"
|
|
||||||
data-bind="
|
|
||||||
click: cancel, event: { keydown: onCloseKeyPress }"
|
|
||||||
>
|
|
||||||
<img src="../../../images/close-black.svg" title="Close" alt="Close" />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<!-- Upload items header - End -->
|
|
||||||
|
|
||||||
<!-- Upload items errors - Start -->
|
|
||||||
<div
|
|
||||||
class="warningErrorContainer"
|
|
||||||
aria-live="assertive"
|
|
||||||
data-bind="visible: formErrors() && formErrors() !== ''"
|
|
||||||
>
|
|
||||||
<div class="warningErrorContent">
|
|
||||||
<span><img class="paneErrorIcon" src="/error_red.svg" alt="Error" /></span>
|
|
||||||
<span class="warningErrorDetailsLinkContainer">
|
|
||||||
<span class="formErrors" data-bind="text: formErrors, attr: { title: formErrors }"></span>
|
|
||||||
<a
|
|
||||||
class="errorLink"
|
|
||||||
role="link"
|
|
||||||
data-bind="
|
|
||||||
visible: formErrorsDetails() && formErrorsDetails() !== '',
|
|
||||||
click: showErrorDetails"
|
|
||||||
>More details</a
|
|
||||||
>
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<!-- Upload items errors - End -->
|
|
||||||
|
|
||||||
<!-- Upload item inputs - Start -->
|
|
||||||
<div class="paneMainContent">
|
|
||||||
<div>
|
|
||||||
<div class="renewUploadItemsHeader">
|
|
||||||
<span> Select JSON Files </span>
|
|
||||||
<span class="infoTooltip" role="tooltip" tabindex="0">
|
|
||||||
<img class="infoImg" src="/info-bubble.svg" alt="More information" />
|
|
||||||
<span class="tooltiptext infoTooltipWidth"
|
|
||||||
>Select one or more JSON files to upload. Each file can contain a single JSON document or an array of
|
|
||||||
JSON documents. The combined size of all files in an individual upload operation must be less than 2
|
|
||||||
MB. You can perform multiple upload operations for larger data sets.</span
|
|
||||||
>
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
<input
|
|
||||||
class="importFilesTitle"
|
|
||||||
type="text"
|
|
||||||
disabled
|
|
||||||
data-bind="value: selectedFilesTitle"
|
|
||||||
aria-label="Select JSON Files"
|
|
||||||
/>
|
|
||||||
<input
|
|
||||||
type="file"
|
|
||||||
id="importDocsInput"
|
|
||||||
title="Upload Icon"
|
|
||||||
multiple
|
|
||||||
accept="application/json"
|
|
||||||
role="button"
|
|
||||||
tabindex="0"
|
|
||||||
style="display: none"
|
|
||||||
data-bind="event: { change: updateSelectedFiles }"
|
|
||||||
/>
|
|
||||||
<a
|
|
||||||
href="#"
|
|
||||||
id="fileImportLink"
|
|
||||||
data-bind="event: { click: onImportLinkClick, keypress: onImportLinkKeyPress }"
|
|
||||||
autofocus
|
|
||||||
>
|
|
||||||
<img
|
|
||||||
class="fileImportImg"
|
|
||||||
src="/folder_16x16.svg"
|
|
||||||
alt="Select JSON files to upload"
|
|
||||||
title="Select JSON files to upload"
|
|
||||||
/>
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
<div class="fileUploadSummaryContainer" data-bind="visible: uploadFileDataVisible">
|
|
||||||
<b>File upload status</b>
|
|
||||||
<table class="fileUploadSummary">
|
|
||||||
<thead>
|
|
||||||
<tr class="fileUploadSummaryHeader fileUploadSummaryTuple">
|
|
||||||
<th>FILE NAME</th>
|
|
||||||
<th>STATUS</th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
<!-- ko foreach: uploadFileData -->
|
|
||||||
<tr class="fileUploadSummaryTuple">
|
|
||||||
<td data-bind="text: $data.fileName"></td>
|
|
||||||
<td data-bind="text: $parent.fileUploadSummaryText($data.numSucceeded, $data.numFailed)"></td>
|
|
||||||
</tr>
|
|
||||||
<!-- /ko -->
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="paneFooter">
|
|
||||||
<div class="leftpanel-okbut"><input type="submit" value="Upload" class="btncreatecoll1" /></div>
|
|
||||||
</div>
|
|
||||||
<!-- Upload item inputs - End -->
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
<!-- Upload items form - Start -->
|
|
||||||
<!-- Loader - Start -->
|
|
||||||
<div class="dataExplorerLoaderContainer dataExplorerPaneLoaderContainer" data-bind="visible: isExecuting">
|
|
||||||
<img class="dataExplorerLoader" src="/LoadingIndicator_3Squares.gif" />
|
|
||||||
</div>
|
|
||||||
<!-- Loader - End -->
|
|
||||||
</div>
|
|
||||||
</div>
|
|
@ -1,143 +0,0 @@
|
|||||||
import * as ko from "knockout";
|
|
||||||
import * as Constants from "../../Common/Constants";
|
|
||||||
import * as ViewModels from "../../Contracts/ViewModels";
|
|
||||||
import { ContextualPaneBase } from "./ContextualPaneBase";
|
|
||||||
import { ConsoleDataType } from "../Menus/NotificationConsole/NotificationConsoleComponent";
|
|
||||||
import * as NotificationConsoleUtils from "../../Utils/NotificationConsoleUtils";
|
|
||||||
import { UploadDetailsRecord, UploadDetails } from "../../workers/upload/definitions";
|
|
||||||
import { getErrorMessage } from "../../Common/ErrorHandlingUtils";
|
|
||||||
|
|
||||||
const UPLOAD_FILE_SIZE_LIMIT = 2097152;
|
|
||||||
|
|
||||||
export class UploadItemsPane extends ContextualPaneBase {
|
|
||||||
public selectedFilesTitle: ko.Observable<string>;
|
|
||||||
public files: ko.Observable<FileList>;
|
|
||||||
public uploadFileDataVisible: ko.Computed<boolean>;
|
|
||||||
public uploadFileData: ko.ObservableArray<UploadDetailsRecord>;
|
|
||||||
|
|
||||||
constructor(options: ViewModels.PaneOptions) {
|
|
||||||
super(options);
|
|
||||||
this._initTitle();
|
|
||||||
this.resetData();
|
|
||||||
|
|
||||||
this.selectedFilesTitle = ko.observable<string>("");
|
|
||||||
this.uploadFileData = ko.observableArray<UploadDetailsRecord>();
|
|
||||||
this.uploadFileDataVisible = ko.computed<boolean>(
|
|
||||||
() => !!this.uploadFileData() && this.uploadFileData().length > 0
|
|
||||||
);
|
|
||||||
this.files = ko.observable<FileList>();
|
|
||||||
this.files.subscribe((newFiles: FileList) => this._updateSelectedFilesTitle(newFiles));
|
|
||||||
}
|
|
||||||
|
|
||||||
public submit() {
|
|
||||||
this.formErrors("");
|
|
||||||
if (!this.files() || this.files().length === 0) {
|
|
||||||
this.formErrors("No files specified");
|
|
||||||
this.formErrorsDetails("No files were specified. Please input at least one file.");
|
|
||||||
NotificationConsoleUtils.logConsoleMessage(
|
|
||||||
ConsoleDataType.Error,
|
|
||||||
"Could not upload items -- No files were specified. Please input at least one file."
|
|
||||||
);
|
|
||||||
return;
|
|
||||||
} else if (this._totalFileSizeForFileList(this.files()) > UPLOAD_FILE_SIZE_LIMIT) {
|
|
||||||
this.formErrors("Upload file size limit exceeded");
|
|
||||||
this.formErrorsDetails("Total file upload size exceeds the 2 MB file size limit.");
|
|
||||||
NotificationConsoleUtils.logConsoleMessage(
|
|
||||||
ConsoleDataType.Error,
|
|
||||||
"Could not upload items -- Total file upload size exceeds the 2 MB file size limit."
|
|
||||||
);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const selectedCollection: ViewModels.Collection = this.container.findSelectedCollection();
|
|
||||||
this.isExecuting(true);
|
|
||||||
selectedCollection &&
|
|
||||||
selectedCollection
|
|
||||||
.uploadFiles(this.files())
|
|
||||||
.then(
|
|
||||||
(uploadDetails: UploadDetails) => {
|
|
||||||
this.uploadFileData(uploadDetails.data);
|
|
||||||
this.files(undefined);
|
|
||||||
this._resetFileInput();
|
|
||||||
},
|
|
||||||
(error: any) => {
|
|
||||||
const errorMessage = getErrorMessage(error);
|
|
||||||
this.formErrors(errorMessage);
|
|
||||||
this.formErrorsDetails(errorMessage);
|
|
||||||
}
|
|
||||||
)
|
|
||||||
.finally(() => {
|
|
||||||
this.isExecuting(false);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
public updateSelectedFiles(element: any, event: any): void {
|
|
||||||
this.files(event.target.files);
|
|
||||||
}
|
|
||||||
|
|
||||||
public close() {
|
|
||||||
super.close();
|
|
||||||
this.resetData();
|
|
||||||
this.files(undefined);
|
|
||||||
this.uploadFileData([]);
|
|
||||||
this._resetFileInput();
|
|
||||||
}
|
|
||||||
|
|
||||||
public onImportLinkClick(source: any, event: MouseEvent): boolean {
|
|
||||||
document.getElementById("importDocsInput").click();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public onImportLinkKeyPress = (source: any, event: KeyboardEvent): boolean => {
|
|
||||||
if (event.keyCode === Constants.KeyCodes.Enter || event.keyCode === Constants.KeyCodes.Space) {
|
|
||||||
this.onImportLinkClick(source, null);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
};
|
|
||||||
|
|
||||||
public fileUploadSummaryText = (numSucceeded: number, numFailed: number): string => {
|
|
||||||
return `${numSucceeded} items created, ${numFailed} errors`;
|
|
||||||
};
|
|
||||||
|
|
||||||
private _totalFileSizeForFileList(fileList: FileList): number {
|
|
||||||
let totalFileSize: number = 0;
|
|
||||||
if (!fileList) {
|
|
||||||
return totalFileSize;
|
|
||||||
}
|
|
||||||
for (let i = 0; i < fileList.length; i++) {
|
|
||||||
totalFileSize = totalFileSize + fileList.item(i).size;
|
|
||||||
}
|
|
||||||
|
|
||||||
return totalFileSize;
|
|
||||||
}
|
|
||||||
|
|
||||||
private _updateSelectedFilesTitle(fileList: FileList) {
|
|
||||||
this.selectedFilesTitle("");
|
|
||||||
|
|
||||||
if (!fileList || fileList.length === 0) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (let i = 0; i < fileList.length; i++) {
|
|
||||||
const originalTitle = this.selectedFilesTitle();
|
|
||||||
this.selectedFilesTitle(originalTitle + `"${fileList.item(i).name}"`);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private _initTitle(): void {
|
|
||||||
if (this.container.isPreferredApiCassandra() || this.container.isPreferredApiTable()) {
|
|
||||||
this.title("Upload Tables");
|
|
||||||
} else if (this.container.isPreferredApiGraph()) {
|
|
||||||
this.title("Upload Graph");
|
|
||||||
} else {
|
|
||||||
this.title("Upload Items");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private _resetFileInput(): void {
|
|
||||||
const inputElement = $("#importDocsInput");
|
|
||||||
inputElement.wrap("<form>").closest("form").get(0).reset();
|
|
||||||
inputElement.unwrap();
|
|
||||||
}
|
|
||||||
}
|
|
1059
src/Explorer/Panes/UploadItemsPane/__snapshots__/index.test.tsx.snap
Normal file
1059
src/Explorer/Panes/UploadItemsPane/__snapshots__/index.test.tsx.snap
Normal file
File diff suppressed because it is too large
Load Diff
14
src/Explorer/Panes/UploadItemsPane/index.test.tsx
Normal file
14
src/Explorer/Panes/UploadItemsPane/index.test.tsx
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
import { shallow } from "enzyme";
|
||||||
|
import React from "react";
|
||||||
|
import { UploadItemsPane } from ".";
|
||||||
|
import Explorer from "../../Explorer";
|
||||||
|
const props = {
|
||||||
|
explorer: new Explorer(),
|
||||||
|
closePanel: (): void => undefined,
|
||||||
|
};
|
||||||
|
describe("Upload Items Pane", () => {
|
||||||
|
it("should render Default properly", () => {
|
||||||
|
const wrapper = shallow(<UploadItemsPane {...props} />);
|
||||||
|
expect(wrapper).toMatchSnapshot();
|
||||||
|
});
|
||||||
|
});
|
160
src/Explorer/Panes/UploadItemsPane/index.tsx
Normal file
160
src/Explorer/Panes/UploadItemsPane/index.tsx
Normal file
@ -0,0 +1,160 @@
|
|||||||
|
import { DetailsList, DetailsListLayoutMode, IColumn, SelectionMode } from "office-ui-fabric-react";
|
||||||
|
import React, { ChangeEvent, FunctionComponent, useState } from "react";
|
||||||
|
import { Upload } from "../../../Common/Upload";
|
||||||
|
import { userContext } from "../../../UserContext";
|
||||||
|
import { logConsoleError } from "../../../Utils/NotificationConsoleUtils";
|
||||||
|
import { UploadDetails, UploadDetailsRecord } from "../../../workers/upload/definitions";
|
||||||
|
import Explorer from "../../Explorer";
|
||||||
|
import { getErrorMessage } from "../../Tables/Utilities";
|
||||||
|
import { GenericRightPaneComponent, GenericRightPaneProps } from "../GenericRightPaneComponent";
|
||||||
|
|
||||||
|
const UPLOAD_FILE_SIZE_LIMIT_KB = 2097152;
|
||||||
|
|
||||||
|
export interface UploadItemsPaneProps {
|
||||||
|
explorer: Explorer;
|
||||||
|
closePanel: () => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface IUploadFileData {
|
||||||
|
numSucceeded: number;
|
||||||
|
numFailed: number;
|
||||||
|
fileName: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
const getTitle = (): string => {
|
||||||
|
if (userContext.apiType === "Cassandra" || userContext.apiType === "Tables") {
|
||||||
|
return "Upload Tables";
|
||||||
|
} else if (userContext.apiType === "Gremlin") {
|
||||||
|
return "Upload Graph";
|
||||||
|
} else {
|
||||||
|
return "Upload Items";
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export const UploadItemsPane: FunctionComponent<UploadItemsPaneProps> = ({
|
||||||
|
explorer,
|
||||||
|
closePanel,
|
||||||
|
}: UploadItemsPaneProps) => {
|
||||||
|
const [files, setFiles] = useState<FileList>();
|
||||||
|
const [uploadFileData, setUploadFileData] = useState<UploadDetailsRecord[]>([]);
|
||||||
|
const [formError, setFormError] = useState<string>("");
|
||||||
|
const [formErrorDetail, setFormErrorDetail] = useState<string>("");
|
||||||
|
const [isExecuting, setIsExecuting] = useState<boolean>();
|
||||||
|
|
||||||
|
const onSubmit = () => {
|
||||||
|
setFormError("");
|
||||||
|
if (!files || files.length === 0) {
|
||||||
|
setFormError("No files specified");
|
||||||
|
setFormErrorDetail("No files were specified. Please input at least one file.");
|
||||||
|
logConsoleError("Could not upload items -- No files were specified. Please input at least one file.");
|
||||||
|
} else if (_totalFileSizeForFileList(files) > UPLOAD_FILE_SIZE_LIMIT_KB) {
|
||||||
|
setFormError("Upload file size limit exceeded");
|
||||||
|
setFormErrorDetail("Total file upload size exceeds the 2 MB file size limit.");
|
||||||
|
logConsoleError("Could not upload items -- Total file upload size exceeds the 2 MB file size limit.");
|
||||||
|
}
|
||||||
|
|
||||||
|
const selectedCollection = explorer.findSelectedCollection();
|
||||||
|
|
||||||
|
setIsExecuting(true);
|
||||||
|
|
||||||
|
selectedCollection
|
||||||
|
?.uploadFiles(files)
|
||||||
|
.then(
|
||||||
|
(uploadDetails: UploadDetails) => {
|
||||||
|
setUploadFileData(uploadDetails.data);
|
||||||
|
setFiles(undefined);
|
||||||
|
},
|
||||||
|
(error: Error) => {
|
||||||
|
const errorMessage = getErrorMessage(error);
|
||||||
|
setFormError(errorMessage);
|
||||||
|
setFormErrorDetail(errorMessage);
|
||||||
|
}
|
||||||
|
)
|
||||||
|
.finally(() => {
|
||||||
|
setIsExecuting(false);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const updateSelectedFiles = (event: ChangeEvent<HTMLInputElement>): void => {
|
||||||
|
setFiles(event.target.files);
|
||||||
|
};
|
||||||
|
|
||||||
|
const _totalFileSizeForFileList = (fileList: FileList): number => {
|
||||||
|
let totalFileSize = 0;
|
||||||
|
for (let i = 0; i < fileList?.length; i++) {
|
||||||
|
totalFileSize += fileList.item(i).size;
|
||||||
|
}
|
||||||
|
return totalFileSize;
|
||||||
|
};
|
||||||
|
|
||||||
|
const genericPaneProps: GenericRightPaneProps = {
|
||||||
|
container: explorer,
|
||||||
|
formError,
|
||||||
|
formErrorDetail,
|
||||||
|
id: "uploaditemspane",
|
||||||
|
isExecuting: isExecuting,
|
||||||
|
title: getTitle(),
|
||||||
|
submitButtonText: "Upload",
|
||||||
|
onClose: closePanel,
|
||||||
|
onSubmit,
|
||||||
|
};
|
||||||
|
const columns: IColumn[] = [
|
||||||
|
{
|
||||||
|
key: "fileName",
|
||||||
|
name: "FILE NAME",
|
||||||
|
fieldName: "fileName",
|
||||||
|
minWidth: 140,
|
||||||
|
maxWidth: 140,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: "status",
|
||||||
|
name: "STATUS",
|
||||||
|
fieldName: "numSucceeded",
|
||||||
|
minWidth: 140,
|
||||||
|
maxWidth: 140,
|
||||||
|
isRowHeader: true,
|
||||||
|
isResizable: true,
|
||||||
|
data: "string",
|
||||||
|
isPadded: true,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
const _renderItemColumn = (item: IUploadFileData, index: number, column: IColumn) => {
|
||||||
|
switch (column.key) {
|
||||||
|
case "status":
|
||||||
|
return <span>{item.numSucceeded + " items created, " + item.numFailed + " errors"}</span>;
|
||||||
|
default:
|
||||||
|
return <span>{item.fileName}</span>;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<GenericRightPaneComponent {...genericPaneProps}>
|
||||||
|
<div className="paneMainContent">
|
||||||
|
<Upload
|
||||||
|
label="Select JSON Files"
|
||||||
|
onUpload={updateSelectedFiles}
|
||||||
|
accept="application/json"
|
||||||
|
multiple
|
||||||
|
tabIndex={0}
|
||||||
|
tooltip="Select one or more JSON files to upload. Each file can contain a single JSON document or an array of JSON
|
||||||
|
documents. The combined size of all files in an individual upload operation must be less than 2 MB. You
|
||||||
|
can perform multiple upload operations for larger data sets."
|
||||||
|
/>
|
||||||
|
{uploadFileData?.length > 0 && (
|
||||||
|
<div className="fileUploadSummaryContainer">
|
||||||
|
<b>File upload status</b>
|
||||||
|
<DetailsList
|
||||||
|
items={uploadFileData}
|
||||||
|
columns={columns}
|
||||||
|
onRenderItemColumn={_renderItemColumn}
|
||||||
|
selectionMode={SelectionMode.none}
|
||||||
|
layoutMode={DetailsListLayoutMode.justified}
|
||||||
|
isHeaderVisible={true}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</GenericRightPaneComponent>
|
||||||
|
);
|
||||||
|
};
|
@ -1,161 +0,0 @@
|
|||||||
import * as ko from "knockout";
|
|
||||||
import * as NotificationConsoleUtils from "../../Utils/NotificationConsoleUtils";
|
|
||||||
import * as React from "react";
|
|
||||||
import * as ViewModels from "../../Contracts/ViewModels";
|
|
||||||
import { ConsoleDataType } from "../Menus/NotificationConsole/NotificationConsoleComponent";
|
|
||||||
import { GenericRightPaneComponent, GenericRightPaneProps } from "./GenericRightPaneComponent";
|
|
||||||
import { ReactAdapter } from "../../Bindings/ReactBindingHandler";
|
|
||||||
import { UploadDetailsRecord, UploadDetails } from "../../workers/upload/definitions";
|
|
||||||
import { UploadItemsPaneComponent, UploadItemsPaneProps } from "./UploadItemsPaneComponent";
|
|
||||||
import Explorer from "../Explorer";
|
|
||||||
import { getErrorMessage } from "../../Common/ErrorHandlingUtils";
|
|
||||||
|
|
||||||
const UPLOAD_FILE_SIZE_LIMIT = 2097152;
|
|
||||||
|
|
||||||
export class UploadItemsPaneAdapter implements ReactAdapter {
|
|
||||||
public parameters: ko.Observable<number>;
|
|
||||||
private isOpened: boolean;
|
|
||||||
private isExecuting: boolean;
|
|
||||||
private formError: string;
|
|
||||||
private formErrorDetail: string;
|
|
||||||
private selectedFiles: FileList;
|
|
||||||
private selectedFilesTitle: string;
|
|
||||||
private uploadFileData: UploadDetailsRecord[];
|
|
||||||
|
|
||||||
public constructor(private container: Explorer) {
|
|
||||||
this.parameters = ko.observable(Date.now());
|
|
||||||
this.reset();
|
|
||||||
this.triggerRender();
|
|
||||||
}
|
|
||||||
|
|
||||||
public renderComponent(): JSX.Element {
|
|
||||||
if (!this.isOpened) {
|
|
||||||
return undefined;
|
|
||||||
}
|
|
||||||
|
|
||||||
const genericPaneProps: GenericRightPaneProps = {
|
|
||||||
container: this.container,
|
|
||||||
formError: this.formError,
|
|
||||||
formErrorDetail: this.formErrorDetail,
|
|
||||||
id: "uploaditemspane",
|
|
||||||
isExecuting: this.isExecuting,
|
|
||||||
title: "Upload Items",
|
|
||||||
submitButtonText: "Upload",
|
|
||||||
onClose: () => this.close(),
|
|
||||||
onSubmit: () => this.submit(),
|
|
||||||
};
|
|
||||||
|
|
||||||
const uploadItemsPaneProps: UploadItemsPaneProps = {
|
|
||||||
selectedFilesTitle: this.selectedFilesTitle,
|
|
||||||
updateSelectedFiles: this.updateSelectedFiles,
|
|
||||||
uploadFileData: this.uploadFileData,
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
|
||||||
<GenericRightPaneComponent {...genericPaneProps}>
|
|
||||||
<UploadItemsPaneComponent {...uploadItemsPaneProps} />
|
|
||||||
</GenericRightPaneComponent>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
public triggerRender(): void {
|
|
||||||
window.requestAnimationFrame(() => this.parameters(Date.now()));
|
|
||||||
}
|
|
||||||
|
|
||||||
public open(): void {
|
|
||||||
this.isOpened = true;
|
|
||||||
this.triggerRender();
|
|
||||||
}
|
|
||||||
|
|
||||||
public close(): void {
|
|
||||||
this.reset();
|
|
||||||
this.triggerRender();
|
|
||||||
}
|
|
||||||
|
|
||||||
public submit(): void {
|
|
||||||
this.formError = "";
|
|
||||||
if (!this.selectedFiles || this.selectedFiles.length === 0) {
|
|
||||||
this.formError = "No files specified";
|
|
||||||
this.formErrorDetail = "No files were specified. Please input at least one file.";
|
|
||||||
NotificationConsoleUtils.logConsoleMessage(
|
|
||||||
ConsoleDataType.Error,
|
|
||||||
"Could not upload items -- No files were specified. Please input at least one file."
|
|
||||||
);
|
|
||||||
this.triggerRender();
|
|
||||||
return;
|
|
||||||
} else if (this._totalFileSizeForFileList() > UPLOAD_FILE_SIZE_LIMIT) {
|
|
||||||
this.formError = "Upload file size limit exceeded";
|
|
||||||
this.formErrorDetail = "Total file upload size exceeds the 2 MB file size limit.";
|
|
||||||
NotificationConsoleUtils.logConsoleMessage(
|
|
||||||
ConsoleDataType.Error,
|
|
||||||
"Could not upload items -- Total file upload size exceeds the 2 MB file size limit."
|
|
||||||
);
|
|
||||||
this.triggerRender();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const selectedCollection: ViewModels.Collection = this.container.findSelectedCollection();
|
|
||||||
this.isExecuting = true;
|
|
||||||
this.triggerRender();
|
|
||||||
selectedCollection &&
|
|
||||||
selectedCollection
|
|
||||||
.uploadFiles(this.selectedFiles)
|
|
||||||
.then(
|
|
||||||
(uploadDetails: UploadDetails) => {
|
|
||||||
this.uploadFileData = uploadDetails.data;
|
|
||||||
this.selectedFiles = undefined;
|
|
||||||
this.selectedFilesTitle = "";
|
|
||||||
},
|
|
||||||
(error) => {
|
|
||||||
const errorMessage = getErrorMessage(error);
|
|
||||||
this.formError = errorMessage;
|
|
||||||
this.formErrorDetail = errorMessage;
|
|
||||||
}
|
|
||||||
)
|
|
||||||
.finally(() => {
|
|
||||||
this.triggerRender();
|
|
||||||
this.isExecuting = false;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
private updateSelectedFiles = (event: React.ChangeEvent<HTMLInputElement>): void => {
|
|
||||||
this.selectedFiles = event.target.files;
|
|
||||||
this._updateSelectedFilesTitle();
|
|
||||||
this.triggerRender();
|
|
||||||
};
|
|
||||||
|
|
||||||
private _updateSelectedFilesTitle = (): void => {
|
|
||||||
this.selectedFilesTitle = "";
|
|
||||||
|
|
||||||
if (!this.selectedFiles || this.selectedFiles.length === 0) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (let i = 0; i < this.selectedFiles.length; i++) {
|
|
||||||
this.selectedFilesTitle += `"${this.selectedFiles.item(i).name}"`;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
private _totalFileSizeForFileList(): number {
|
|
||||||
let totalFileSize = 0;
|
|
||||||
if (!this.selectedFiles) {
|
|
||||||
return totalFileSize;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (let i = 0; i < this.selectedFiles.length; i++) {
|
|
||||||
totalFileSize += this.selectedFiles.item(i).size;
|
|
||||||
}
|
|
||||||
|
|
||||||
return totalFileSize;
|
|
||||||
}
|
|
||||||
|
|
||||||
private reset = (): void => {
|
|
||||||
this.isOpened = false;
|
|
||||||
this.isExecuting = false;
|
|
||||||
this.formError = "";
|
|
||||||
this.formErrorDetail = "";
|
|
||||||
this.selectedFiles = undefined;
|
|
||||||
this.selectedFilesTitle = "";
|
|
||||||
this.uploadFileData = [];
|
|
||||||
};
|
|
||||||
}
|
|
@ -1,97 +0,0 @@
|
|||||||
import * as Constants from "../../Common/Constants";
|
|
||||||
import * as React from "react";
|
|
||||||
import { IconButton } from "office-ui-fabric-react/lib/Button";
|
|
||||||
import { UploadDetailsRecord } from "../../workers/upload/definitions";
|
|
||||||
import InfoBubbleIcon from "../../../images/info-bubble.svg";
|
|
||||||
|
|
||||||
export interface UploadItemsPaneProps {
|
|
||||||
selectedFilesTitle: string;
|
|
||||||
updateSelectedFiles: (event: React.ChangeEvent<HTMLInputElement>) => void;
|
|
||||||
uploadFileData: UploadDetailsRecord[];
|
|
||||||
}
|
|
||||||
|
|
||||||
export class UploadItemsPaneComponent extends React.Component<UploadItemsPaneProps> {
|
|
||||||
public render(): JSX.Element {
|
|
||||||
return (
|
|
||||||
<div className="panelContent">
|
|
||||||
<div className="paneMainContent">
|
|
||||||
<div className="renewUploadItemsHeader">
|
|
||||||
<span> Select JSON Files </span>
|
|
||||||
<span className="infoTooltip" role="tooltip" tabIndex={0}>
|
|
||||||
<img className="infoImg" src={InfoBubbleIcon} alt="More information" />
|
|
||||||
<span className="tooltiptext infoTooltipWidth">
|
|
||||||
Select one or more JSON files to upload. Each file can contain a single JSON document or an array of
|
|
||||||
JSON documents. The combined size of all files in an individual upload operation must be less than 2 MB.
|
|
||||||
You can perform multiple upload operations for larger data sets.
|
|
||||||
</span>
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
<input
|
|
||||||
className="importFilesTitle"
|
|
||||||
type="text"
|
|
||||||
disabled
|
|
||||||
value={this.props.selectedFilesTitle}
|
|
||||||
aria-label="Select JSON Files"
|
|
||||||
/>
|
|
||||||
<input
|
|
||||||
type="file"
|
|
||||||
id="importDocsInput"
|
|
||||||
title="Upload Icon"
|
|
||||||
multiple
|
|
||||||
accept="application/json"
|
|
||||||
role="button"
|
|
||||||
tabIndex={0}
|
|
||||||
style={{ display: "none" }}
|
|
||||||
onChange={this.props.updateSelectedFiles}
|
|
||||||
/>
|
|
||||||
<IconButton
|
|
||||||
iconProps={{ iconName: "FolderHorizontal" }}
|
|
||||||
className="fileImportButton"
|
|
||||||
alt="Select JSON files to upload"
|
|
||||||
title="Select JSON files to upload"
|
|
||||||
onClick={this.onImportButtonClick}
|
|
||||||
onKeyPress={this.onImportButtonKeyPress}
|
|
||||||
/>
|
|
||||||
<div className="fileUploadSummaryContainer" hidden={this.props.uploadFileData.length === 0}>
|
|
||||||
<b>File upload status</b>
|
|
||||||
<table className="fileUploadSummary">
|
|
||||||
<thead>
|
|
||||||
<tr className="fileUploadSummaryHeader fileUploadSummaryTuple">
|
|
||||||
<th>FILE NAME</th>
|
|
||||||
<th>STATUS</th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
{this.props.uploadFileData.map(
|
|
||||||
(data: UploadDetailsRecord): JSX.Element => {
|
|
||||||
return (
|
|
||||||
<tr className="fileUploadSummaryTuple" key={data.fileName}>
|
|
||||||
<td>{data.fileName}</td>
|
|
||||||
<td>{this.fileUploadSummaryText(data.numSucceeded, data.numFailed)}</td>
|
|
||||||
</tr>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
)}
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
private fileUploadSummaryText = (numSucceeded: number, numFailed: number): string => {
|
|
||||||
return `${numSucceeded} items created, ${numFailed} errors`;
|
|
||||||
};
|
|
||||||
|
|
||||||
private onImportButtonClick = (): void => {
|
|
||||||
document.getElementById("importDocsInput").click();
|
|
||||||
};
|
|
||||||
|
|
||||||
private onImportButtonKeyPress = (event: React.KeyboardEvent<HTMLButtonElement>): void => {
|
|
||||||
if (event.charCode === Constants.KeyCodes.Enter || event.charCode === Constants.KeyCodes.Space) {
|
|
||||||
this.onImportButtonClick();
|
|
||||||
event.stopPropagation();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
@ -1,43 +1,35 @@
|
|||||||
|
import { extractPartitionKey, ItemDefinition, PartitionKeyDefinition, QueryIterator, Resource } from "@azure/cosmos";
|
||||||
import * as ko from "knockout";
|
import * as ko from "knockout";
|
||||||
import Q from "q";
|
import Q from "q";
|
||||||
|
import DeleteDocumentIcon from "../../../images/DeleteDocument.svg";
|
||||||
|
import DiscardIcon from "../../../images/discard.svg";
|
||||||
|
import NewDocumentIcon from "../../../images/NewDocument.svg";
|
||||||
|
import SaveIcon from "../../../images/save-cosmos.svg";
|
||||||
|
import UploadIcon from "../../../images/Upload_16x16.svg";
|
||||||
import * as Constants from "../../Common/Constants";
|
import * as Constants from "../../Common/Constants";
|
||||||
|
import { DocumentsGridMetrics, KeyCodes } from "../../Common/Constants";
|
||||||
|
import { createDocument } from "../../Common/dataAccess/createDocument";
|
||||||
|
import { deleteDocument } from "../../Common/dataAccess/deleteDocument";
|
||||||
|
import { queryDocuments } from "../../Common/dataAccess/queryDocuments";
|
||||||
|
import { readDocument } from "../../Common/dataAccess/readDocument";
|
||||||
|
import { updateDocument } from "../../Common/dataAccess/updateDocument";
|
||||||
|
import editable from "../../Common/EditableUtility";
|
||||||
|
import { getErrorMessage, getErrorStack } from "../../Common/ErrorHandlingUtils";
|
||||||
|
import * as HeadersUtility from "../../Common/HeadersUtility";
|
||||||
|
import { Splitter, SplitterBounds, SplitterDirection } from "../../Common/Splitter";
|
||||||
import * as DataModels from "../../Contracts/DataModels";
|
import * as DataModels from "../../Contracts/DataModels";
|
||||||
import * as ViewModels from "../../Contracts/ViewModels";
|
import * as ViewModels from "../../Contracts/ViewModels";
|
||||||
import { Action } from "../../Shared/Telemetry/TelemetryConstants";
|
import { Action } from "../../Shared/Telemetry/TelemetryConstants";
|
||||||
import { AccessibleVerticalList } from "../Tree/AccessibleVerticalList";
|
|
||||||
import { KeyCodes } from "../../Common/Constants";
|
|
||||||
import DocumentId from "../Tree/DocumentId";
|
|
||||||
import editable from "../../Common/EditableUtility";
|
|
||||||
import * as HeadersUtility from "../../Common/HeadersUtility";
|
|
||||||
import TabsBase from "./TabsBase";
|
|
||||||
import { DocumentsGridMetrics } from "../../Common/Constants";
|
|
||||||
import * as QueryUtils from "../../Utils/QueryUtils";
|
|
||||||
import { Splitter, SplitterBounds, SplitterDirection } from "../../Common/Splitter";
|
|
||||||
import * as TelemetryProcessor from "../../Shared/Telemetry/TelemetryProcessor";
|
import * as TelemetryProcessor from "../../Shared/Telemetry/TelemetryProcessor";
|
||||||
import NewDocumentIcon from "../../../images/NewDocument.svg";
|
|
||||||
import SaveIcon from "../../../images/save-cosmos.svg";
|
|
||||||
import DiscardIcon from "../../../images/discard.svg";
|
|
||||||
import DeleteDocumentIcon from "../../../images/DeleteDocument.svg";
|
|
||||||
import UploadIcon from "../../../images/Upload_16x16.svg";
|
|
||||||
import {
|
|
||||||
extractPartitionKey,
|
|
||||||
PartitionKeyDefinition,
|
|
||||||
QueryIterator,
|
|
||||||
ItemDefinition,
|
|
||||||
Resource,
|
|
||||||
Item,
|
|
||||||
} from "@azure/cosmos";
|
|
||||||
import { ConsoleDataType } from "../Menus/NotificationConsole/NotificationConsoleComponent";
|
|
||||||
import * as NotificationConsoleUtils from "../../Utils/NotificationConsoleUtils";
|
import * as NotificationConsoleUtils from "../../Utils/NotificationConsoleUtils";
|
||||||
import Explorer from "../Explorer";
|
import * as QueryUtils from "../../Utils/QueryUtils";
|
||||||
import { CommandButtonComponentProps } from "../Controls/CommandButton/CommandButtonComponent";
|
import { CommandButtonComponentProps } from "../Controls/CommandButton/CommandButtonComponent";
|
||||||
import { getErrorMessage, getErrorStack } from "../../Common/ErrorHandlingUtils";
|
import Explorer from "../Explorer";
|
||||||
import { queryDocuments } from "../../Common/dataAccess/queryDocuments";
|
import { ConsoleDataType } from "../Menus/NotificationConsole/NotificationConsoleComponent";
|
||||||
import { readDocument } from "../../Common/dataAccess/readDocument";
|
import { AccessibleVerticalList } from "../Tree/AccessibleVerticalList";
|
||||||
import { deleteDocument } from "../../Common/dataAccess/deleteDocument";
|
import DocumentId from "../Tree/DocumentId";
|
||||||
import { updateDocument } from "../../Common/dataAccess/updateDocument";
|
|
||||||
import { createDocument } from "../../Common/dataAccess/createDocument";
|
|
||||||
import template from "./DocumentsTab.html";
|
import template from "./DocumentsTab.html";
|
||||||
|
import TabsBase from "./TabsBase";
|
||||||
|
|
||||||
export default class DocumentsTab extends TabsBase {
|
export default class DocumentsTab extends TabsBase {
|
||||||
public static readonly component = { name: "documents-tab", template };
|
public static readonly component = { name: "documents-tab", template };
|
||||||
@ -922,12 +914,7 @@ export default class DocumentsTab extends TabsBase {
|
|||||||
iconAlt: label,
|
iconAlt: label,
|
||||||
onCommandClick: () => {
|
onCommandClick: () => {
|
||||||
const selectedCollection: ViewModels.Collection = container.findSelectedCollection();
|
const selectedCollection: ViewModels.Collection = container.findSelectedCollection();
|
||||||
const focusElement = document.getElementById("itemImportLink");
|
selectedCollection && container.openUploadItemsPanePane();
|
||||||
const uploadItemsPane = container.isRightPanelV2Enabled()
|
|
||||||
? container.uploadItemsPaneAdapter
|
|
||||||
: container.uploadItemsPane;
|
|
||||||
selectedCollection && uploadItemsPane.open();
|
|
||||||
focusElement && focusElement.focus();
|
|
||||||
},
|
},
|
||||||
commandButtonLabel: label,
|
commandButtonLabel: label,
|
||||||
ariaLabel: label,
|
ariaLabel: label,
|
||||||
|
@ -229,7 +229,6 @@ const App: React.FunctionComponent = () => {
|
|||||||
closePanel={closeSidePanel}
|
closePanel={closeSidePanel}
|
||||||
isConsoleExpanded={isNotificationConsoleExpanded}
|
isConsoleExpanded={isNotificationConsoleExpanded}
|
||||||
/>
|
/>
|
||||||
<div data-bind="react:uploadItemsPaneAdapter" />
|
|
||||||
<div data-bind='component: { name: "add-database-pane", params: {data: addDatabasePane} }' />
|
<div data-bind='component: { name: "add-database-pane", params: {data: addDatabasePane} }' />
|
||||||
<div data-bind='component: { name: "add-collection-pane", params: { data: addCollectionPane} }' />
|
<div data-bind='component: { name: "add-collection-pane", params: { data: addCollectionPane} }' />
|
||||||
<div data-bind='component: { name: "delete-collection-confirmation-pane", params: { data: deleteCollectionConfirmationPane} }' />
|
<div data-bind='component: { name: "delete-collection-confirmation-pane", params: { data: deleteCollectionConfirmationPane} }' />
|
||||||
@ -241,7 +240,6 @@ const App: React.FunctionComponent = () => {
|
|||||||
<div data-bind='component: { name: "table-column-options-pane", params: { data: tableColumnOptionsPane} }' />
|
<div data-bind='component: { name: "table-column-options-pane", params: { data: tableColumnOptionsPane} }' />
|
||||||
<div data-bind='component: { name: "table-query-select-pane", params: { data: querySelectPane} }' />
|
<div data-bind='component: { name: "table-query-select-pane", params: { data: querySelectPane} }' />
|
||||||
<div data-bind='component: { name: "cassandra-add-collection-pane", params: { data: cassandraAddCollectionPane} }' />
|
<div data-bind='component: { name: "cassandra-add-collection-pane", params: { data: cassandraAddCollectionPane} }' />
|
||||||
<div data-bind='component: { name: "upload-items-pane", params: { data: uploadItemsPane} }' />
|
|
||||||
<div data-bind='component: { name: "load-query-pane", params: { data: loadQueryPane} }' />
|
<div data-bind='component: { name: "load-query-pane", params: { data: loadQueryPane} }' />
|
||||||
<div data-bind='component: { name: "save-query-pane", params: { data: saveQueryPane} }' />
|
<div data-bind='component: { name: "save-query-pane", params: { data: saveQueryPane} }' />
|
||||||
<div data-bind='component: { name: "browse-queries-pane", params: { data: browseQueriesPane} }' />
|
<div data-bind='component: { name: "browse-queries-pane", params: { data: browseQueriesPane} }' />
|
||||||
|
Loading…
Reference in New Issue
Block a user