Migrate String Input Pane to React (#678)
Co-authored-by: Steve Faulkner <southpolesteve@gmail.com>
This commit is contained in:
parent
67062c18aa
commit
71e7ad4547
|
@ -125,7 +125,7 @@ src/Explorer/Panes/GraphStylingPane.ts
|
|||
# src/Explorer/Panes/NewVertexPane.ts
|
||||
src/Explorer/Panes/PaneComponents.ts
|
||||
src/Explorer/Panes/RenewAdHocAccessPane.ts
|
||||
src/Explorer/Panes/StringInputPane.ts
|
||||
src/Explorer/Panes/SetupNotebooksPane.ts
|
||||
src/Explorer/Panes/SwitchDirectoryPane.ts
|
||||
src/Explorer/Panes/Tables/EditTableEntityPane.ts
|
||||
src/Explorer/Panes/Tables/EntityPropertyViewModel.ts
|
||||
|
|
|
@ -28,10 +28,6 @@ describe("Component Registerer", () => {
|
|||
expect(ko.components.isRegistered("graph-styling-pane")).toBe(true);
|
||||
});
|
||||
|
||||
it("should register string-input-pane component", () => {
|
||||
expect(ko.components.isRegistered("string-input-pane")).toBe(true);
|
||||
});
|
||||
|
||||
it("should register dynamic-list component", () => {
|
||||
expect(ko.components.isRegistered("dynamic-list")).toBe(true);
|
||||
});
|
||||
|
|
|
@ -25,5 +25,4 @@ ko.components.register("graph-styling-pane", new PaneComponents.GraphStylingPane
|
|||
ko.components.register("table-add-entity-pane", new PaneComponents.TableAddEntityPaneComponent());
|
||||
ko.components.register("table-edit-entity-pane", new PaneComponents.TableEditEntityPaneComponent());
|
||||
ko.components.register("cassandra-add-collection-pane", new PaneComponents.CassandraAddCollectionPaneComponent());
|
||||
ko.components.register("string-input-pane", new PaneComponents.StringInputPaneComponent());
|
||||
ko.components.register("github-repos-pane", new PaneComponents.GitHubReposPaneComponent());
|
||||
|
|
|
@ -224,20 +224,6 @@ exports[`SettingsComponent renders 1`] = `
|
|||
"userTableQuery": [Function],
|
||||
"visible": [Function],
|
||||
},
|
||||
StringInputPane {
|
||||
"container": [Circular],
|
||||
"firstFieldHasFocus": [Function],
|
||||
"formErrors": [Function],
|
||||
"formErrorsDetails": [Function],
|
||||
"id": "stringinputpane",
|
||||
"inputLabel": [Function],
|
||||
"isExecuting": [Function],
|
||||
"isTemplateReady": [Function],
|
||||
"stringInput": [Function],
|
||||
"submitButtonLabel": [Function],
|
||||
"title": [Function],
|
||||
"visible": [Function],
|
||||
},
|
||||
],
|
||||
"_refreshSparkEnabledStateForAccount": [Function],
|
||||
"_resetNotebookWorkspace": [Function],
|
||||
|
@ -548,20 +534,6 @@ exports[`SettingsComponent renders 1`] = `
|
|||
"onResizeStop": [Function],
|
||||
"splitterId": "h_splitter1",
|
||||
},
|
||||
"stringInputPane": StringInputPane {
|
||||
"container": [Circular],
|
||||
"firstFieldHasFocus": [Function],
|
||||
"formErrors": [Function],
|
||||
"formErrorsDetails": [Function],
|
||||
"id": "stringinputpane",
|
||||
"inputLabel": [Function],
|
||||
"isExecuting": [Function],
|
||||
"isTemplateReady": [Function],
|
||||
"stringInput": [Function],
|
||||
"submitButtonLabel": [Function],
|
||||
"title": [Function],
|
||||
"visible": [Function],
|
||||
},
|
||||
"tabsManager": TabsManager {
|
||||
"activeTab": [Function],
|
||||
"openedTabs": [Function],
|
||||
|
@ -784,20 +756,6 @@ exports[`SettingsComponent renders 1`] = `
|
|||
"userTableQuery": [Function],
|
||||
"visible": [Function],
|
||||
},
|
||||
StringInputPane {
|
||||
"container": [Circular],
|
||||
"firstFieldHasFocus": [Function],
|
||||
"formErrors": [Function],
|
||||
"formErrorsDetails": [Function],
|
||||
"id": "stringinputpane",
|
||||
"inputLabel": [Function],
|
||||
"isExecuting": [Function],
|
||||
"isTemplateReady": [Function],
|
||||
"stringInput": [Function],
|
||||
"submitButtonLabel": [Function],
|
||||
"title": [Function],
|
||||
"visible": [Function],
|
||||
},
|
||||
],
|
||||
"_refreshSparkEnabledStateForAccount": [Function],
|
||||
"_resetNotebookWorkspace": [Function],
|
||||
|
@ -1108,20 +1066,6 @@ exports[`SettingsComponent renders 1`] = `
|
|||
"onResizeStop": [Function],
|
||||
"splitterId": "h_splitter1",
|
||||
},
|
||||
"stringInputPane": StringInputPane {
|
||||
"container": [Circular],
|
||||
"firstFieldHasFocus": [Function],
|
||||
"formErrors": [Function],
|
||||
"formErrorsDetails": [Function],
|
||||
"id": "stringinputpane",
|
||||
"inputLabel": [Function],
|
||||
"isExecuting": [Function],
|
||||
"isTemplateReady": [Function],
|
||||
"stringInput": [Function],
|
||||
"submitButtonLabel": [Function],
|
||||
"title": [Function],
|
||||
"visible": [Function],
|
||||
},
|
||||
"tabsManager": TabsManager {
|
||||
"activeTab": [Function],
|
||||
"openedTabs": [Function],
|
||||
|
@ -1357,20 +1301,6 @@ exports[`SettingsComponent renders 1`] = `
|
|||
"userTableQuery": [Function],
|
||||
"visible": [Function],
|
||||
},
|
||||
StringInputPane {
|
||||
"container": [Circular],
|
||||
"firstFieldHasFocus": [Function],
|
||||
"formErrors": [Function],
|
||||
"formErrorsDetails": [Function],
|
||||
"id": "stringinputpane",
|
||||
"inputLabel": [Function],
|
||||
"isExecuting": [Function],
|
||||
"isTemplateReady": [Function],
|
||||
"stringInput": [Function],
|
||||
"submitButtonLabel": [Function],
|
||||
"title": [Function],
|
||||
"visible": [Function],
|
||||
},
|
||||
],
|
||||
"_refreshSparkEnabledStateForAccount": [Function],
|
||||
"_resetNotebookWorkspace": [Function],
|
||||
|
@ -1681,20 +1611,6 @@ exports[`SettingsComponent renders 1`] = `
|
|||
"onResizeStop": [Function],
|
||||
"splitterId": "h_splitter1",
|
||||
},
|
||||
"stringInputPane": StringInputPane {
|
||||
"container": [Circular],
|
||||
"firstFieldHasFocus": [Function],
|
||||
"formErrors": [Function],
|
||||
"formErrorsDetails": [Function],
|
||||
"id": "stringinputpane",
|
||||
"inputLabel": [Function],
|
||||
"isExecuting": [Function],
|
||||
"isTemplateReady": [Function],
|
||||
"stringInput": [Function],
|
||||
"submitButtonLabel": [Function],
|
||||
"title": [Function],
|
||||
"visible": [Function],
|
||||
},
|
||||
"tabsManager": TabsManager {
|
||||
"activeTab": [Function],
|
||||
"openedTabs": [Function],
|
||||
|
@ -1917,20 +1833,6 @@ exports[`SettingsComponent renders 1`] = `
|
|||
"userTableQuery": [Function],
|
||||
"visible": [Function],
|
||||
},
|
||||
StringInputPane {
|
||||
"container": [Circular],
|
||||
"firstFieldHasFocus": [Function],
|
||||
"formErrors": [Function],
|
||||
"formErrorsDetails": [Function],
|
||||
"id": "stringinputpane",
|
||||
"inputLabel": [Function],
|
||||
"isExecuting": [Function],
|
||||
"isTemplateReady": [Function],
|
||||
"stringInput": [Function],
|
||||
"submitButtonLabel": [Function],
|
||||
"title": [Function],
|
||||
"visible": [Function],
|
||||
},
|
||||
],
|
||||
"_refreshSparkEnabledStateForAccount": [Function],
|
||||
"_resetNotebookWorkspace": [Function],
|
||||
|
@ -2241,20 +2143,6 @@ exports[`SettingsComponent renders 1`] = `
|
|||
"onResizeStop": [Function],
|
||||
"splitterId": "h_splitter1",
|
||||
},
|
||||
"stringInputPane": StringInputPane {
|
||||
"container": [Circular],
|
||||
"firstFieldHasFocus": [Function],
|
||||
"formErrors": [Function],
|
||||
"formErrorsDetails": [Function],
|
||||
"id": "stringinputpane",
|
||||
"inputLabel": [Function],
|
||||
"isExecuting": [Function],
|
||||
"isTemplateReady": [Function],
|
||||
"stringInput": [Function],
|
||||
"submitButtonLabel": [Function],
|
||||
"title": [Function],
|
||||
"visible": [Function],
|
||||
},
|
||||
"tabsManager": TabsManager {
|
||||
"activeTab": [Function],
|
||||
"openedTabs": [Function],
|
||||
|
|
|
@ -64,7 +64,7 @@ import { LoadQueryPane } from "./Panes/LoadQueryPane/LoadQueryPane";
|
|||
import { SaveQueryPane } from "./Panes/SaveQueryPane/SaveQueryPane";
|
||||
import { SettingsPane } from "./Panes/SettingsPane/SettingsPane";
|
||||
import { SetupNoteBooksPanel } from "./Panes/SetupNotebooksPanel/SetupNotebooksPanel";
|
||||
import { StringInputPane } from "./Panes/StringInputPane";
|
||||
import { StringInputPane } from "./Panes/StringInputPane/StringInputPane";
|
||||
import { AddTableEntityPanel } from "./Panes/Tables/AddTableEntityPanel";
|
||||
import { EditTableEntityPanel } from "./Panes/Tables/EditTableEntityPanel";
|
||||
import { TableQuerySelectPanel } from "./Panes/Tables/TableQuerySelectPanel";
|
||||
|
@ -174,7 +174,6 @@ export default class Explorer {
|
|||
public addCollectionPane: AddCollectionPane;
|
||||
public graphStylingPane: GraphStylingPane;
|
||||
public cassandraAddCollectionPane: CassandraAddCollectionPane;
|
||||
public stringInputPane: StringInputPane;
|
||||
public gitHubReposPane: ContextualPaneBase;
|
||||
public publishNotebookPaneAdapter: ReactAdapter;
|
||||
|
||||
|
@ -506,13 +505,6 @@ export default class Explorer {
|
|||
container: this,
|
||||
});
|
||||
|
||||
this.stringInputPane = new StringInputPane({
|
||||
id: "stringinputpane",
|
||||
visible: ko.observable<boolean>(false),
|
||||
|
||||
container: this,
|
||||
});
|
||||
|
||||
this.tabsManager = params?.tabsManager ?? new TabsManager();
|
||||
this.tabsManager.openedTabs.subscribe((tabs) => {
|
||||
if (tabs.length === 0) {
|
||||
|
@ -526,7 +518,6 @@ export default class Explorer {
|
|||
this.addCollectionPane,
|
||||
this.graphStylingPane,
|
||||
this.cassandraAddCollectionPane,
|
||||
this.stringInputPane,
|
||||
];
|
||||
this.addDatabaseText.subscribe((addDatabaseText: string) => this.addDatabasePane.title(addDatabaseText));
|
||||
this.isTabsContentExpanded = ko.observable(false);
|
||||
|
@ -1533,7 +1524,7 @@ export default class Explorer {
|
|||
return true;
|
||||
}
|
||||
|
||||
public renameNotebook(notebookFile: NotebookContentItem): Q.Promise<NotebookContentItem> {
|
||||
public renameNotebook(notebookFile: NotebookContentItem): void {
|
||||
if (!this.isNotebookEnabled() || !this.notebookManager?.notebookContentClient) {
|
||||
const error = "Attempt to rename notebook, but notebook is not enabled";
|
||||
handleError(error, "Explorer/renameNotebook");
|
||||
|
@ -1549,57 +1540,59 @@ export default class Explorer {
|
|||
);
|
||||
if (openedNotebookTabs.length > 0) {
|
||||
this.showOkModalDialog("Unable to rename file", "This file is being edited. Please close the tab and try again.");
|
||||
return Q.reject();
|
||||
} else {
|
||||
this.openSidePanel(
|
||||
"",
|
||||
<StringInputPane
|
||||
explorer={this}
|
||||
closePanel={() => {
|
||||
this.closeSidePanel();
|
||||
this.resourceTree.triggerRender();
|
||||
}}
|
||||
inputLabel="Enter new notebook name"
|
||||
submitButtonLabel="Rename"
|
||||
errorMessage="Could not rename notebook"
|
||||
inProgressMessage="Renaming notebook to"
|
||||
successMessage="Renamed notebook to"
|
||||
paneTitle="Rename Notebook"
|
||||
defaultInput={FileSystemUtil.stripExtension(notebookFile.name, "ipynb")}
|
||||
onSubmit={(notebookFile: NotebookContentItem, input: string): Promise<NotebookContentItem> =>
|
||||
this.notebookManager?.notebookContentClient.renameNotebook(notebookFile, input)
|
||||
}
|
||||
|
||||
const originalPath = notebookFile.path;
|
||||
const result = this.stringInputPane
|
||||
.openWithOptions<NotebookContentItem>({
|
||||
errorMessage: "Could not rename notebook",
|
||||
inProgressMessage: "Renaming notebook to",
|
||||
successMessage: "Renamed notebook to",
|
||||
inputLabel: "Enter new notebook name",
|
||||
paneTitle: "Rename Notebook",
|
||||
submitButtonLabel: "Rename",
|
||||
defaultInput: FileSystemUtil.stripExtension(notebookFile.name, "ipynb"),
|
||||
onSubmit: (input: string) => this.notebookManager?.notebookContentClient.renameNotebook(notebookFile, input),
|
||||
})
|
||||
.then((newNotebookFile) => {
|
||||
const notebookTabs = this.tabsManager.getTabs(
|
||||
ViewModels.CollectionTabKind.NotebookV2,
|
||||
(tab: NotebookV2Tab) => tab.notebookPath && FileSystemUtil.isPathEqual(tab.notebookPath(), originalPath)
|
||||
notebookFile={notebookFile}
|
||||
/>
|
||||
);
|
||||
notebookTabs.forEach((tab) => {
|
||||
tab.tabTitle(newNotebookFile.name);
|
||||
tab.tabPath(newNotebookFile.path);
|
||||
(tab as NotebookV2Tab).notebookPath(newNotebookFile.path);
|
||||
});
|
||||
|
||||
return newNotebookFile;
|
||||
});
|
||||
result.then(() => this.resourceTree.triggerRender());
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
public onCreateDirectory(parent: NotebookContentItem): Q.Promise<NotebookContentItem> {
|
||||
public onCreateDirectory(parent: NotebookContentItem): void {
|
||||
if (!this.isNotebookEnabled() || !this.notebookManager?.notebookContentClient) {
|
||||
const error = "Attempt to create notebook directory, but notebook is not enabled";
|
||||
handleError(error, "Explorer/onCreateDirectory");
|
||||
throw new Error(error);
|
||||
}
|
||||
|
||||
const result = this.stringInputPane.openWithOptions<NotebookContentItem>({
|
||||
errorMessage: "Could not create directory ",
|
||||
inProgressMessage: "Creating directory ",
|
||||
successMessage: "Created directory ",
|
||||
inputLabel: "Enter new directory name",
|
||||
paneTitle: "Create new directory",
|
||||
submitButtonLabel: "Create",
|
||||
defaultInput: "",
|
||||
onSubmit: (input: string) => this.notebookManager?.notebookContentClient.createDirectory(parent, input),
|
||||
});
|
||||
result.then(() => this.resourceTree.triggerRender());
|
||||
return result;
|
||||
this.openSidePanel(
|
||||
"",
|
||||
<StringInputPane
|
||||
explorer={this}
|
||||
closePanel={() => {
|
||||
this.closeSidePanel();
|
||||
this.resourceTree.triggerRender();
|
||||
}}
|
||||
errorMessage="Could not create directory "
|
||||
inProgressMessage="Creating directory "
|
||||
successMessage="Created directory "
|
||||
inputLabel="Enter new directory name"
|
||||
paneTitle="Create new directory"
|
||||
submitButtonLabel="Create"
|
||||
defaultInput=""
|
||||
onSubmit={(notebookFile: NotebookContentItem, input: string): Promise<NotebookContentItem> =>
|
||||
this.notebookManager?.notebookContentClient.createDirectory(notebookFile, input)
|
||||
}
|
||||
notebookFile={parent}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
public readFile(notebookFile: NotebookContentItem): Promise<string> {
|
||||
|
|
|
@ -3,7 +3,6 @@ import AddDatabasePaneTemplate from "./AddDatabasePane.html";
|
|||
import CassandraAddCollectionPaneTemplate from "./CassandraAddCollectionPane.html";
|
||||
import GitHubReposPaneTemplate from "./GitHubReposPane.html";
|
||||
import GraphStylingPaneTemplate from "./GraphStylingPane.html";
|
||||
import StringInputPaneTemplate from "./StringInputPane.html";
|
||||
import TableAddEntityPaneTemplate from "./Tables/TableAddEntityPane.html";
|
||||
import TableEditEntityPaneTemplate from "./Tables/TableEditEntityPane.html";
|
||||
|
||||
|
@ -66,15 +65,6 @@ export class CassandraAddCollectionPaneComponent {
|
|||
}
|
||||
}
|
||||
|
||||
export class StringInputPaneComponent {
|
||||
constructor() {
|
||||
return {
|
||||
viewModel: PaneComponent,
|
||||
template: StringInputPaneTemplate,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
export class GitHubReposPaneComponent {
|
||||
constructor() {
|
||||
return {
|
||||
|
|
|
@ -200,20 +200,6 @@ exports[`Settings Pane should render Default properly 1`] = `
|
|||
"userTableQuery": [Function],
|
||||
"visible": [Function],
|
||||
},
|
||||
StringInputPane {
|
||||
"container": [Circular],
|
||||
"firstFieldHasFocus": [Function],
|
||||
"formErrors": [Function],
|
||||
"formErrorsDetails": [Function],
|
||||
"id": "stringinputpane",
|
||||
"inputLabel": [Function],
|
||||
"isExecuting": [Function],
|
||||
"isTemplateReady": [Function],
|
||||
"stringInput": [Function],
|
||||
"submitButtonLabel": [Function],
|
||||
"title": [Function],
|
||||
"visible": [Function],
|
||||
},
|
||||
],
|
||||
"_refreshSparkEnabledStateForAccount": [Function],
|
||||
"_resetNotebookWorkspace": [Function],
|
||||
|
@ -524,20 +510,6 @@ exports[`Settings Pane should render Default properly 1`] = `
|
|||
"onResizeStop": [Function],
|
||||
"splitterId": "h_splitter1",
|
||||
},
|
||||
"stringInputPane": StringInputPane {
|
||||
"container": [Circular],
|
||||
"firstFieldHasFocus": [Function],
|
||||
"formErrors": [Function],
|
||||
"formErrorsDetails": [Function],
|
||||
"id": "stringinputpane",
|
||||
"inputLabel": [Function],
|
||||
"isExecuting": [Function],
|
||||
"isTemplateReady": [Function],
|
||||
"stringInput": [Function],
|
||||
"submitButtonLabel": [Function],
|
||||
"title": [Function],
|
||||
"visible": [Function],
|
||||
},
|
||||
"tabsManager": TabsManager {
|
||||
"activeTab": [Function],
|
||||
"openedTabs": [Function],
|
||||
|
@ -883,20 +855,6 @@ exports[`Settings Pane should render Gremlin properly 1`] = `
|
|||
"userTableQuery": [Function],
|
||||
"visible": [Function],
|
||||
},
|
||||
StringInputPane {
|
||||
"container": [Circular],
|
||||
"firstFieldHasFocus": [Function],
|
||||
"formErrors": [Function],
|
||||
"formErrorsDetails": [Function],
|
||||
"id": "stringinputpane",
|
||||
"inputLabel": [Function],
|
||||
"isExecuting": [Function],
|
||||
"isTemplateReady": [Function],
|
||||
"stringInput": [Function],
|
||||
"submitButtonLabel": [Function],
|
||||
"title": [Function],
|
||||
"visible": [Function],
|
||||
},
|
||||
],
|
||||
"_refreshSparkEnabledStateForAccount": [Function],
|
||||
"_resetNotebookWorkspace": [Function],
|
||||
|
@ -1207,20 +1165,6 @@ exports[`Settings Pane should render Gremlin properly 1`] = `
|
|||
"onResizeStop": [Function],
|
||||
"splitterId": "h_splitter1",
|
||||
},
|
||||
"stringInputPane": StringInputPane {
|
||||
"container": [Circular],
|
||||
"firstFieldHasFocus": [Function],
|
||||
"formErrors": [Function],
|
||||
"formErrorsDetails": [Function],
|
||||
"id": "stringinputpane",
|
||||
"inputLabel": [Function],
|
||||
"isExecuting": [Function],
|
||||
"isTemplateReady": [Function],
|
||||
"stringInput": [Function],
|
||||
"submitButtonLabel": [Function],
|
||||
"title": [Function],
|
||||
"visible": [Function],
|
||||
},
|
||||
"tabsManager": TabsManager {
|
||||
"activeTab": [Function],
|
||||
"openedTabs": [Function],
|
||||
|
|
|
@ -1,66 +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="stringInputPane">
|
||||
<!-- String Input form -- Start -->
|
||||
<div class="contextual-pane-in">
|
||||
<form class="paneContentContainer" data-bind="submit: submit">
|
||||
<!-- String Input 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"></div>
|
||||
</div>
|
||||
<!-- String Input header - End -->
|
||||
|
||||
<!-- String Input 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>
|
||||
<!-- String Input errors - End -->
|
||||
|
||||
<!-- String Input inputs - Start -->
|
||||
<div class="paneMainContent">
|
||||
<div>
|
||||
<p data-bind="text: inputLabel"></p>
|
||||
<p>
|
||||
<input
|
||||
type="text"
|
||||
name="collectionIdConfirmation"
|
||||
required
|
||||
class="collid"
|
||||
data-bind="textInput: stringInput, hasFocus: firstFieldHasFocus"
|
||||
aria-label="inputLabel"
|
||||
/>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="paneFooter">
|
||||
<div class="leftpanel-okbut">
|
||||
<input type="submit" data-bind="attr: { value: submitButtonLabel }" class="btncreatecoll1" />
|
||||
</div>
|
||||
</div>
|
||||
<!-- String Input inputs - End -->
|
||||
</form>
|
||||
</div>
|
||||
<!-- String Input 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,99 +0,0 @@
|
|||
import * as ko from "knockout";
|
||||
import Q from "q";
|
||||
import * as ViewModels from "../../Contracts/ViewModels";
|
||||
import { logConsoleError, logConsoleInfo, logConsoleProgress } from "../../Utils/NotificationConsoleUtils";
|
||||
import { ContextualPaneBase } from "./ContextualPaneBase";
|
||||
|
||||
export interface StringInputPaneOpenOptions {
|
||||
paneTitle: string;
|
||||
inputLabel: string;
|
||||
errorMessage: string;
|
||||
inProgressMessage: string;
|
||||
successMessage: string;
|
||||
onSubmit: (input: string) => Promise<any>;
|
||||
submitButtonLabel: string;
|
||||
defaultInput?: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generic pane to get a single string input from user
|
||||
*/
|
||||
export class StringInputPane extends ContextualPaneBase {
|
||||
private openOptions: StringInputPaneOpenOptions;
|
||||
private submitButtonLabel: ko.Observable<string>;
|
||||
private inputLabel: ko.Observable<string>;
|
||||
private stringInput: ko.Observable<string>;
|
||||
|
||||
private paneDeferred: Q.Deferred<any>;
|
||||
|
||||
constructor(options: ViewModels.PaneOptions) {
|
||||
super(options);
|
||||
this.resetData();
|
||||
this.inputLabel = ko.observable("");
|
||||
this.submitButtonLabel = ko.observable("Load");
|
||||
this.stringInput = ko.observable();
|
||||
}
|
||||
|
||||
public submit() {
|
||||
this.formErrors("");
|
||||
this.formErrorsDetails("");
|
||||
|
||||
const clearInProgressMessage = logConsoleProgress(`${this.openOptions.inProgressMessage} ${this.stringInput()}`);
|
||||
this.isExecuting(true);
|
||||
this.openOptions
|
||||
.onSubmit(this.stringInput())
|
||||
.then(
|
||||
(value: any) => {
|
||||
logConsoleInfo(`${this.openOptions.successMessage}: ${this.stringInput()}`);
|
||||
this.close();
|
||||
this.paneDeferred.resolve(value);
|
||||
},
|
||||
(reason) => {
|
||||
let error = reason;
|
||||
if (reason instanceof Error) {
|
||||
error = reason.message;
|
||||
} else if (typeof reason === "object") {
|
||||
error = JSON.stringify(reason);
|
||||
}
|
||||
|
||||
// If it's an AjaxError (AjaxObservable), add more error
|
||||
if (reason.response && reason.response.message) {
|
||||
error += `. ${reason.response.message}`;
|
||||
}
|
||||
|
||||
this.formErrors(this.openOptions.errorMessage);
|
||||
this.formErrorsDetails(`${this.openOptions.errorMessage}: ${error}`);
|
||||
logConsoleError(`${this.openOptions.errorMessage} ${this.stringInput()}: ${error}`);
|
||||
this.paneDeferred.reject(error);
|
||||
}
|
||||
)
|
||||
.finally(() => {
|
||||
this.isExecuting(false);
|
||||
clearInProgressMessage();
|
||||
});
|
||||
}
|
||||
|
||||
public close() {
|
||||
super.close();
|
||||
this.resetData();
|
||||
this.resetFileInput();
|
||||
}
|
||||
|
||||
public openWithOptions<T>(options: StringInputPaneOpenOptions): Q.Promise<T> {
|
||||
this.openOptions = options;
|
||||
this.title(this.openOptions.paneTitle);
|
||||
if (this.openOptions.submitButtonLabel) {
|
||||
this.submitButtonLabel(this.openOptions.submitButtonLabel);
|
||||
}
|
||||
this.inputLabel(this.openOptions.inputLabel);
|
||||
this.stringInput(this.openOptions.defaultInput);
|
||||
|
||||
super.open();
|
||||
this.paneDeferred = Q.defer<T>();
|
||||
return this.paneDeferred.promise;
|
||||
}
|
||||
|
||||
private resetFileInput(): void {
|
||||
this.stringInput("");
|
||||
}
|
||||
}
|
|
@ -0,0 +1,28 @@
|
|||
import { mount } from "enzyme";
|
||||
import React from "react";
|
||||
import Explorer from "../../Explorer";
|
||||
import { StringInputPane } from "./StringInputPane";
|
||||
const props = {
|
||||
explorer: new Explorer(),
|
||||
closePanel: (): void => undefined,
|
||||
errorMessage: "Could not create directory ",
|
||||
inProgressMessage: "Creating directory ",
|
||||
successMessage: "Created directory ",
|
||||
inputLabel: "Enter new directory name",
|
||||
paneTitle: "Create new directory",
|
||||
submitButtonLabel: "Create",
|
||||
defaultInput: "",
|
||||
onSubmit: jest.fn(),
|
||||
notebookFile: {
|
||||
name: "Untitled1123.ipynb",
|
||||
path: "notebooks/Untitled1123.ipynb",
|
||||
type: 0,
|
||||
timestamp: 1618452275805,
|
||||
},
|
||||
};
|
||||
describe("StringInput Pane", () => {
|
||||
it("should render Create new directory properly", () => {
|
||||
const wrapper = mount(<StringInputPane {...props} />);
|
||||
expect(wrapper).toMatchSnapshot();
|
||||
});
|
||||
});
|
|
@ -0,0 +1,122 @@
|
|||
import { TextField } from "office-ui-fabric-react";
|
||||
import React, { FormEvent, FunctionComponent, useState } from "react";
|
||||
import * as ViewModels from "../../../Contracts/ViewModels";
|
||||
import { logConsoleError, logConsoleInfo, logConsoleProgress } from "../../../Utils/NotificationConsoleUtils";
|
||||
import Explorer from "../../Explorer";
|
||||
import * as FileSystemUtil from "../../Notebook/FileSystemUtil";
|
||||
import { NotebookContentItem } from "../../Notebook/NotebookContentItem";
|
||||
import NotebookV2Tab from "../../Tabs/NotebookV2Tab";
|
||||
import {
|
||||
GenericRightPaneComponent,
|
||||
GenericRightPaneProps,
|
||||
} from "../GenericRightPaneComponent/GenericRightPaneComponent";
|
||||
|
||||
export interface StringInputPanelProps {
|
||||
explorer: Explorer;
|
||||
closePanel: () => void;
|
||||
errorMessage: string;
|
||||
inProgressMessage: string;
|
||||
successMessage: string;
|
||||
inputLabel: string;
|
||||
paneTitle: string;
|
||||
submitButtonLabel: string;
|
||||
defaultInput: string;
|
||||
onSubmit: (notebookFile: NotebookContentItem, input: string) => Promise<NotebookContentItem>;
|
||||
notebookFile: NotebookContentItem;
|
||||
}
|
||||
|
||||
export const StringInputPane: FunctionComponent<StringInputPanelProps> = ({
|
||||
explorer: container,
|
||||
closePanel,
|
||||
errorMessage,
|
||||
inProgressMessage,
|
||||
successMessage,
|
||||
inputLabel,
|
||||
paneTitle,
|
||||
submitButtonLabel,
|
||||
defaultInput,
|
||||
onSubmit,
|
||||
notebookFile,
|
||||
}: StringInputPanelProps): JSX.Element => {
|
||||
const [stringInput, setStringInput] = useState<string>(defaultInput);
|
||||
const [formErrors, setFormErrors] = useState<string>("");
|
||||
const [formErrorsDetails, setFormErrorsDetails] = useState<string>("");
|
||||
const [isExecuting, setIsExecuting] = useState<boolean>(false);
|
||||
|
||||
const submit = async (): Promise<void> => {
|
||||
if (stringInput === "") {
|
||||
const errorMessage = "Please " + inputLabel;
|
||||
setFormErrors(errorMessage);
|
||||
logConsoleError("Error while " + paneTitle + " : " + errorMessage);
|
||||
return;
|
||||
} else {
|
||||
setFormErrors("");
|
||||
setFormErrorsDetails("");
|
||||
}
|
||||
|
||||
const clearMessage = logConsoleProgress(`${inProgressMessage} ${stringInput}`);
|
||||
try {
|
||||
const newNotebookFile: NotebookContentItem = await onSubmit(notebookFile, stringInput);
|
||||
logConsoleInfo(`${successMessage}: ${stringInput}`);
|
||||
const originalPath = notebookFile.path;
|
||||
|
||||
const notebookTabs = container.tabsManager.getTabs(
|
||||
ViewModels.CollectionTabKind.NotebookV2,
|
||||
(tab: NotebookV2Tab) => tab.notebookPath && FileSystemUtil.isPathEqual(tab.notebookPath(), originalPath)
|
||||
);
|
||||
notebookTabs.forEach((tab) => {
|
||||
tab.tabTitle(newNotebookFile.name);
|
||||
tab.tabPath(newNotebookFile.path);
|
||||
(tab as NotebookV2Tab).notebookPath(newNotebookFile.path);
|
||||
});
|
||||
closePanel();
|
||||
} catch (reason) {
|
||||
let error = reason;
|
||||
if (reason instanceof Error) {
|
||||
error = reason.message;
|
||||
} else if (typeof reason === "object") {
|
||||
error = JSON.stringify(reason);
|
||||
}
|
||||
|
||||
// If it's an AjaxError (AjaxObservable), add more error
|
||||
if (reason?.response?.message) {
|
||||
error += `. ${reason.response.message}`;
|
||||
}
|
||||
|
||||
setFormErrors(errorMessage);
|
||||
setFormErrorsDetails(`${errorMessage}: ${error}`);
|
||||
logConsoleError(`${errorMessage} ${stringInput}: ${error}`);
|
||||
} finally {
|
||||
setIsExecuting(false);
|
||||
clearMessage();
|
||||
}
|
||||
};
|
||||
const genericPaneProps: GenericRightPaneProps = {
|
||||
container: container,
|
||||
formError: formErrors,
|
||||
formErrorDetail: formErrorsDetails,
|
||||
id: "stringInputPane",
|
||||
isExecuting: isExecuting,
|
||||
title: paneTitle,
|
||||
submitButtonText: submitButtonLabel,
|
||||
onClose: closePanel,
|
||||
onSubmit: submit,
|
||||
};
|
||||
return (
|
||||
<GenericRightPaneComponent {...genericPaneProps}>
|
||||
<div className="paneMainContent">
|
||||
<TextField
|
||||
label={inputLabel}
|
||||
name="collectionIdConfirmation"
|
||||
value={stringInput}
|
||||
autoFocus
|
||||
required
|
||||
onChange={(event: FormEvent<HTMLInputElement | HTMLTextAreaElement>, newValue?: string) =>
|
||||
setStringInput(newValue)
|
||||
}
|
||||
aria-label={inputLabel}
|
||||
/>
|
||||
</div>
|
||||
</GenericRightPaneComponent>
|
||||
);
|
||||
};
|
File diff suppressed because it is too large
Load Diff
|
@ -200,20 +200,6 @@ exports[`Upload Items Pane should render Default properly 1`] = `
|
|||
"userTableQuery": [Function],
|
||||
"visible": [Function],
|
||||
},
|
||||
StringInputPane {
|
||||
"container": [Circular],
|
||||
"firstFieldHasFocus": [Function],
|
||||
"formErrors": [Function],
|
||||
"formErrorsDetails": [Function],
|
||||
"id": "stringinputpane",
|
||||
"inputLabel": [Function],
|
||||
"isExecuting": [Function],
|
||||
"isTemplateReady": [Function],
|
||||
"stringInput": [Function],
|
||||
"submitButtonLabel": [Function],
|
||||
"title": [Function],
|
||||
"visible": [Function],
|
||||
},
|
||||
],
|
||||
"_refreshSparkEnabledStateForAccount": [Function],
|
||||
"_resetNotebookWorkspace": [Function],
|
||||
|
@ -524,20 +510,6 @@ exports[`Upload Items Pane should render Default properly 1`] = `
|
|||
"onResizeStop": [Function],
|
||||
"splitterId": "h_splitter1",
|
||||
},
|
||||
"stringInputPane": StringInputPane {
|
||||
"container": [Circular],
|
||||
"firstFieldHasFocus": [Function],
|
||||
"formErrors": [Function],
|
||||
"formErrorsDetails": [Function],
|
||||
"id": "stringinputpane",
|
||||
"inputLabel": [Function],
|
||||
"isExecuting": [Function],
|
||||
"isTemplateReady": [Function],
|
||||
"stringInput": [Function],
|
||||
"submitButtonLabel": [Function],
|
||||
"title": [Function],
|
||||
"visible": [Function],
|
||||
},
|
||||
"tabsManager": TabsManager {
|
||||
"activeTab": [Function],
|
||||
"openedTabs": [Function],
|
||||
|
|
|
@ -201,20 +201,6 @@ exports[`Delete Database Confirmation Pane submit() Should call delete database
|
|||
"userTableQuery": [Function],
|
||||
"visible": [Function],
|
||||
},
|
||||
StringInputPane {
|
||||
"container": [Circular],
|
||||
"firstFieldHasFocus": [Function],
|
||||
"formErrors": [Function],
|
||||
"formErrorsDetails": [Function],
|
||||
"id": "stringinputpane",
|
||||
"inputLabel": [Function],
|
||||
"isExecuting": [Function],
|
||||
"isTemplateReady": [Function],
|
||||
"stringInput": [Function],
|
||||
"submitButtonLabel": [Function],
|
||||
"title": [Function],
|
||||
"visible": [Function],
|
||||
},
|
||||
],
|
||||
"_refreshSparkEnabledStateForAccount": [Function],
|
||||
"_resetNotebookWorkspace": [Function],
|
||||
|
@ -529,20 +515,6 @@ exports[`Delete Database Confirmation Pane submit() Should call delete database
|
|||
"onResizeStop": [Function],
|
||||
"splitterId": "h_splitter1",
|
||||
},
|
||||
"stringInputPane": StringInputPane {
|
||||
"container": [Circular],
|
||||
"firstFieldHasFocus": [Function],
|
||||
"formErrors": [Function],
|
||||
"formErrorsDetails": [Function],
|
||||
"id": "stringinputpane",
|
||||
"inputLabel": [Function],
|
||||
"isExecuting": [Function],
|
||||
"isTemplateReady": [Function],
|
||||
"stringInput": [Function],
|
||||
"submitButtonLabel": [Function],
|
||||
"title": [Function],
|
||||
"visible": [Function],
|
||||
},
|
||||
"tabsManager": TabsManager {
|
||||
"activeTab": [Function],
|
||||
"openedTabs": [Function],
|
||||
|
|
|
@ -761,7 +761,7 @@ export class ResourceTreeAdapter implements ReactAdapter {
|
|||
{
|
||||
label: "Rename",
|
||||
iconSrc: NotebookIcon,
|
||||
onClick: () => this.container.renameNotebook(item).then(() => this.triggerRender()),
|
||||
onClick: () => this.container.renameNotebook(item),
|
||||
},
|
||||
{
|
||||
label: "New Directory",
|
||||
|
|
|
@ -232,7 +232,6 @@ const App: React.FunctionComponent = () => {
|
|||
<div data-bind='component: { name: "add-collection-pane", params: { data: addCollectionPane} }' />
|
||||
<div data-bind='component: { name: "graph-styling-pane", params: { data: graphStylingPane} }' />
|
||||
<div data-bind='component: { name: "cassandra-add-collection-pane", params: { data: cassandraAddCollectionPane} }' />
|
||||
<div data-bind='component: { name: "string-input-pane", params: { data: stringInputPane} }' />
|
||||
<KOCommentIfStart if="isGitHubPaneEnabled" />
|
||||
<div data-bind='component: { name: "github-repos-pane", params: { data: gitHubReposPane } }' />
|
||||
<KOCommentEnd />
|
||||
|
|
Loading…
Reference in New Issue