mirror of
https://github.com/Azure/cosmos-explorer.git
synced 2025-12-25 11:51:07 +00:00
Compare commits
5 Commits
resolve_De
...
fix_exlint
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e55e2b9fe3 | ||
|
|
0c1f6d2a80 | ||
|
|
55837db65b | ||
|
|
9f27cb95b9 | ||
|
|
271256bffb |
@@ -42,8 +42,6 @@ src/Explorer/Controls/Editor/EditorComponent.ts
|
||||
src/Explorer/Controls/JsonEditor/JsonEditorComponent.ts
|
||||
src/Explorer/DataSamples/ContainerSampleGenerator.test.ts
|
||||
src/Explorer/DataSamples/ContainerSampleGenerator.ts
|
||||
src/Explorer/DataSamples/DataSamplesUtil.test.ts
|
||||
src/Explorer/DataSamples/DataSamplesUtil.ts
|
||||
src/Explorer/Graph/GraphExplorerComponent/ArraysByKeyCache.test.ts
|
||||
src/Explorer/Graph/GraphExplorerComponent/ArraysByKeyCache.ts
|
||||
src/Explorer/Graph/GraphExplorerComponent/D3ForceGraph.test.ts
|
||||
@@ -54,8 +52,6 @@ src/Explorer/Graph/GraphExplorerComponent/GraphData.ts
|
||||
src/Explorer/Graph/GraphExplorerComponent/GremlinClient.test.ts
|
||||
src/Explorer/Graph/GraphExplorerComponent/GremlinClient.ts
|
||||
src/Explorer/Graph/GraphExplorerComponent/GremlinSimpleClient.test.ts
|
||||
src/Explorer/Graph/GraphExplorerComponent/GremlinSimpleClient.ts
|
||||
src/Explorer/Menus/ContextMenu.ts
|
||||
src/Explorer/MostRecentActivity/MostRecentActivity.ts
|
||||
src/Explorer/Notebook/NotebookClientV2.ts
|
||||
src/Explorer/Notebook/NotebookComponent/NotebookContentProvider.ts
|
||||
@@ -64,11 +60,8 @@ src/Explorer/Notebook/NotebookComponent/actions.ts
|
||||
src/Explorer/Notebook/NotebookComponent/epics.test.ts
|
||||
src/Explorer/Notebook/NotebookComponent/epics.ts
|
||||
src/Explorer/Notebook/NotebookComponent/loadTransform.ts
|
||||
src/Explorer/Notebook/NotebookComponent/reducers.ts
|
||||
src/Explorer/Notebook/NotebookComponent/store.ts
|
||||
src/Explorer/Notebook/NotebookComponent/types.ts
|
||||
src/Explorer/Notebook/NotebookContainerClient.ts
|
||||
src/Explorer/Notebook/NotebookContentClient.ts
|
||||
src/Explorer/Notebook/NotebookContentItem.ts
|
||||
src/Explorer/Notebook/NotebookUtil.ts
|
||||
src/Explorer/OpenActionsStubs.ts
|
||||
@@ -81,12 +74,8 @@ src/Explorer/Tables/DataTable/DataTableBindingManager.ts
|
||||
src/Explorer/Tables/DataTable/DataTableBuilder.ts
|
||||
src/Explorer/Tables/DataTable/DataTableContextMenu.ts
|
||||
src/Explorer/Tables/DataTable/DataTableOperationManager.ts
|
||||
# src/Explorer/Tables/DataTable/DataTableOperations.ts
|
||||
src/Explorer/Tables/DataTable/DataTableViewModel.ts
|
||||
# src/Explorer/Tables/DataTable/TableCommands.ts
|
||||
# src/Explorer/Tables/DataTable/TableEntityCache.ts
|
||||
src/Explorer/Tables/DataTable/TableEntityListViewModel.ts
|
||||
# src/Explorer/Tables/Entities.ts
|
||||
src/Explorer/Tables/QueryBuilder/CustomTimestampHelper.ts
|
||||
src/Explorer/Tables/TableDataClient.ts
|
||||
src/Explorer/Tables/TableEntityProcessor.ts
|
||||
@@ -134,20 +123,13 @@ src/Explorer/Controls/Notebook/NotebookTerminalComponent.tsx
|
||||
src/Explorer/Controls/NotebookViewer/NotebookViewerComponent.tsx
|
||||
src/Explorer/Controls/TreeComponent/TreeComponent.tsx
|
||||
src/Explorer/Graph/GraphExplorerComponent/GraphExplorer.test.tsx
|
||||
; src/Explorer/Graph/GraphExplorerComponent/GraphExplorer.tsx
|
||||
src/Explorer/Graph/GraphExplorerComponent/GraphVizComponent.tsx
|
||||
src/Explorer/Graph/GraphExplorerComponent/LeftPaneComponent.tsx
|
||||
src/Explorer/Graph/GraphExplorerComponent/MiddlePaneComponent.tsx
|
||||
src/Explorer/Graph/GraphExplorerComponent/NodePropertiesComponent.test.tsx
|
||||
src/Explorer/Graph/GraphExplorerComponent/NodePropertiesComponent.tsx
|
||||
src/Explorer/Graph/GraphExplorerComponent/ReadOnlyNodePropertiesComponent.test.tsx
|
||||
src/Explorer/Graph/GraphExplorerComponent/ReadOnlyNodePropertiesComponent.tsx
|
||||
src/Explorer/Menus/CommandBar/CommandBarUtil.tsx
|
||||
src/Explorer/Notebook/NotebookComponent/NotebookComponentAdapter.tsx
|
||||
; src/Explorer/Notebook/NotebookComponent/NotebookComponentBootstrapper.tsx
|
||||
src/Explorer/Notebook/NotebookComponent/VirtualCommandBarComponent.tsx
|
||||
src/Explorer/Notebook/NotebookComponent/contents/index.tsx
|
||||
; src/Explorer/Notebook/NotebookRenderer/NotebookReadOnlyRenderer.tsx
|
||||
src/Explorer/Notebook/NotebookRenderer/NotebookRenderer.tsx
|
||||
src/Explorer/Notebook/NotebookRenderer/decorators/draggable/index.tsx
|
||||
src/Explorer/Notebook/NotebookRenderer/decorators/hijack-scroll/index.tsx
|
||||
|
||||
@@ -19,7 +19,7 @@ describe("DataSampleUtils", () => {
|
||||
const explorer = {} as Explorer;
|
||||
useDatabases.getState().addDatabases([database]);
|
||||
const dataSamplesUtil = new DataSamplesUtil(explorer);
|
||||
|
||||
//eslint-disable-next-line
|
||||
const fakeGenerator = sinon.createStubInstance<ContainerSampleGenerator>(ContainerSampleGenerator as any);
|
||||
fakeGenerator.getCollectionId.returns(sampleCollectionId);
|
||||
fakeGenerator.getDatabaseId.returns(sampleDatabaseId);
|
||||
|
||||
@@ -18,6 +18,7 @@ export interface GremlinSimpleClientParameters {
|
||||
|
||||
export interface Result {
|
||||
requestId: string; // Can be null
|
||||
//eslint-disable-next-line
|
||||
data: any;
|
||||
requestCharge: number; // RU cost
|
||||
}
|
||||
@@ -30,6 +31,7 @@ export interface GremlinRequestMessage {
|
||||
args:
|
||||
| {
|
||||
gremlin: string;
|
||||
//eslint-disable-next-line
|
||||
bindings: {};
|
||||
language: string;
|
||||
}
|
||||
@@ -54,6 +56,7 @@ export interface GremlinResponseMessage {
|
||||
message: string;
|
||||
};
|
||||
result: {
|
||||
//eslint-disable-next-line
|
||||
data: any;
|
||||
};
|
||||
}
|
||||
@@ -74,7 +77,7 @@ export class GremlinSimpleClient {
|
||||
this.requestsToSend = {};
|
||||
}
|
||||
|
||||
public connect() {
|
||||
public connect(): void {
|
||||
if (this.ws) {
|
||||
if (this.ws.readyState === WebSocket.CONNECTING) {
|
||||
// Wait until it connects to execute all requests
|
||||
@@ -106,9 +109,10 @@ export class GremlinSimpleClient {
|
||||
return new WebSocket(endpoint);
|
||||
}
|
||||
|
||||
public close() {
|
||||
public close(): void {
|
||||
if (this.ws && this.ws.readyState !== WebSocket.CLOSING && this.ws.readyState !== WebSocket.CLOSED) {
|
||||
const msg = `Disconnecting from ${this.params.endpoint} as ${this.params.user}`;
|
||||
//eslint-disable-next-line
|
||||
console.log(msg);
|
||||
if (this.params.infoCallback) {
|
||||
this.params.infoCallback(msg);
|
||||
@@ -143,7 +147,7 @@ export class GremlinSimpleClient {
|
||||
}
|
||||
}
|
||||
|
||||
public onMessage(msg: MessageEvent) {
|
||||
public onMessage(msg: MessageEvent): void {
|
||||
if (!msg) {
|
||||
if (this.params.failureCallback) {
|
||||
this.params.failureCallback(null, "onMessage called with no message");
|
||||
@@ -194,8 +198,10 @@ export class GremlinSimpleClient {
|
||||
}
|
||||
break;
|
||||
case 407: // Request authentication
|
||||
const challengeResponse = this.buildChallengeResponse(this.pendingRequests[requestId]);
|
||||
this.sendGremlinMessage(challengeResponse);
|
||||
{
|
||||
const challengeResponse = this.buildChallengeResponse(this.pendingRequests[requestId]);
|
||||
this.sendGremlinMessage(challengeResponse);
|
||||
}
|
||||
break;
|
||||
case 401: // Unauthorized
|
||||
delete this.pendingRequests[requestId];
|
||||
@@ -267,7 +273,7 @@ export class GremlinSimpleClient {
|
||||
}
|
||||
|
||||
public buildChallengeResponse(request: GremlinRequestMessage): GremlinRequestMessage {
|
||||
var args = {
|
||||
const args = {
|
||||
SASL: GremlinSimpleClient.utf8ToB64("\0" + this.params.user + "\0" + this.params.password),
|
||||
};
|
||||
return {
|
||||
@@ -278,9 +284,9 @@ export class GremlinSimpleClient {
|
||||
};
|
||||
}
|
||||
|
||||
public static utf8ToB64(utf8Str: string) {
|
||||
public static utf8ToB64(utf8Str: string): string {
|
||||
return btoa(
|
||||
encodeURIComponent(utf8Str).replace(/%([0-9A-F]{2})/g, function (match, p1) {
|
||||
encodeURIComponent(utf8Str).replace(/%([0-9A-F]{2})/g, (match, p1) => {
|
||||
return String.fromCharCode(parseInt(p1, 16));
|
||||
})
|
||||
);
|
||||
@@ -291,12 +297,13 @@ export class GremlinSimpleClient {
|
||||
* mimeLength + mimeType + serialized message
|
||||
* @param requestMessage
|
||||
*/
|
||||
//eslint-disable-next-line
|
||||
public static buildGremlinMessage(requestMessage: {}): Uint8Array {
|
||||
const mimeType = "application/json";
|
||||
let serializedMessage = mimeType + JSON.stringify(requestMessage);
|
||||
const serializedMessage = mimeType + JSON.stringify(requestMessage);
|
||||
const encodedMessage = new TextEncoder().encode(serializedMessage);
|
||||
|
||||
let binaryMessage = new Uint8Array(1 + encodedMessage.length);
|
||||
const binaryMessage = new Uint8Array(1 + encodedMessage.length);
|
||||
binaryMessage[0] = mimeType.length;
|
||||
|
||||
for (let i = 0; i < encodedMessage.length; i++) {
|
||||
@@ -305,19 +312,19 @@ export class GremlinSimpleClient {
|
||||
return binaryMessage;
|
||||
}
|
||||
|
||||
private onOpen(event: any) {
|
||||
private onOpen() {
|
||||
this.executeRequestsToSend();
|
||||
}
|
||||
|
||||
private executeRequestsToSend() {
|
||||
for (let requestId in this.requestsToSend) {
|
||||
for (const requestId in this.requestsToSend) {
|
||||
const request = this.requestsToSend[requestId];
|
||||
this.sendGremlinMessage(request);
|
||||
this.pendingRequests[request.requestId] = request;
|
||||
delete this.requestsToSend[request.requestId];
|
||||
}
|
||||
}
|
||||
|
||||
//eslint-disable-next-line
|
||||
private onError(err: any) {
|
||||
if (this.params.failureCallback) {
|
||||
this.params.failureCallback(null, err);
|
||||
@@ -339,9 +346,9 @@ export class GremlinSimpleClient {
|
||||
* RFC4122 version 4 compliant UUID
|
||||
*/
|
||||
private static uuidv4() {
|
||||
return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, function (c) {
|
||||
var r = (Math.random() * 16) | 0,
|
||||
v = c == "x" ? r : (r & 0x3) | 0x8;
|
||||
return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, (c) => {
|
||||
const r = (Math.random() * 16) | 0,
|
||||
v = c === "x" ? r : (r & 0x3) | 0x8;
|
||||
return v.toString(16);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -58,7 +58,7 @@ export class LeftPaneComponent extends React.Component<LeftPaneComponentProps> {
|
||||
className={className}
|
||||
as="tr"
|
||||
aria-label={node.caption}
|
||||
onActivated={(e) => this.props.onRootNodeSelected(node.id)}
|
||||
onActivated={() => this.props.onRootNodeSelected(node.id)}
|
||||
key={node.id}
|
||||
>
|
||||
<td className="resultItem">
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import React from "react";
|
||||
import { mount, ReactWrapper } from "enzyme";
|
||||
import * as Q from "q";
|
||||
import { NodePropertiesComponent, NodePropertiesComponentProps, Mode } from "./NodePropertiesComponent";
|
||||
import { GraphHighlightedNodeData, EditedProperties, EditedEdges, PossibleVertex } from "./GraphExplorer";
|
||||
import React from "react";
|
||||
import { GraphHighlightedNodeData, PossibleVertex } from "./GraphExplorer";
|
||||
import { Mode, NodePropertiesComponent, NodePropertiesComponentProps } from "./NodePropertiesComponent";
|
||||
|
||||
describe("Property pane", () => {
|
||||
const title = "My Title";
|
||||
@@ -37,17 +37,18 @@ describe("Property pane", () => {
|
||||
return {
|
||||
expandedTitle: title,
|
||||
isCollapsed: false,
|
||||
onCollapsedChanged: (newValue: boolean): void => {},
|
||||
onCollapsedChanged: jest.fn(),
|
||||
node: highlightedNode,
|
||||
getPkIdFromNodeData: (v: GraphHighlightedNodeData): string => null,
|
||||
collectionPartitionKeyProperty: null,
|
||||
updateVertexProperties: (editedProperties: EditedProperties): Q.Promise<void> => Q.resolve(),
|
||||
selectNode: (id: string): void => {},
|
||||
updatePossibleVertices: (): Q.Promise<PossibleVertex[]> => Q.resolve(null),
|
||||
possibleEdgeLabels: null,
|
||||
editGraphEdges: (editedEdges: EditedEdges): Q.Promise<any> => Q.resolve(),
|
||||
deleteHighlightedNode: (): void => {},
|
||||
onModeChanged: (newMode: Mode): void => {},
|
||||
getPkIdFromNodeData: (): string => undefined,
|
||||
collectionPartitionKeyProperty: undefined,
|
||||
updateVertexProperties: (): Q.Promise<void> => Q.resolve(),
|
||||
selectNode: jest.fn(),
|
||||
updatePossibleVertices: (): Q.Promise<PossibleVertex[]> => Q.resolve(undefined),
|
||||
possibleEdgeLabels: undefined,
|
||||
//eslint-disable-next-line
|
||||
editGraphEdges: (): Q.Promise<any> => Q.resolve(),
|
||||
deleteHighlightedNode: jest.fn(),
|
||||
onModeChanged: jest.fn(),
|
||||
viewMode: Mode.READONLY_PROP,
|
||||
};
|
||||
};
|
||||
|
||||
@@ -72,7 +72,7 @@ export class NodePropertiesComponent extends React.Component<
|
||||
super(props);
|
||||
this.state = {
|
||||
editedProperties: {
|
||||
pkId: null,
|
||||
pkId: undefined,
|
||||
readOnlyProperties: [],
|
||||
existingProperties: [],
|
||||
addedProperties: [],
|
||||
@@ -98,15 +98,12 @@ export class NodePropertiesComponent extends React.Component<
|
||||
};
|
||||
}
|
||||
|
||||
public static getDerivedStateFromProps(
|
||||
props: NodePropertiesComponentProps,
|
||||
state: NodePropertiesComponentState
|
||||
): Partial<NodePropertiesComponentState> {
|
||||
public static getDerivedStateFromProps(props: NodePropertiesComponentProps): Partial<NodePropertiesComponentState> {
|
||||
if (props.viewMode !== Mode.READONLY_PROP) {
|
||||
return { isDeleteConfirm: false };
|
||||
}
|
||||
|
||||
return null;
|
||||
return undefined;
|
||||
}
|
||||
|
||||
public render(): JSX.Element {
|
||||
@@ -138,10 +135,10 @@ export class NodePropertiesComponent extends React.Component<
|
||||
* @param value
|
||||
*/
|
||||
private static getTypeOption(value: any): ViewModels.InputPropertyValueTypeString {
|
||||
if (value == null) {
|
||||
if (value === undefined) {
|
||||
return "null";
|
||||
}
|
||||
let type = typeof value;
|
||||
const type = typeof value;
|
||||
switch (type) {
|
||||
case "number":
|
||||
case "boolean":
|
||||
@@ -172,10 +169,9 @@ export class NodePropertiesComponent extends React.Component<
|
||||
];
|
||||
|
||||
const existingProps: ViewModels.InputProperty[] = [];
|
||||
|
||||
if (this.props.node.hasOwnProperty("properties")) {
|
||||
const hProps = this.props.node["properties"];
|
||||
for (let p in hProps) {
|
||||
for (const p in hProps) {
|
||||
const propValues = hProps[p];
|
||||
(p === partitionKeyProperty ? readOnlyProps : existingProps).push({
|
||||
key: p,
|
||||
@@ -437,7 +433,7 @@ export class NodePropertiesComponent extends React.Component<
|
||||
</div>
|
||||
);
|
||||
} else {
|
||||
return null;
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -307,18 +307,11 @@ function createOpenSynapseLinkDialogButton(container: Explorer): CommandButtonCo
|
||||
|
||||
function createNewDatabase(container: Explorer): CommandButtonComponentProps {
|
||||
const label = "New " + getDatabaseName();
|
||||
const newDatabaseButton = document.activeElement as HTMLElement;
|
||||
|
||||
return {
|
||||
iconSrc: AddDatabaseIcon,
|
||||
iconAlt: label,
|
||||
onCommandClick: () =>
|
||||
useSidePanel
|
||||
.getState()
|
||||
.openSidePanel(
|
||||
"New " + getDatabaseName(),
|
||||
<AddDatabasePanel explorer={container} buttonElement={newDatabaseButton} />
|
||||
),
|
||||
useSidePanel.getState().openSidePanel("New " + getDatabaseName(), <AddDatabasePanel explorer={container} />),
|
||||
commandButtonLabel: label,
|
||||
ariaLabel: label,
|
||||
hasPopup: true,
|
||||
|
||||
@@ -50,6 +50,7 @@ export const coreReducer = (state: CoreRecord, action: Action) => {
|
||||
.setIn(path.concat("language"), kernelspecs.language);
|
||||
}
|
||||
default:
|
||||
//eslint-disable-next-line
|
||||
return nteractReducers.core(state as any, action as any);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -228,11 +228,12 @@ export class NotebookContentClient {
|
||||
|
||||
public async readFileContent(filePath: string): Promise<string> {
|
||||
const xhr = await this.contentProvider.get(this.getServerConfig(), filePath, { content: 1 }).toPromise();
|
||||
//eslint-disable-next-line
|
||||
const content = (xhr.response as any).content;
|
||||
if (!content) {
|
||||
throw new Error("No content read");
|
||||
}
|
||||
|
||||
//eslint-disable-next-line
|
||||
const format = (xhr.response as any).format;
|
||||
switch (format) {
|
||||
case "text":
|
||||
|
||||
@@ -4,6 +4,8 @@ import * as React from "react";
|
||||
import { useFullScreenURLs } from "../hooks/useFullScreenURLs";
|
||||
|
||||
export const OpenFullScreen: React.FunctionComponent = () => {
|
||||
const [isReadUrlCopy, setIsReadUrlCopy] = React.useState<boolean>(false);
|
||||
const [isReadWriteUrlCopy, setIsReadWriteUrlCopy] = React.useState<boolean>(false);
|
||||
const result = useFullScreenURLs();
|
||||
if (!result) {
|
||||
return <Spinner label="Generating URLs..." ariaLive="assertive" labelPosition="right" />;
|
||||
@@ -25,8 +27,9 @@ export const OpenFullScreen: React.FunctionComponent = () => {
|
||||
<DefaultButton
|
||||
onClick={() => {
|
||||
copyToClipboard(readWriteUrl);
|
||||
setIsReadWriteUrlCopy(true);
|
||||
}}
|
||||
text="Copy"
|
||||
text={isReadWriteUrlCopy ? "Copied" : "Copy"}
|
||||
iconProps={{ iconName: "Copy" }}
|
||||
/>
|
||||
<PrimaryButton
|
||||
@@ -41,9 +44,10 @@ export const OpenFullScreen: React.FunctionComponent = () => {
|
||||
<Stack horizontal tokens={{ childrenGap: 10 }}>
|
||||
<DefaultButton
|
||||
onClick={() => {
|
||||
setIsReadUrlCopy(true);
|
||||
copyToClipboard(readUrl);
|
||||
}}
|
||||
text="Copy"
|
||||
text={isReadUrlCopy ? "Copied" : "Copy"}
|
||||
iconProps={{ iconName: "Copy" }}
|
||||
/>
|
||||
<PrimaryButton
|
||||
|
||||
@@ -23,12 +23,10 @@ import { RightPaneForm, RightPaneFormProps } from "../RightPaneForm/RightPaneFor
|
||||
|
||||
export interface AddDatabasePaneProps {
|
||||
explorer: Explorer;
|
||||
buttonElement?: HTMLElement;
|
||||
}
|
||||
|
||||
export const AddDatabasePanel: FunctionComponent<AddDatabasePaneProps> = ({
|
||||
explorer: container,
|
||||
buttonElement,
|
||||
}: AddDatabasePaneProps) => {
|
||||
const closeSidePanel = useSidePanel((state) => state.closeSidePanel);
|
||||
let throughput: number;
|
||||
@@ -79,7 +77,6 @@ export const AddDatabasePanel: FunctionComponent<AddDatabasePaneProps> = ({
|
||||
dataExplorerArea: Constants.Areas.ContextualPane,
|
||||
};
|
||||
TelemetryProcessor.trace(Action.CreateDatabase, ActionModifiers.Open, addDatabasePaneOpenMessage);
|
||||
buttonElement.focus();
|
||||
}, []);
|
||||
|
||||
const onSubmit = () => {
|
||||
|
||||
@@ -307,23 +307,16 @@ export class SplashScreen extends React.Component<SplashScreenProps> {
|
||||
iconSrc: AddDatabaseIcon,
|
||||
title: "New " + getDatabaseName(),
|
||||
description: undefined,
|
||||
onClick: () => this.openAddDatabasePanel(),
|
||||
onClick: () =>
|
||||
useSidePanel
|
||||
.getState()
|
||||
.openSidePanel("New " + getDatabaseName(), <AddDatabasePanel explorer={this.container} />),
|
||||
});
|
||||
}
|
||||
|
||||
return items;
|
||||
}
|
||||
|
||||
private openAddDatabasePanel() {
|
||||
const newDatabaseButton = document.activeElement as HTMLElement;
|
||||
useSidePanel
|
||||
.getState()
|
||||
.openSidePanel(
|
||||
"New " + getDatabaseName(),
|
||||
<AddDatabasePanel explorer={this.container} buttonElement={newDatabaseButton} />
|
||||
);
|
||||
}
|
||||
|
||||
private decorateOpenCollectionActivity({ databaseId, collectionId }: MostRecentActivity.OpenCollectionItem) {
|
||||
return {
|
||||
iconSrc: NotebookIcon,
|
||||
|
||||
@@ -202,14 +202,21 @@ export class CassandraAPIDataClient extends TableDataClient {
|
||||
|
||||
let updateQuery = `UPDATE ${collection.databaseId}.${collection.id()}`;
|
||||
let isPropertyUpdated = false;
|
||||
let isFirstPropertyToUpdate = true;
|
||||
for (let property in newEntity) {
|
||||
if (
|
||||
!originalDocument[property] ||
|
||||
newEntity[property]._.toString() !== originalDocument[property]._.toString()
|
||||
) {
|
||||
updateQuery += this.isStringType(newEntity[property].$)
|
||||
? ` SET ${property} = '${newEntity[property]._}',`
|
||||
: ` SET ${property} = ${newEntity[property]._},`;
|
||||
let propertyQuerySegment = this.isStringType(newEntity[property].$)
|
||||
? `${property} = '${newEntity[property]._}',`
|
||||
: `${property} = ${newEntity[property]._},`;
|
||||
// Only add the "SET" keyword once
|
||||
if (isFirstPropertyToUpdate) {
|
||||
propertyQuerySegment = " SET " + propertyQuerySegment;
|
||||
isFirstPropertyToUpdate = false;
|
||||
}
|
||||
updateQuery += propertyQuerySegment;
|
||||
isPropertyUpdated = true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -118,7 +118,7 @@ export default class NotebookTabV2 extends NotebookTabBase {
|
||||
const saveButtonChildren = [];
|
||||
if (this.container.notebookManager?.gitHubOAuthService.isLoggedIn()) {
|
||||
saveButtonChildren.push({
|
||||
iconName: "Copy",
|
||||
iconName: copyToLabel,
|
||||
onCommandClick: () => this.copyNotebook(),
|
||||
commandButtonLabel: copyToLabel,
|
||||
hasPopup: false,
|
||||
|
||||
Reference in New Issue
Block a user