mirror of
https://github.com/Azure/cosmos-explorer.git
synced 2025-12-20 01:11:25 +00:00
Global Secondary Index (#2071)
* add Materialized Views feature flag * fetch MV properties from RP API and capture them in our data models * AddMaterializedViewPanel * undefined check * subpartition keys * Partition Key, Throughput, Unique Keys * All views associated with a container (#2063) and Materialized View Target Container (#2065) Identified Source container and Target container Created tabs in Scale and Settings respectively Changed the Icon of target container * Add MV Panel * format * format * styling * add tests * tests * test files (#2074) Co-authored-by: nishthaAhujaa * fix type error * fix tests * merge conflict * Panel Integration (#2075) * integrated panel * edited header text --------- Co-authored-by: nishthaAhujaa <nishtha17354@iiittd.ac.in> Co-authored-by: Asier Isayas <aisayas@microsoft.com> * updated tests (#2077) Co-authored-by: nishthaAhujaa * fix tests * update treeNodeUtil test snap * update settings component test snap * fixed source container in global "New Materialized View" * source container check (#2079) Co-authored-by: nishthaAhujaa * renamed Materialized Views to Global Secondary Index * more renaming * fix import * fix typo * disable materialized views for Fabric * updated input validation --------- Co-authored-by: Asier Isayas <aisayas@microsoft.com> Co-authored-by: Nishtha Ahuja <45535788+nishthaAhujaa@users.noreply.github.com> Co-authored-by: nishthaAhujaa <nishtha17354@iiittd.ac.in>
This commit is contained in:
@@ -58,6 +58,8 @@ export default class Collection implements ViewModels.Collection {
|
||||
public uniqueKeyPolicy: DataModels.UniqueKeyPolicy;
|
||||
public usageSizeInKB: ko.Observable<number>;
|
||||
public computedProperties: ko.Observable<DataModels.ComputedProperties>;
|
||||
public materializedViews: ko.Observable<DataModels.MaterializedView[]>;
|
||||
public materializedViewDefinition: ko.Observable<DataModels.MaterializedViewDefinition>;
|
||||
|
||||
public offer: ko.Observable<DataModels.Offer>;
|
||||
public conflictResolutionPolicy: ko.Observable<DataModels.ConflictResolutionPolicy>;
|
||||
@@ -124,6 +126,8 @@ export default class Collection implements ViewModels.Collection {
|
||||
this.requestSchema = data.requestSchema;
|
||||
this.geospatialConfig = ko.observable(data.geospatialConfig);
|
||||
this.computedProperties = ko.observable(data.computedProperties);
|
||||
this.materializedViews = ko.observable(data.materializedViews);
|
||||
this.materializedViewDefinition = ko.observable(data.materializedViewDefinition);
|
||||
|
||||
this.partitionKeyPropertyHeaders = this.partitionKey?.paths;
|
||||
this.partitionKeyProperties = this.partitionKeyPropertyHeaders?.map((partitionKeyPropertyHeader, i) => {
|
||||
|
||||
@@ -19,7 +19,7 @@ import { logConsoleError } from "../../Utils/NotificationConsoleUtils";
|
||||
import { useSidePanel } from "../../hooks/useSidePanel";
|
||||
import { useTabs } from "../../hooks/useTabs";
|
||||
import Explorer from "../Explorer";
|
||||
import { AddCollectionPanel } from "../Panes/AddCollectionPanel";
|
||||
import { AddCollectionPanel } from "../Panes/AddCollectionPanel/AddCollectionPanel";
|
||||
import { DatabaseSettingsTabV2 } from "../Tabs/SettingsTabV2";
|
||||
import { useDatabases } from "../useDatabases";
|
||||
import { useSelectedNode } from "../useSelectedNode";
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { Tree, TreeItemValue, TreeOpenChangeData, TreeOpenChangeEvent } from "@fluentui/react-components";
|
||||
import { Home16Regular } from "@fluentui/react-icons";
|
||||
import { AuthType } from "AuthType";
|
||||
import { Collection } from "Contracts/ViewModels";
|
||||
import { useTreeStyles } from "Explorer/Controls/TreeComponent/Styles";
|
||||
import { TreeNode, TreeNodeComponent } from "Explorer/Controls/TreeComponent/TreeNodeComponent";
|
||||
import {
|
||||
@@ -60,7 +61,7 @@ export const ResourceTree: React.FC<ResourceTreeProps> = ({ explorer }: Resource
|
||||
|
||||
const databaseTreeNodes = useMemo(() => {
|
||||
return userContext.authType === AuthType.ResourceToken
|
||||
? createResourceTokenTreeNodes(resourceTokenCollection)
|
||||
? createResourceTokenTreeNodes(resourceTokenCollection as Collection)
|
||||
: createDatabaseTreeNodes(explorer, isNotebookEnabled, databases, refreshActiveTab);
|
||||
}, [resourceTokenCollection, databases, isNotebookEnabled, refreshActiveTab]);
|
||||
|
||||
|
||||
@@ -30,7 +30,7 @@ exports[`createDatabaseTreeNodes generates the correct tree structure for the Ca
|
||||
"styleClass": "deleteCollectionMenuItem",
|
||||
},
|
||||
],
|
||||
"iconSrc": <DocumentMultipleRegular
|
||||
"iconSrc": <EyeRegular
|
||||
fontSize={16}
|
||||
/>,
|
||||
"isExpanded": true,
|
||||
@@ -72,7 +72,7 @@ exports[`createDatabaseTreeNodes generates the correct tree structure for the Ca
|
||||
"styleClass": "deleteCollectionMenuItem",
|
||||
},
|
||||
],
|
||||
"iconSrc": <DocumentMultipleRegular
|
||||
"iconSrc": <EyeRegular
|
||||
fontSize={16}
|
||||
/>,
|
||||
"isExpanded": true,
|
||||
@@ -145,7 +145,7 @@ exports[`createDatabaseTreeNodes generates the correct tree structure for the Ca
|
||||
"styleClass": "deleteCollectionMenuItem",
|
||||
},
|
||||
],
|
||||
"iconSrc": <DocumentMultipleRegular
|
||||
"iconSrc": <EyeRegular
|
||||
fontSize={16}
|
||||
/>,
|
||||
"isExpanded": true,
|
||||
@@ -264,7 +264,7 @@ exports[`createDatabaseTreeNodes generates the correct tree structure for the Ca
|
||||
"styleClass": "deleteCollectionMenuItem",
|
||||
},
|
||||
],
|
||||
"iconSrc": <DocumentMultipleRegular
|
||||
"iconSrc": <EyeRegular
|
||||
fontSize={16}
|
||||
/>,
|
||||
"isExpanded": true,
|
||||
@@ -369,7 +369,7 @@ exports[`createDatabaseTreeNodes generates the correct tree structure for the Mo
|
||||
"styleClass": "deleteCollectionMenuItem",
|
||||
},
|
||||
],
|
||||
"iconSrc": <DocumentMultipleRegular
|
||||
"iconSrc": <EyeRegular
|
||||
fontSize={16}
|
||||
/>,
|
||||
"isExpanded": true,
|
||||
@@ -442,7 +442,7 @@ exports[`createDatabaseTreeNodes generates the correct tree structure for the Mo
|
||||
"styleClass": "deleteCollectionMenuItem",
|
||||
},
|
||||
],
|
||||
"iconSrc": <DocumentMultipleRegular
|
||||
"iconSrc": <EyeRegular
|
||||
fontSize={16}
|
||||
/>,
|
||||
"isExpanded": true,
|
||||
@@ -546,7 +546,7 @@ exports[`createDatabaseTreeNodes generates the correct tree structure for the Mo
|
||||
"styleClass": "deleteCollectionMenuItem",
|
||||
},
|
||||
],
|
||||
"iconSrc": <DocumentMultipleRegular
|
||||
"iconSrc": <EyeRegular
|
||||
fontSize={16}
|
||||
/>,
|
||||
"isExpanded": true,
|
||||
@@ -696,7 +696,7 @@ exports[`createDatabaseTreeNodes generates the correct tree structure for the Mo
|
||||
"styleClass": "deleteCollectionMenuItem",
|
||||
},
|
||||
],
|
||||
"iconSrc": <DocumentMultipleRegular
|
||||
"iconSrc": <EyeRegular
|
||||
fontSize={16}
|
||||
/>,
|
||||
"isExpanded": true,
|
||||
@@ -760,7 +760,7 @@ exports[`createDatabaseTreeNodes generates the correct tree structure for the SQ
|
||||
"styleClass": "deleteCollectionMenuItem",
|
||||
},
|
||||
],
|
||||
"iconSrc": <DocumentMultipleRegular
|
||||
"iconSrc": <EyeRegular
|
||||
fontSize={16}
|
||||
/>,
|
||||
"isExpanded": true,
|
||||
@@ -787,7 +787,7 @@ exports[`createDatabaseTreeNodes generates the correct tree structure for the SQ
|
||||
"styleClass": "deleteCollectionMenuItem",
|
||||
},
|
||||
],
|
||||
"iconSrc": <DocumentMultipleRegular
|
||||
"iconSrc": <EyeRegular
|
||||
fontSize={16}
|
||||
/>,
|
||||
"isExpanded": true,
|
||||
@@ -841,7 +841,7 @@ exports[`createDatabaseTreeNodes generates the correct tree structure for the SQ
|
||||
"styleClass": "deleteCollectionMenuItem",
|
||||
},
|
||||
],
|
||||
"iconSrc": <DocumentMultipleRegular
|
||||
"iconSrc": <EyeRegular
|
||||
fontSize={16}
|
||||
/>,
|
||||
"isExpanded": true,
|
||||
@@ -895,7 +895,7 @@ exports[`createDatabaseTreeNodes generates the correct tree structure for the SQ
|
||||
"styleClass": "deleteCollectionMenuItem",
|
||||
},
|
||||
],
|
||||
"iconSrc": <DocumentMultipleRegular
|
||||
"iconSrc": <EyeRegular
|
||||
fontSize={16}
|
||||
/>,
|
||||
"isExpanded": true,
|
||||
@@ -953,7 +953,7 @@ exports[`createDatabaseTreeNodes generates the correct tree structure for the SQ
|
||||
"onClick": [Function],
|
||||
},
|
||||
],
|
||||
"iconSrc": <DocumentMultipleRegular
|
||||
"iconSrc": <EyeRegular
|
||||
fontSize={16}
|
||||
/>,
|
||||
"isExpanded": true,
|
||||
@@ -974,7 +974,7 @@ exports[`createDatabaseTreeNodes generates the correct tree structure for the SQ
|
||||
"onClick": [Function],
|
||||
},
|
||||
],
|
||||
"iconSrc": <DocumentMultipleRegular
|
||||
"iconSrc": <EyeRegular
|
||||
fontSize={16}
|
||||
/>,
|
||||
"isExpanded": true,
|
||||
@@ -1010,7 +1010,7 @@ exports[`createDatabaseTreeNodes generates the correct tree structure for the SQ
|
||||
"onClick": [Function],
|
||||
},
|
||||
],
|
||||
"iconSrc": <DocumentMultipleRegular
|
||||
"iconSrc": <EyeRegular
|
||||
fontSize={16}
|
||||
/>,
|
||||
"isExpanded": true,
|
||||
@@ -1046,7 +1046,7 @@ exports[`createDatabaseTreeNodes generates the correct tree structure for the SQ
|
||||
"onClick": [Function],
|
||||
},
|
||||
],
|
||||
"iconSrc": <DocumentMultipleRegular
|
||||
"iconSrc": <EyeRegular
|
||||
fontSize={16}
|
||||
/>,
|
||||
"isExpanded": true,
|
||||
@@ -1208,7 +1208,7 @@ exports[`createDatabaseTreeNodes generates the correct tree structure for the SQ
|
||||
"styleClass": "deleteCollectionMenuItem",
|
||||
},
|
||||
],
|
||||
"iconSrc": <DocumentMultipleRegular
|
||||
"iconSrc": <EyeRegular
|
||||
fontSize={16}
|
||||
/>,
|
||||
"isExpanded": true,
|
||||
@@ -1311,7 +1311,7 @@ exports[`createDatabaseTreeNodes generates the correct tree structure for the SQ
|
||||
"styleClass": "deleteCollectionMenuItem",
|
||||
},
|
||||
],
|
||||
"iconSrc": <DocumentMultipleRegular
|
||||
"iconSrc": <EyeRegular
|
||||
fontSize={16}
|
||||
/>,
|
||||
"isExpanded": true,
|
||||
@@ -1445,7 +1445,7 @@ exports[`createDatabaseTreeNodes generates the correct tree structure for the SQ
|
||||
"styleClass": "deleteCollectionMenuItem",
|
||||
},
|
||||
],
|
||||
"iconSrc": <DocumentMultipleRegular
|
||||
"iconSrc": <EyeRegular
|
||||
fontSize={16}
|
||||
/>,
|
||||
"isExpanded": true,
|
||||
@@ -1625,7 +1625,7 @@ exports[`createDatabaseTreeNodes generates the correct tree structure for the SQ
|
||||
"styleClass": "deleteCollectionMenuItem",
|
||||
},
|
||||
],
|
||||
"iconSrc": <DocumentMultipleRegular
|
||||
"iconSrc": <EyeRegular
|
||||
fontSize={16}
|
||||
/>,
|
||||
"isExpanded": true,
|
||||
@@ -1799,7 +1799,7 @@ exports[`createDatabaseTreeNodes using NoSQL API on Hosted Platform creates expe
|
||||
"styleClass": "deleteCollectionMenuItem",
|
||||
},
|
||||
],
|
||||
"iconSrc": <DocumentMultipleRegular
|
||||
"iconSrc": <EyeRegular
|
||||
fontSize={16}
|
||||
/>,
|
||||
"isExpanded": true,
|
||||
@@ -1897,7 +1897,7 @@ exports[`createDatabaseTreeNodes using NoSQL API on Hosted Platform creates expe
|
||||
"styleClass": "deleteCollectionMenuItem",
|
||||
},
|
||||
],
|
||||
"iconSrc": <DocumentMultipleRegular
|
||||
"iconSrc": <EyeRegular
|
||||
fontSize={16}
|
||||
/>,
|
||||
"isExpanded": true,
|
||||
@@ -2031,7 +2031,7 @@ exports[`createDatabaseTreeNodes using NoSQL API on Hosted Platform creates expe
|
||||
"styleClass": "deleteCollectionMenuItem",
|
||||
},
|
||||
],
|
||||
"iconSrc": <DocumentMultipleRegular
|
||||
"iconSrc": <EyeRegular
|
||||
fontSize={16}
|
||||
/>,
|
||||
"isExpanded": true,
|
||||
@@ -2211,7 +2211,7 @@ exports[`createDatabaseTreeNodes using NoSQL API on Hosted Platform creates expe
|
||||
"styleClass": "deleteCollectionMenuItem",
|
||||
},
|
||||
],
|
||||
"iconSrc": <DocumentMultipleRegular
|
||||
"iconSrc": <EyeRegular
|
||||
fontSize={16}
|
||||
/>,
|
||||
"isExpanded": true,
|
||||
@@ -2266,7 +2266,7 @@ exports[`createResourceTokenTreeNodes creates the expected tree nodes 1`] = `
|
||||
},
|
||||
],
|
||||
"className": "collectionNode",
|
||||
"iconSrc": <DocumentMultipleRegular
|
||||
"iconSrc": <EyeRegular
|
||||
fontSize={16}
|
||||
/>,
|
||||
"isExpanded": true,
|
||||
|
||||
@@ -82,6 +82,7 @@ jest.mock("Explorer/Tree/Trigger", () => {
|
||||
jest.mock("Common/DatabaseAccountUtility", () => {
|
||||
return {
|
||||
isPublicInternetAccessAllowed: () => true,
|
||||
isGlobalSecondaryIndexEnabled: () => false,
|
||||
};
|
||||
});
|
||||
|
||||
@@ -134,6 +135,15 @@ const baseCollection = {
|
||||
kind: "hash",
|
||||
version: 2,
|
||||
},
|
||||
materializedViews: ko.observable<DataModels.MaterializedView[]>([
|
||||
{ id: "view1", _rid: "rid1" },
|
||||
{ id: "view2", _rid: "rid2" },
|
||||
]),
|
||||
materializedViewDefinition: ko.observable<DataModels.MaterializedViewDefinition>({
|
||||
definition: "SELECT * FROM c WHERE c.id = 1",
|
||||
sourceCollectionId: "source1",
|
||||
sourceCollectionRid: "rid123",
|
||||
}),
|
||||
storedProcedures: ko.observableArray([]),
|
||||
userDefinedFunctions: ko.observableArray([]),
|
||||
triggers: ko.observableArray([]),
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { DatabaseRegular, DocumentMultipleRegular, SettingsRegular } from "@fluentui/react-icons";
|
||||
import { DatabaseRegular, DocumentMultipleRegular, EyeRegular, SettingsRegular } from "@fluentui/react-icons";
|
||||
import { TreeNode } from "Explorer/Controls/TreeComponent/TreeNodeComponent";
|
||||
import { collectionWasOpened } from "Explorer/MostRecentActivity/MostRecentActivity";
|
||||
import TabsBase from "Explorer/Tabs/TabsBase";
|
||||
@@ -29,6 +29,7 @@ export const shouldShowScriptNodes = (): boolean => {
|
||||
const TreeDatabaseIcon = <DatabaseRegular fontSize={16} />;
|
||||
const TreeSettingsIcon = <SettingsRegular fontSize={16} />;
|
||||
const TreeCollectionIcon = <DocumentMultipleRegular fontSize={16} />;
|
||||
const GlobalSecondaryIndexCollectionIcon = <EyeRegular fontSize={16} />; //check icon
|
||||
|
||||
export const createSampleDataTreeNodes = (sampleDataResourceTokenCollection: ViewModels.CollectionBase): TreeNode[] => {
|
||||
const updatedSampleTree: TreeNode = {
|
||||
@@ -80,7 +81,7 @@ export const createSampleDataTreeNodes = (sampleDataResourceTokenCollection: Vie
|
||||
return [updatedSampleTree];
|
||||
};
|
||||
|
||||
export const createResourceTokenTreeNodes = (collection: ViewModels.CollectionBase): TreeNode[] => {
|
||||
export const createResourceTokenTreeNodes = (collection: ViewModels.Collection): TreeNode[] => {
|
||||
if (!collection) {
|
||||
return [
|
||||
{
|
||||
@@ -110,7 +111,7 @@ export const createResourceTokenTreeNodes = (collection: ViewModels.CollectionBa
|
||||
isExpanded: true,
|
||||
children,
|
||||
className: "collectionNode",
|
||||
iconSrc: TreeCollectionIcon,
|
||||
iconSrc: collection.materializedViewDefinition() ? GlobalSecondaryIndexCollectionIcon : TreeCollectionIcon,
|
||||
onClick: () => {
|
||||
// Rewritten version of expandCollapseCollection
|
||||
useSelectedNode.getState().setSelectedNode(collection);
|
||||
@@ -228,7 +229,7 @@ export const buildCollectionNode = (
|
||||
children: children,
|
||||
className: "collectionNode",
|
||||
contextMenu: ResourceTreeContextMenuButtonFactory.createCollectionContextMenuButton(container, collection),
|
||||
iconSrc: TreeCollectionIcon,
|
||||
iconSrc: collection.materializedViewDefinition() ? GlobalSecondaryIndexCollectionIcon : TreeCollectionIcon,
|
||||
onClick: () => {
|
||||
useSelectedNode.getState().setSelectedNode(collection);
|
||||
collection.openTab();
|
||||
|
||||
Reference in New Issue
Block a user