Compare commits

..

1 Commits

Author SHA1 Message Date
msftbot[bot]
60af36b736 Add .github/fabricbot.json 2022-06-27 20:49:42 +00:00
206 changed files with 3395 additions and 26331 deletions

30
.github/fabricbot.json vendored Normal file
View File

@@ -0,0 +1,30 @@
{
"version": "1.0",
"tasks": [
{
"taskType": "trigger",
"capabilityId": "AutoMerge",
"subCapability": "AutoMerge",
"version": "1.0",
"id": "LUEPwPETV",
"config": {
"taskName": "Auto Merge",
"label": "automerge",
"minMinutesOpen": "5",
"mergeType": "squash",
"deleteBranches": true,
"requireAllStatuses": true,
"requireSpecificCheckRuns": false,
"usePrDescriptionAsCommitMessage": true,
"requireAllStatuses_exemptList": [
"Azure Pipelines",
"Dependabot",
"GitHub Pages",
"Check Enforcer"
],
"silentMode": true
}
}
],
"userGroups": []
}

View File

@@ -92,11 +92,11 @@ jobs:
name: dist
path: dist/
- name: Upload build to preview blob storage
run: az storage blob upload-batch -d '$web' -s 'dist' --account-name cosmosexplorerpreview --destination-path "${{github.event.pull_request.head.sha || github.sha}}" --account-key="${PREVIEW_STORAGE_KEY}" --overwrite true
run: az storage blob upload-batch -d '$web' -s 'dist' --account-name cosmosexplorerpreview --destination-path "${{github.event.pull_request.head.sha || github.sha}}" --account-key="${PREVIEW_STORAGE_KEY}"
env:
PREVIEW_STORAGE_KEY: ${{ secrets.PREVIEW_STORAGE_KEY }}
- name: Upload preview config to blob storage
run: az storage blob upload -c '$web' -f ./preview/config.json --account-name cosmosexplorerpreview --name "${{github.event.pull_request.head.sha || github.sha}}/config.json" --account-key="${PREVIEW_STORAGE_KEY}" --overwrite true
run: az storage blob upload -c '$web' -f ./preview/config.json --account-name cosmosexplorerpreview --name "${{github.event.pull_request.head.sha || github.sha}}/config.json" --account-key="${PREVIEW_STORAGE_KEY}"
env:
PREVIEW_STORAGE_KEY: ${{ secrets.PREVIEW_STORAGE_KEY }}
endtoendemulator:
@@ -182,7 +182,7 @@ jobs:
with:
name: dist
- run: cp ./configs/prod.json config.json
- run: nuget sources add -Name "ADO" -Source "$NUGET_SOURCE" -UserName "jawelton@microsoft.com" -Password "$AZURE_DEVOPS_PAT"
- run: nuget sources add -Name "ADO" -Source "$NUGET_SOURCE" -UserName "GitHub" -Password "$AZURE_DEVOPS_PAT"
- run: nuget pack -Version "2.0.0-github-${GITHUB_SHA}"
- run: nuget push -SkipDuplicate -Source "$NUGET_SOURCE" -ApiKey Az *.nupkg
- uses: actions/upload-artifact@v2
@@ -207,7 +207,7 @@ jobs:
name: dist
- run: cp ./configs/mpac.json config.json
- run: sed -i 's/Azure.Cosmos.DB.Data.Explorer/Azure.Cosmos.DB.Data.Explorer.MPAC/g' DataExplorer.nuspec
- run: nuget sources add -Name "ADO" -Source "$NUGET_SOURCE" -UserName "jawelton@microsoft.com" -Password "$AZURE_DEVOPS_PAT"
- run: nuget sources add -Name "ADO" -Source "$NUGET_SOURCE" -UserName "GitHub" -Password "$AZURE_DEVOPS_PAT"
- run: nuget pack -Version "2.0.0-github-${GITHUB_SHA}"
- run: nuget push -SkipDuplicate -Source "$NUGET_SOURCE" -ApiKey Az *.nupkg
- uses: actions/upload-artifact@v2

View File

@@ -1,41 +0,0 @@
<!-- BEGIN MICROSOFT SECURITY.MD V0.0.7 BLOCK -->
## Security
Microsoft takes the security of our software products and services seriously, which includes all source code repositories managed through our GitHub organizations, which include [Microsoft](https://github.com/Microsoft), [Azure](https://github.com/Azure), [DotNet](https://github.com/dotnet), [AspNet](https://github.com/aspnet), [Xamarin](https://github.com/xamarin), and [our GitHub organizations](https://opensource.microsoft.com/).
If you believe you have found a security vulnerability in any Microsoft-owned repository that meets [Microsoft's definition of a security vulnerability](https://aka.ms/opensource/security/definition), please report it to us as described below.
## Reporting Security Issues
**Please do not report security vulnerabilities through public GitHub issues.**
Instead, please report them to the Microsoft Security Response Center (MSRC) at [https://msrc.microsoft.com/create-report](https://aka.ms/opensource/security/create-report).
If you prefer to submit without logging in, send email to [secure@microsoft.com](mailto:secure@microsoft.com). If possible, encrypt your message with our PGP key; please download it from the [Microsoft Security Response Center PGP Key page](https://aka.ms/opensource/security/pgpkey).
You should receive a response within 24 hours. If for some reason you do not, please follow up via email to ensure we received your original message. Additional information can be found at [microsoft.com/msrc](https://aka.ms/opensource/security/msrc).
Please include the requested information listed below (as much as you can provide) to help us better understand the nature and scope of the possible issue:
* Type of issue (e.g. buffer overflow, SQL injection, cross-site scripting, etc.)
* Full paths of source file(s) related to the manifestation of the issue
* The location of the affected source code (tag/branch/commit or direct URL)
* Any special configuration required to reproduce the issue
* Step-by-step instructions to reproduce the issue
* Proof-of-concept or exploit code (if possible)
* Impact of the issue, including how an attacker might exploit the issue
This information will help us triage your report more quickly.
If you are reporting for a bug bounty, more complete reports can contribute to a higher bounty award. Please visit our [Microsoft Bug Bounty Program](https://aka.ms/opensource/security/bounty) page for more details about our active programs.
## Preferred Languages
We prefer all communications to be in English.
## Policy
Microsoft follows the principle of [Coordinated Vulnerability Disclosure](https://aka.ms/opensource/security/cvd).
<!-- END MICROSOFT SECURITY.MD BLOCK -->

View File

@@ -1,6 +1,5 @@
<!doctype html>
<html class="default no-js">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
@@ -10,292 +9,256 @@
<link rel="stylesheet" href="../assets/css/main.css">
<script async src="../assets/js/search.js" id="search-script"></script>
</head>
<body>
<header>
<div class="tsd-page-toolbar">
<div class="container">
<div class="table-wrap">
<div class="table-cell" id="tsd-search" data-index="../assets/js/search.json" data-base="..">
<div class="field">
<label for="tsd-search-field" class="tsd-widget search no-caption">Search</label>
<input id="tsd-search-field" type="text" />
</div>
<ul class="results">
<li class="state loading">Preparing search index...</li>
<li class="state failure">The search index is not available</li>
</ul>
<a href="../index.html" class="title">cosmos-explorer</a>
<header>
<div class="tsd-page-toolbar">
<div class="container">
<div class="table-wrap">
<div class="table-cell" id="tsd-search" data-index="../assets/js/search.json" data-base="..">
<div class="field">
<label for="tsd-search-field" class="tsd-widget search no-caption">Search</label>
<input id="tsd-search-field" type="text" />
</div>
<div class="table-cell" id="tsd-widgets">
<div id="tsd-filter">
<a href="#" class="tsd-widget options no-caption" data-toggle="options">Options</a>
<div class="tsd-filter-group">
<div class="tsd-select" id="tsd-filter-visibility">
<span class="tsd-select-label">All</span>
<ul class="tsd-select-list">
<li data-value="public">Public</li>
<li data-value="protected">Public/Protected</li>
<li data-value="private" class="selected">All</li>
</ul>
</div>
<input type="checkbox" id="tsd-filter-inherited" checked />
<label class="tsd-widget" for="tsd-filter-inherited">Inherited</label>
<input type="checkbox" id="tsd-filter-externals" checked />
<label class="tsd-widget" for="tsd-filter-externals">Externals</label>
<ul class="results">
<li class="state loading">Preparing search index...</li>
<li class="state failure">The search index is not available</li>
</ul>
<a href="../index.html" class="title">cosmos-explorer</a>
</div>
<div class="table-cell" id="tsd-widgets">
<div id="tsd-filter">
<a href="#" class="tsd-widget options no-caption" data-toggle="options">Options</a>
<div class="tsd-filter-group">
<div class="tsd-select" id="tsd-filter-visibility">
<span class="tsd-select-label">All</span>
<ul class="tsd-select-list">
<li data-value="public">Public</li>
<li data-value="protected">Public/Protected</li>
<li data-value="private" class="selected">All</li>
</ul>
</div>
<input type="checkbox" id="tsd-filter-inherited" checked />
<label class="tsd-widget" for="tsd-filter-inherited">Inherited</label>
<input type="checkbox" id="tsd-filter-externals" checked />
<label class="tsd-widget" for="tsd-filter-externals">Externals</label>
</div>
<a href="#" class="tsd-widget menu no-caption" data-toggle="menu">Menu</a>
</div>
<a href="#" class="tsd-widget menu no-caption" data-toggle="menu">Menu</a>
</div>
</div>
</div>
<div class="tsd-page-title">
<div class="container">
<ul class="tsd-breadcrumb">
<li>
<a href="../modules.html">cosmos-explorer</a>
</li>
<li>
<a href="../modules/selfserve_selfserveutils.html">SelfServe/SelfServeUtils</a>
</li>
<li>
<a href="selfserve_selfserveutils.bladetype.html">BladeType</a>
</li>
</ul>
<h1>Enumeration BladeType</h1>
</div>
</div>
<div class="tsd-page-title">
<div class="container">
<ul class="tsd-breadcrumb">
<li>
<a href="../modules.html">cosmos-explorer</a>
</li>
<li>
<a href="../modules/selfserve_selfserveutils.html">SelfServe/SelfServeUtils</a>
</li>
<li>
<a href="selfserve_selfserveutils.bladetype.html">BladeType</a>
</li>
</ul>
<h1>Enumeration BladeType</h1>
</div>
</header>
<div class="container container-main">
<div class="row">
<div class="col-8 col-content">
<section class="tsd-panel tsd-comment">
</div>
</header>
<div class="container container-main">
<div class="row">
<div class="col-8 col-content">
<section class="tsd-panel tsd-comment">
<div class="tsd-comment tsd-typography">
<div class="lead">
<p>Portal Blade types</p>
</div>
</div>
</section>
<section class="tsd-panel-group tsd-index-group">
<h2>Index</h2>
<section class="tsd-panel tsd-index-panel">
<div class="tsd-index-content">
<section class="tsd-index-section ">
<h3>Enumeration members</h3>
<ul class="tsd-index-list">
<li class="tsd-kind-enum-member tsd-parent-kind-enum"><a href="selfserve_selfserveutils.bladetype.html#cassandrakeys" class="tsd-kind-icon">Cassandra<wbr>Keys</a></li>
<li class="tsd-kind-enum-member tsd-parent-kind-enum"><a href="selfserve_selfserveutils.bladetype.html#gremlinkeys" class="tsd-kind-icon">Gremlin<wbr>Keys</a></li>
<li class="tsd-kind-enum-member tsd-parent-kind-enum"><a href="selfserve_selfserveutils.bladetype.html#metrics" class="tsd-kind-icon">Metrics</a></li>
<li class="tsd-kind-enum-member tsd-parent-kind-enum"><a href="selfserve_selfserveutils.bladetype.html#mongokeys" class="tsd-kind-icon">Mongo<wbr>Keys</a></li>
<li class="tsd-kind-enum-member tsd-parent-kind-enum"><a href="selfserve_selfserveutils.bladetype.html#sqlkeys" class="tsd-kind-icon">Sql<wbr>Keys</a></li>
<li class="tsd-kind-enum-member tsd-parent-kind-enum"><a href="selfserve_selfserveutils.bladetype.html#tablekeys" class="tsd-kind-icon">Table<wbr>Keys</a></li>
</ul>
</section>
</div>
</section>
</section>
<section class="tsd-panel-group tsd-member-group ">
<h2>Enumeration members</h2>
<section class="tsd-panel tsd-member tsd-kind-enum-member tsd-parent-kind-enum">
<a name="cassandrakeys" class="tsd-anchor"></a>
<h3>Cassandra<wbr>Keys</h3>
<div class="tsd-signature tsd-kind-icon">Cassandra<wbr>Keys<span class="tsd-signature-symbol">:</span> <span class="tsd-signature-symbol"> = &quot;cassandraDbKeys&quot;</span></div>
<aside class="tsd-sources">
</aside>
<div class="tsd-comment tsd-typography">
<div class="lead">
<p>Portal Blade types</p>
<p>Keys blade of a Cassandra API account.</p>
</div>
</div>
</section>
<section class="tsd-panel-group tsd-index-group">
<h2>Index</h2>
<section class="tsd-panel tsd-index-panel">
<div class="tsd-index-content">
<section class="tsd-index-section ">
<h3>Enumeration members</h3>
<ul class="tsd-index-list">
<li class="tsd-kind-enum-member tsd-parent-kind-enum"><a
href="selfserve_selfserveutils.bladetype.html#cassandrakeys"
class="tsd-kind-icon">Cassandra<wbr>Keys</a></li>
<li class="tsd-kind-enum-member tsd-parent-kind-enum"><a
href="selfserve_selfserveutils.bladetype.html#gremlinkeys"
class="tsd-kind-icon">Gremlin<wbr>Keys</a></li>
<li class="tsd-kind-enum-member tsd-parent-kind-enum"><a
href="selfserve_selfserveutils.bladetype.html#metrics"
class="tsd-kind-icon">Metrics</a></li>
<li class="tsd-kind-enum-member tsd-parent-kind-enum"><a
href="selfserve_selfserveutils.bladetype.html#mongokeys"
class="tsd-kind-icon">Mongo<wbr>Keys</a></li>
<li class="tsd-kind-enum-member tsd-parent-kind-enum"><a
href="selfserve_selfserveutils.bladetype.html#sqlkeys"
class="tsd-kind-icon">Sql<wbr>Keys</a></li>
<li class="tsd-kind-enum-member tsd-parent-kind-enum"><a
href="selfserve_selfserveutils.bladetype.html#tablekeys"
class="tsd-kind-icon">Table<wbr>Keys</a></li>
</ul>
</section>
<section class="tsd-panel tsd-member tsd-kind-enum-member tsd-parent-kind-enum">
<a name="gremlinkeys" class="tsd-anchor"></a>
<h3>Gremlin<wbr>Keys</h3>
<div class="tsd-signature tsd-kind-icon">Gremlin<wbr>Keys<span class="tsd-signature-symbol">:</span> <span class="tsd-signature-symbol"> = &quot;keys&quot;</span></div>
<aside class="tsd-sources">
</aside>
<div class="tsd-comment tsd-typography">
<div class="lead">
<p>Keys blade of a Gremlin API account.</p>
</div>
</section>
</div>
</section>
<section class="tsd-panel-group tsd-member-group ">
<h2>Enumeration members</h2>
<section class="tsd-panel tsd-member tsd-kind-enum-member tsd-parent-kind-enum">
<a name="cassandrakeys" class="tsd-anchor"></a>
<h3>Cassandra<wbr>Keys</h3>
<div class="tsd-signature tsd-kind-icon">Cassandra<wbr>Keys<span
class="tsd-signature-symbol">:</span> <span class="tsd-signature-symbol"> =
&quot;cassandraDbKeys&quot;</span></div>
<aside class="tsd-sources">
</aside>
<div class="tsd-comment tsd-typography">
<div class="lead">
<p>Keys blade of a Azure Cosmos DB for Apache Cassandra account.</p>
</div>
<section class="tsd-panel tsd-member tsd-kind-enum-member tsd-parent-kind-enum">
<a name="metrics" class="tsd-anchor"></a>
<h3>Metrics</h3>
<div class="tsd-signature tsd-kind-icon">Metrics<span class="tsd-signature-symbol">:</span> <span class="tsd-signature-symbol"> = &quot;metrics&quot;</span></div>
<aside class="tsd-sources">
</aside>
<div class="tsd-comment tsd-typography">
<div class="lead">
<p>Metrics blade of an Azure Cosmos DB account.</p>
</div>
</section>
<section class="tsd-panel tsd-member tsd-kind-enum-member tsd-parent-kind-enum">
<a name="gremlinkeys" class="tsd-anchor"></a>
<h3>Gremlin<wbr>Keys</h3>
<div class="tsd-signature tsd-kind-icon">Gremlin<wbr>Keys<span
class="tsd-signature-symbol">:</span> <span class="tsd-signature-symbol"> =
&quot;keys&quot;</span></div>
<aside class="tsd-sources">
</aside>
<div class="tsd-comment tsd-typography">
<div class="lead">
<p>Keys blade of a Azure Cosmos DB for Apache Gremlin account.</p>
</div>
</div>
</section>
<section class="tsd-panel tsd-member tsd-kind-enum-member tsd-parent-kind-enum">
<a name="metrics" class="tsd-anchor"></a>
<h3>Metrics</h3>
<div class="tsd-signature tsd-kind-icon">Metrics<span class="tsd-signature-symbol">:</span>
<span class="tsd-signature-symbol"> = &quot;metrics&quot;</span></div>
<aside class="tsd-sources">
</aside>
<div class="tsd-comment tsd-typography">
<div class="lead">
<p>Metrics blade of an Azure Cosmos DB account.</p>
</div>
</div>
</section>
<section class="tsd-panel tsd-member tsd-kind-enum-member tsd-parent-kind-enum">
<a name="mongokeys" class="tsd-anchor"></a>
<h3>Mongo<wbr>Keys</h3>
<div class="tsd-signature tsd-kind-icon">Mongo<wbr>Keys<span
class="tsd-signature-symbol">:</span> <span class="tsd-signature-symbol"> =
&quot;mongoDbKeys&quot;</span></div>
<aside class="tsd-sources">
</aside>
<div class="tsd-comment tsd-typography">
<div class="lead">
<p>Keys blade of a Azure Cosmos DB for MongoDB account.</p>
</div>
</div>
</section>
<section class="tsd-panel tsd-member tsd-kind-enum-member tsd-parent-kind-enum">
<a name="sqlkeys" class="tsd-anchor"></a>
<h3>Sql<wbr>Keys</h3>
<div class="tsd-signature tsd-kind-icon">Sql<wbr>Keys<span class="tsd-signature-symbol">:</span>
<span class="tsd-signature-symbol"> = &quot;keys&quot;</span></div>
<aside class="tsd-sources">
</aside>
<div class="tsd-comment tsd-typography">
<div class="lead">
<p>Keys blade of a Azure Cosmos DB for NoSQL account.</p>
</div>
</div>
</section>
<section class="tsd-panel tsd-member tsd-kind-enum-member tsd-parent-kind-enum">
<a name="tablekeys" class="tsd-anchor"></a>
<h3>Table<wbr>Keys</h3>
<div class="tsd-signature tsd-kind-icon">Table<wbr>Keys<span
class="tsd-signature-symbol">:</span> <span class="tsd-signature-symbol"> =
&quot;tableKeys&quot;</span></div>
<aside class="tsd-sources">
</aside>
<div class="tsd-comment tsd-typography">
<div class="lead">
<p>Keys blade of a Azure Cosmos DB for Table account.</p>
</div>
</div>
</section>
</div>
</section>
</div>
<div class="col-4 col-menu menu-sticky-wrap menu-highlight">
<nav class="tsd-navigation primary">
<ul>
<li class=" ">
<a href="../modules.html">Modules</a>
</li>
<li class=" tsd-kind-module">
<a href="../modules/selfserve.html">Self<wbr>Serve</a>
</li>
<li class=" tsd-kind-module">
<a href="../modules/selfserve___what_is_currently_supported_.html">Self<wbr>Serve -<wbr>
<wbr>What is currently supported?</a>
</li>
<li class=" tsd-kind-module">
<a href="../modules/selfserve_decorators.html">Self<wbr>Serve/<wbr>Decorators</a>
</li>
<li class=" tsd-kind-module">
<a
href="../modules/selfserve_selfservetelemetryprocessor.html">Self<wbr>Serve/<wbr>Self<wbr>Serve<wbr>Telemetry<wbr>Processor</a>
</li>
<li class=" tsd-kind-module">
<a
href="../modules/selfserve_selfservetypes.html">Self<wbr>Serve/<wbr>Self<wbr>Serve<wbr>Types</a>
</li>
<li class="current tsd-kind-module">
<a
href="../modules/selfserve_selfserveutils.html">Self<wbr>Serve/<wbr>Self<wbr>Serve<wbr>Utils</a>
</li>
</ul>
</nav>
<nav class="tsd-navigation secondary menu-sticky">
<ul class="before-current">
</ul>
<ul class="current">
<li class="current tsd-kind-enum tsd-parent-kind-module">
<a href="selfserve_selfserveutils.bladetype.html" class="tsd-kind-icon">Blade<wbr>Type</a>
<ul>
<li class=" tsd-kind-enum-member tsd-parent-kind-enum">
<a href="selfserve_selfserveutils.bladetype.html#cassandrakeys"
class="tsd-kind-icon">Cassandra<wbr>Keys</a>
</li>
<li class=" tsd-kind-enum-member tsd-parent-kind-enum">
<a href="selfserve_selfserveutils.bladetype.html#gremlinkeys"
class="tsd-kind-icon">Gremlin<wbr>Keys</a>
</li>
<li class=" tsd-kind-enum-member tsd-parent-kind-enum">
<a href="selfserve_selfserveutils.bladetype.html#metrics"
class="tsd-kind-icon">Metrics</a>
</li>
<li class=" tsd-kind-enum-member tsd-parent-kind-enum">
<a href="selfserve_selfserveutils.bladetype.html#mongokeys"
class="tsd-kind-icon">Mongo<wbr>Keys</a>
</li>
<li class=" tsd-kind-enum-member tsd-parent-kind-enum">
<a href="selfserve_selfserveutils.bladetype.html#sqlkeys"
class="tsd-kind-icon">Sql<wbr>Keys</a>
</li>
<li class=" tsd-kind-enum-member tsd-parent-kind-enum">
<a href="selfserve_selfserveutils.bladetype.html#tablekeys"
class="tsd-kind-icon">Table<wbr>Keys</a>
</li>
</ul>
</li>
</ul>
<ul class="after-current">
<li class=" tsd-kind-enum tsd-parent-kind-module">
<a href="selfserve_selfserveutils.selfservetype.html"
class="tsd-kind-icon">Self<wbr>Serve<wbr>Type</a>
</li>
<li class=" tsd-kind-function tsd-parent-kind-module">
<a href="../modules/selfserve_selfserveutils.html#generatebladelink"
class="tsd-kind-icon">generate<wbr>Blade<wbr>Link</a>
</li>
</ul>
</nav>
</div>
<section class="tsd-panel tsd-member tsd-kind-enum-member tsd-parent-kind-enum">
<a name="mongokeys" class="tsd-anchor"></a>
<h3>Mongo<wbr>Keys</h3>
<div class="tsd-signature tsd-kind-icon">Mongo<wbr>Keys<span class="tsd-signature-symbol">:</span> <span class="tsd-signature-symbol"> = &quot;mongoDbKeys&quot;</span></div>
<aside class="tsd-sources">
</aside>
<div class="tsd-comment tsd-typography">
<div class="lead">
<p>Keys blade of a Mongo API account.</p>
</div>
</div>
</section>
<section class="tsd-panel tsd-member tsd-kind-enum-member tsd-parent-kind-enum">
<a name="sqlkeys" class="tsd-anchor"></a>
<h3>Sql<wbr>Keys</h3>
<div class="tsd-signature tsd-kind-icon">Sql<wbr>Keys<span class="tsd-signature-symbol">:</span> <span class="tsd-signature-symbol"> = &quot;keys&quot;</span></div>
<aside class="tsd-sources">
</aside>
<div class="tsd-comment tsd-typography">
<div class="lead">
<p>Keys blade of a SQL API account.</p>
</div>
</div>
</section>
<section class="tsd-panel tsd-member tsd-kind-enum-member tsd-parent-kind-enum">
<a name="tablekeys" class="tsd-anchor"></a>
<h3>Table<wbr>Keys</h3>
<div class="tsd-signature tsd-kind-icon">Table<wbr>Keys<span class="tsd-signature-symbol">:</span> <span class="tsd-signature-symbol"> = &quot;tableKeys&quot;</span></div>
<aside class="tsd-sources">
</aside>
<div class="tsd-comment tsd-typography">
<div class="lead">
<p>Keys blade of a Table API account.</p>
</div>
</div>
</section>
</section>
</div>
<div class="col-4 col-menu menu-sticky-wrap menu-highlight">
<nav class="tsd-navigation primary">
<ul>
<li class=" ">
<a href="../modules.html">Modules</a>
</li>
<li class=" tsd-kind-module">
<a href="../modules/selfserve.html">Self<wbr>Serve</a>
</li>
<li class=" tsd-kind-module">
<a href="../modules/selfserve___what_is_currently_supported_.html">Self<wbr>Serve -<wbr> <wbr>What is currently supported?</a>
</li>
<li class=" tsd-kind-module">
<a href="../modules/selfserve_decorators.html">Self<wbr>Serve/<wbr>Decorators</a>
</li>
<li class=" tsd-kind-module">
<a href="../modules/selfserve_selfservetelemetryprocessor.html">Self<wbr>Serve/<wbr>Self<wbr>Serve<wbr>Telemetry<wbr>Processor</a>
</li>
<li class=" tsd-kind-module">
<a href="../modules/selfserve_selfservetypes.html">Self<wbr>Serve/<wbr>Self<wbr>Serve<wbr>Types</a>
</li>
<li class="current tsd-kind-module">
<a href="../modules/selfserve_selfserveutils.html">Self<wbr>Serve/<wbr>Self<wbr>Serve<wbr>Utils</a>
</li>
</ul>
</nav>
<nav class="tsd-navigation secondary menu-sticky">
<ul class="before-current">
</ul>
<ul class="current">
<li class="current tsd-kind-enum tsd-parent-kind-module">
<a href="selfserve_selfserveutils.bladetype.html" class="tsd-kind-icon">Blade<wbr>Type</a>
<ul>
<li class=" tsd-kind-enum-member tsd-parent-kind-enum">
<a href="selfserve_selfserveutils.bladetype.html#cassandrakeys" class="tsd-kind-icon">Cassandra<wbr>Keys</a>
</li>
<li class=" tsd-kind-enum-member tsd-parent-kind-enum">
<a href="selfserve_selfserveutils.bladetype.html#gremlinkeys" class="tsd-kind-icon">Gremlin<wbr>Keys</a>
</li>
<li class=" tsd-kind-enum-member tsd-parent-kind-enum">
<a href="selfserve_selfserveutils.bladetype.html#metrics" class="tsd-kind-icon">Metrics</a>
</li>
<li class=" tsd-kind-enum-member tsd-parent-kind-enum">
<a href="selfserve_selfserveutils.bladetype.html#mongokeys" class="tsd-kind-icon">Mongo<wbr>Keys</a>
</li>
<li class=" tsd-kind-enum-member tsd-parent-kind-enum">
<a href="selfserve_selfserveutils.bladetype.html#sqlkeys" class="tsd-kind-icon">Sql<wbr>Keys</a>
</li>
<li class=" tsd-kind-enum-member tsd-parent-kind-enum">
<a href="selfserve_selfserveutils.bladetype.html#tablekeys" class="tsd-kind-icon">Table<wbr>Keys</a>
</li>
</ul>
</li>
</ul>
<ul class="after-current">
<li class=" tsd-kind-enum tsd-parent-kind-module">
<a href="selfserve_selfserveutils.selfservetype.html" class="tsd-kind-icon">Self<wbr>Serve<wbr>Type</a>
</li>
<li class=" tsd-kind-function tsd-parent-kind-module">
<a href="../modules/selfserve_selfserveutils.html#generatebladelink" class="tsd-kind-icon">generate<wbr>Blade<wbr>Link</a>
</li>
</ul>
</nav>
</div>
</div>
<footer class="with-border-bottom">
<div class="container">
<h2>Legend</h2>
<div class="tsd-legend-group">
<ul class="tsd-legend">
<li class="tsd-kind-function"><span class="tsd-kind-icon">Function</span></li>
<li class="tsd-kind-type-alias"><span class="tsd-kind-icon">Type alias</span></li>
</ul>
<ul class="tsd-legend">
<li class="tsd-kind-enum"><span class="tsd-kind-icon">Enumeration</span></li>
</ul>
<ul class="tsd-legend">
<li class="tsd-kind-interface"><span class="tsd-kind-icon">Interface</span></li>
</ul>
<ul class="tsd-legend">
<li class="tsd-kind-class"><span class="tsd-kind-icon">Class</span></li>
</ul>
</div>
</div>
<footer class="with-border-bottom">
<div class="container">
<h2>Legend</h2>
<div class="tsd-legend-group">
<ul class="tsd-legend">
<li class="tsd-kind-function"><span class="tsd-kind-icon">Function</span></li>
<li class="tsd-kind-type-alias"><span class="tsd-kind-icon">Type alias</span></li>
</ul>
<ul class="tsd-legend">
<li class="tsd-kind-enum"><span class="tsd-kind-icon">Enumeration</span></li>
</ul>
<ul class="tsd-legend">
<li class="tsd-kind-interface"><span class="tsd-kind-icon">Interface</span></li>
</ul>
<ul class="tsd-legend">
<li class="tsd-kind-class"><span class="tsd-kind-icon">Class</span></li>
</ul>
</div>
</footer>
<div class="container tsd-generator">
<p>Generated using <a href="https://typedoc.org/" target="_blank">TypeDoc</a></p>
</div>
<div class="overlay"></div>
<script src="../assets/js/main.js"></script>
</footer>
<div class="container tsd-generator">
<p>Generated using <a href="https://typedoc.org/" target="_blank">TypeDoc</a></p>
</div>
<div class="overlay"></div>
<script src="../assets/js/main.js"></script>
</body>
</html>

View File

@@ -1,35 +0,0 @@
<svg width="40" height="40" viewBox="0 0 40 40" fill="none" xmlns="http://www.w3.org/2000/svg">
<rect width="40" height="40" fill="white"/>
<path d="M17 3.73926L20 4.04436V12.6862L15.2 13.8013L13.6 15.9967V19.4479C13.6 21.7669 14.8545 23.9045 16.879 25.0353L21.4036 27.5626L13.6 31.69L10.3559 32.1523L7.27902 30.4337C5.25445 29.3028 4 27.1652 4 24.8462V14.7591C4 12.4395 5.25512 10.3015 7.28055 9.17085L16.3174 4.12639L16.3121 4.13012L17 3.73926Z" fill="url(#paint0_radial_420_101763)"/>
<path d="M17 3.73926L20 4.04436V12.6862L15.2 13.8013L13.6 15.9967V19.4479C13.6 21.7669 14.8545 23.9045 16.879 25.0353L21.4036 27.5626L13.6 31.69L10.3559 32.1523L7.27902 30.4337C5.25445 29.3028 4 27.1652 4 24.8462V14.7591C4 12.4395 5.25512 10.3015 7.28055 9.17085L16.3174 4.12639L16.3121 4.13012L17 3.73926Z" fill="url(#paint1_linear_420_101763)"/>
<path d="M26.399 15.001L34.399 19.801L35.999 21.401V24.8452C35.999 27.1642 34.7446 29.3018 32.72 30.4327L23.12 35.7949C21.1804 36.8784 18.8177 36.8784 16.878 35.7949L7.27804 30.4327C7.09146 30.3284 6.91141 30.2157 6.73828 30.095L7.278 30.3965C9.21762 31.4799 11.5803 31.4799 13.52 30.3965L23.12 25.0342C25.1445 23.9033 26.399 21.7657 26.399 19.4467V15.001Z" fill="url(#paint2_radial_420_101763)"/>
<path d="M26.399 15.001L34.399 19.801L35.999 21.401V24.8452C35.999 27.1642 34.7446 29.3018 32.72 30.4327L23.12 35.7949C21.1804 36.8784 18.8177 36.8784 16.878 35.7949L7.27804 30.4327C7.09146 30.3284 6.91141 30.2157 6.73828 30.095L7.278 30.3965C9.21762 31.4799 11.5803 31.4799 13.52 30.3965L23.12 25.0342C25.1445 23.9033 26.399 21.7657 26.399 19.4467V15.001Z" fill="url(#paint3_linear_420_101763)"/>
<path d="M32.7191 9.17053L23.119 3.8117C21.1802 2.72943 18.819 2.72943 16.8802 3.8117L16.3151 4.1271C14.6239 5.31737 13.5996 7.26472 13.5996 9.36025V16.0461L16.8802 14.2149C18.819 13.1326 21.1802 13.1326 23.119 14.2149L32.7191 19.5737C34.6984 20.6786 35.9421 22.7456 35.9977 25.0039C35.999 24.9514 35.9996 24.8987 35.9996 24.8459V14.7588C35.9996 12.4392 34.7445 10.3011 32.7191 9.17053Z" fill="url(#paint4_radial_420_101763)"/>
<path d="M32.7191 9.17053L23.119 3.8117C21.1802 2.72943 18.819 2.72943 16.8802 3.8117L16.3151 4.1271C14.6239 5.31737 13.5996 7.26472 13.5996 9.36025V16.0461L16.8802 14.2149C18.819 13.1326 21.1802 13.1326 23.119 14.2149L32.7191 19.5737C34.6984 20.6786 35.9421 22.7456 35.9977 25.0039C35.999 24.9514 35.9996 24.8987 35.9996 24.8459V14.7588C35.9996 12.4392 34.7445 10.3011 32.7191 9.17053Z" fill="url(#paint5_linear_420_101763)"/>
<defs>
<radialGradient id="paint0_radial_420_101763" cx="0" cy="0" r="1" gradientUnits="userSpaceOnUse" gradientTransform="translate(17.5054 12.8837) rotate(112.544) scale(23.4519 19.3067)">
<stop offset="0.206732" stop-color="#45D586"/>
<stop offset="0.875628" stop-color="#128245"/>
</radialGradient>
<linearGradient id="paint1_linear_420_101763" x1="15.0625" y1="29.6174" x2="13.787" y2="27.2436" gradientUnits="userSpaceOnUse">
<stop offset="0.9999" stop-color="#0F773F"/>
<stop offset="1" stop-color="#0078D4" stop-opacity="0"/>
</linearGradient>
<radialGradient id="paint2_radial_420_101763" cx="0" cy="0" r="1" gradientUnits="userSpaceOnUse" gradientTransform="translate(10.899 27.5214) rotate(-3.9995) scale(24.6197 15.4594)">
<stop offset="0.140029" stop-color="#FBFF47"/>
<stop offset="0.952721" stop-color="#54B228"/>
</radialGradient>
<linearGradient id="paint3_linear_420_101763" x1="30.8932" y1="18.5508" x2="29.5491" y2="20.8921" gradientUnits="userSpaceOnUse">
<stop offset="0.9999" stop-color="#27770B"/>
<stop offset="1" stop-color="#8C66BA" stop-opacity="0"/>
</linearGradient>
<radialGradient id="paint4_radial_420_101763" cx="0" cy="0" r="1" gradientUnits="userSpaceOnUse" gradientTransform="translate(30.632 19.3878) rotate(-138.33) scale(22.8015 13.0047)">
<stop stop-color="#95FEA0"/>
<stop offset="0.839255" stop-color="#10B7B7"/>
</radialGradient>
<linearGradient id="paint5_linear_420_101763" x1="13.5996" y1="11.7134" x2="16.2131" y2="11.7134" gradientUnits="userSpaceOnUse">
<stop offset="0.9999" stop-color="#0A7B7B"/>
<stop offset="1" stop-color="#436DCD" stop-opacity="0"/>
</linearGradient>
</defs>
</svg>

Before

Width:  |  Height:  |  Size: 4.0 KiB

View File

@@ -1,4 +0,0 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<circle cx="8" cy="8" r="8" fill="#0078D4"/>
<path d="M9.18652 4.8418V12H7.64844V6.58008C7.5638 6.65495 7.46289 6.72656 7.3457 6.79492C7.23177 6.86003 7.1097 6.92025 6.97949 6.97559C6.84928 7.02767 6.71419 7.07324 6.57422 7.1123C6.43424 7.14811 6.2959 7.17415 6.15918 7.19043V5.8916C6.55957 5.77441 6.93717 5.62467 7.29199 5.44238C7.64681 5.26009 7.96745 5.0599 8.25391 4.8418H9.18652Z" fill="white"/>
</svg>

Before

Width:  |  Height:  |  Size: 505 B

View File

@@ -1,4 +0,0 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<circle cx="8" cy="8" r="7.5" stroke="#949494"/>
<path d="M7.21875 10.7207H10.1875V12H5.5293V11.4727C5.5293 11.1146 5.58952 10.7939 5.70996 10.5107C5.8304 10.2243 5.98177 9.96875 6.16406 9.74414C6.34635 9.51628 6.54492 9.31608 6.75977 9.14355C6.97786 8.96777 7.18457 8.8099 7.37988 8.66992C7.58496 8.52344 7.764 8.38346 7.91699 8.25C8.07324 8.11654 8.20345 7.9847 8.30762 7.85449C8.41504 7.72103 8.49479 7.58757 8.54688 7.4541C8.59896 7.31738 8.625 7.17253 8.625 7.01953C8.625 6.72005 8.54036 6.49382 8.37109 6.34082C8.20182 6.18783 7.94303 6.11133 7.59473 6.11133C6.99251 6.11133 6.41634 6.35059 5.86621 6.8291V5.47168C6.47493 5.0778 7.16178 4.88086 7.92676 4.88086C8.28158 4.88086 8.59896 4.92806 8.87891 5.02246C9.16211 5.11361 9.40137 5.24544 9.59668 5.41797C9.79199 5.59049 9.9401 5.80046 10.041 6.04785C10.1452 6.29199 10.1973 6.56543 10.1973 6.86816C10.1973 7.19043 10.1468 7.47689 10.0459 7.72754C9.94824 7.97819 9.81641 8.20605 9.65039 8.41113C9.48763 8.61621 9.29883 8.80501 9.08398 8.97754C8.86914 9.14681 8.64616 9.3112 8.41504 9.4707C8.25879 9.58138 8.10742 9.69206 7.96094 9.80273C7.81771 9.91016 7.69076 10.0176 7.58008 10.125C7.4694 10.2292 7.38151 10.3317 7.31641 10.4326C7.2513 10.5335 7.21875 10.6296 7.21875 10.7207Z" fill="#949494"/>
</svg>

Before

Width:  |  Height:  |  Size: 1.3 KiB

View File

@@ -1,4 +0,0 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<circle cx="8" cy="8" r="8" fill="#0078D4"/>
<path d="M7.21875 10.7207H10.1875V12H5.5293V11.4727C5.5293 11.1146 5.58952 10.7939 5.70996 10.5107C5.8304 10.2243 5.98177 9.96875 6.16406 9.74414C6.34635 9.51628 6.54492 9.31608 6.75977 9.14355C6.97786 8.96777 7.18457 8.8099 7.37988 8.66992C7.58496 8.52344 7.764 8.38346 7.91699 8.25C8.07324 8.11654 8.20345 7.9847 8.30762 7.85449C8.41504 7.72103 8.49479 7.58757 8.54688 7.4541C8.59896 7.31738 8.625 7.17253 8.625 7.01953C8.625 6.72005 8.54036 6.49382 8.37109 6.34082C8.20182 6.18783 7.94303 6.11133 7.59473 6.11133C6.99251 6.11133 6.41634 6.35059 5.86621 6.8291V5.47168C6.47493 5.0778 7.16178 4.88086 7.92676 4.88086C8.28158 4.88086 8.59896 4.92806 8.87891 5.02246C9.16211 5.11361 9.40137 5.24544 9.59668 5.41797C9.79199 5.59049 9.9401 5.80046 10.041 6.04785C10.1452 6.29199 10.1973 6.56543 10.1973 6.86816C10.1973 7.19043 10.1468 7.47689 10.0459 7.72754C9.94824 7.97819 9.81641 8.20605 9.65039 8.41113C9.48763 8.61621 9.29883 8.80501 9.08398 8.97754C8.86914 9.14681 8.64616 9.3112 8.41504 9.4707C8.25879 9.58138 8.10742 9.69206 7.96094 9.80273C7.81771 9.91016 7.69076 10.0176 7.58008 10.125C7.4694 10.2292 7.38151 10.3317 7.31641 10.4326C7.2513 10.5335 7.21875 10.6296 7.21875 10.7207Z" fill="white"/>
</svg>

Before

Width:  |  Height:  |  Size: 1.3 KiB

View File

@@ -1,4 +0,0 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<circle cx="8" cy="8" r="7.5" stroke="#949494"/>
<path d="M5.69531 11.7705V10.4277C6.16406 10.7695 6.71094 10.9404 7.33594 10.9404C7.72982 10.9404 8.03581 10.8558 8.25391 10.6865C8.47526 10.5173 8.58594 10.2812 8.58594 9.97852C8.58594 9.66602 8.44922 9.42513 8.17578 9.25586C7.9056 9.08659 7.53288 9.00195 7.05762 9.00195H6.4082V7.82031H7.00879C7.92025 7.82031 8.37598 7.51758 8.37598 6.91211C8.37598 6.34245 8.02604 6.05762 7.32617 6.05762C6.85742 6.05762 6.40169 6.20898 5.95898 6.51172V5.25195C6.45052 5.00456 7.02344 4.88086 7.67773 4.88086C8.39388 4.88086 8.95052 5.04199 9.34766 5.36426C9.74805 5.68652 9.94824 6.10482 9.94824 6.61914C9.94824 7.53385 9.48438 8.10677 8.55664 8.33789V8.3623C9.05143 8.42415 9.44206 8.60482 9.72852 8.9043C10.015 9.20052 10.1582 9.5651 10.1582 9.99805C10.1582 10.6523 9.91895 11.1699 9.44043 11.5508C8.96191 11.9316 8.30111 12.1221 7.45801 12.1221C6.73535 12.1221 6.14779 12.0049 5.69531 11.7705Z" fill="#949494"/>
</svg>

Before

Width:  |  Height:  |  Size: 1.0 KiB

View File

@@ -1,4 +0,0 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<circle cx="8" cy="8" r="8" fill="#0078D4"/>
<path d="M5.69531 11.7705V10.4277C6.16406 10.7695 6.71094 10.9404 7.33594 10.9404C7.72982 10.9404 8.03581 10.8558 8.25391 10.6865C8.47526 10.5173 8.58594 10.2812 8.58594 9.97852C8.58594 9.66602 8.44922 9.42513 8.17578 9.25586C7.9056 9.08659 7.53288 9.00195 7.05762 9.00195H6.4082V7.82031H7.00879C7.92025 7.82031 8.37598 7.51758 8.37598 6.91211C8.37598 6.34245 8.02604 6.05762 7.32617 6.05762C6.85742 6.05762 6.40169 6.20898 5.95898 6.51172V5.25195C6.45052 5.00456 7.02344 4.88086 7.67773 4.88086C8.39388 4.88086 8.95052 5.04199 9.34766 5.36426C9.74805 5.68652 9.94824 6.10482 9.94824 6.61914C9.94824 7.53385 9.48438 8.10677 8.55664 8.33789V8.3623C9.05143 8.42415 9.44206 8.60482 9.72852 8.9043C10.015 9.20052 10.1582 9.5651 10.1582 9.99805C10.1582 10.6523 9.91895 11.1699 9.44043 11.5508C8.96191 11.9316 8.30111 12.1221 7.45801 12.1221C6.73535 12.1221 6.14779 12.0049 5.69531 11.7705Z" fill="white"/>
</svg>

Before

Width:  |  Height:  |  Size: 1.0 KiB

View File

@@ -1,4 +0,0 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<circle cx="8" cy="8" r="7.5" stroke="#949494"/>
<path d="M9.77246 4.99805V9.41211H10.6123V10.5645H9.77246V12H8.36621V10.5645H5.31445V9.3584C5.58464 9.05566 5.86458 8.72526 6.1543 8.36719C6.44401 8.00586 6.72396 7.63477 6.99414 7.25391C7.26432 6.87305 7.51497 6.49056 7.74609 6.10645C7.98047 5.71908 8.17904 5.34961 8.3418 4.99805H9.77246ZM6.69629 9.41211H8.36621V6.96582C8.25228 7.17741 8.12858 7.39225 7.99512 7.61035C7.86165 7.8252 7.72168 8.03841 7.5752 8.25C7.42871 8.45833 7.2806 8.66178 7.13086 8.86035C6.98112 9.05566 6.83626 9.23958 6.69629 9.41211Z" fill="#949494"/>
</svg>

Before

Width:  |  Height:  |  Size: 680 B

View File

@@ -1,4 +0,0 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<circle cx="8" cy="8" r="8" fill="#0078D4"/>
<path d="M9.77246 4.99805V9.41211H10.6123V10.5645H9.77246V12H8.36621V10.5645H5.31445V9.3584C5.58464 9.05566 5.86458 8.72526 6.1543 8.36719C6.44401 8.00586 6.72396 7.63477 6.99414 7.25391C7.26432 6.87305 7.51497 6.49056 7.74609 6.10645C7.98047 5.71908 8.17904 5.34961 8.3418 4.99805H9.77246ZM6.69629 9.41211H8.36621V6.96582C8.25228 7.17741 8.12858 7.39225 7.99512 7.61035C7.86165 7.8252 7.72168 8.03841 7.5752 8.25C7.42871 8.45833 7.2806 8.66178 7.13086 8.86035C6.98112 9.05566 6.83626 9.23958 6.69629 9.41211Z" fill="white"/>
</svg>

Before

Width:  |  Height:  |  Size: 674 B

View File

@@ -1,4 +0,0 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<circle cx="8" cy="8" r="7.5" stroke="#949494"/>
<path d="M5.81738 11.8193V10.501C6.2959 10.7939 6.80534 10.9404 7.3457 10.9404C7.7526 10.9404 8.06999 10.8444 8.29785 10.6523C8.52897 10.457 8.64453 10.1934 8.64453 9.86133C8.64453 9.16797 8.15462 8.82129 7.1748 8.82129C6.81348 8.82129 6.39681 8.84896 5.9248 8.9043L6.18848 4.99805H9.89453V6.25781H7.36523L7.26758 7.65918C7.51823 7.63965 7.7347 7.62988 7.91699 7.62988C8.63639 7.62988 9.19954 7.81868 9.60645 8.19629C10.0133 8.57389 10.2168 9.08171 10.2168 9.71973C10.2168 10.4261 9.97428 11.0039 9.48926 11.4531C9.00423 11.8991 8.34668 12.1221 7.5166 12.1221C6.84277 12.1221 6.27637 12.0212 5.81738 11.8193Z" fill="#949494"/>
</svg>

Before

Width:  |  Height:  |  Size: 779 B

View File

@@ -1,4 +0,0 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<circle cx="8" cy="8" r="8" fill="#0078D4"/>
<path d="M5.81738 11.8193V10.501C6.2959 10.7939 6.80534 10.9404 7.3457 10.9404C7.7526 10.9404 8.06999 10.8444 8.29785 10.6523C8.52897 10.457 8.64453 10.1934 8.64453 9.86133C8.64453 9.16797 8.15462 8.82129 7.1748 8.82129C6.81348 8.82129 6.39681 8.84896 5.9248 8.9043L6.18848 4.99805H9.89453V6.25781H7.36523L7.26758 7.65918C7.51823 7.63965 7.7347 7.62988 7.91699 7.62988C8.63639 7.62988 9.19954 7.81868 9.60645 8.19629C10.0133 8.57389 10.2168 9.08171 10.2168 9.71973C10.2168 10.4261 9.97428 11.0039 9.48926 11.4531C9.00423 11.8991 8.34668 12.1221 7.5166 12.1221C6.84277 12.1221 6.27637 12.0212 5.81738 11.8193Z" fill="white"/>
</svg>

Before

Width:  |  Height:  |  Size: 773 B

View File

@@ -1,3 +0,0 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M2.9 10.4C2.86142 9.92426 2.92976 9.44591 3.1 9C3.2722 8.57315 3.54698 8.19534 3.9 7.9L5.6 6.1L10.6 11.1L8.8 12.8C8.50466 13.153 8.12685 13.4278 7.7 13.6C7.29358 13.7932 6.84997 13.8955 6.4 13.9L5.2 13.7L4.3 13.2L1.7 15.7L1 15L3.5 12.4C3.29618 12.1222 3.12819 11.8198 3 11.5C2.92162 11.1388 2.88804 10.7694 2.9 10.4ZM6.4 12.9L7.3 12.7C7.60584 12.5584 7.87842 12.354 8.1 12.1L9.2 11.1L5.6 7.5L4.6 8.6L4 9.4C3.9125 9.72567 3.87872 10.0634 3.9 10.4C3.88428 10.7034 3.91806 11.0074 4 11.3L4.6 12.1L5.4 12.7L6.4 12.9ZM13.2 4.3C13.4038 4.5778 13.5718 4.88018 13.7 5.2C13.8153 5.59037 13.8824 5.99335 13.9 6.4C13.8955 6.84997 13.7932 7.29358 13.6 7.7C13.4278 8.12685 13.153 8.50466 12.8 8.8L11.1 10.6L6.1 5.6L7.9 3.9C8.19534 3.54698 8.57315 3.2722 9 3.1C9.44591 2.92976 9.92426 2.86142 10.4 2.9H11.5L12.4 3.4L15 1L15.7 1.7L13.2 4.3ZM12.1 8.1C12.354 7.87842 12.5584 7.60584 12.7 7.3C12.8142 7.01258 12.8818 6.70875 12.9 6.4C12.8909 6.0577 12.8232 5.71948 12.7 5.4L12.1 4.6L11.3 4.1C11.0284 3.9405 10.7136 3.87053 10.4 3.9H9.4L8.6 4.5L7.5 5.5L11.1 9.1L12.1 8.1Z" fill="#0078D4"/>
</svg>

Before

Width:  |  Height:  |  Size: 1.2 KiB

View File

@@ -1,15 +0,0 @@
<svg width="34" height="34" viewBox="0 0 34 34" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M0.944458 10.9331H33.0556V28.836C33.0556 29.1205 32.9425 29.3934 32.7413 29.5946C32.5401 29.7958 32.2672 29.9089 31.9827 29.9089H2.01735C1.7328 29.9089 1.45991 29.7958 1.2587 29.5946C1.05749 29.3934 0.944458 29.1205 0.944458 28.836V10.9331Z" fill="url(#paint0_linear_1497_136679)"/>
<path d="M2.02301 4.09132H31.977C32.1179 4.09132 32.2574 4.11907 32.3876 4.17299C32.5178 4.22691 32.636 4.30594 32.7357 4.40557C32.8353 4.50519 32.9143 4.62347 32.9682 4.75364C33.0222 4.8838 33.0499 5.02332 33.0499 5.16421V10.9329H0.944458V5.16421C0.944456 5.02284 0.972394 4.88286 1.02667 4.75232C1.08094 4.62178 1.16047 4.50326 1.2607 4.40356C1.36093 4.30385 1.47987 4.22494 1.6107 4.17136C1.74152 4.11778 1.88164 4.09058 2.02301 4.09132Z" fill="#0078D4"/>
<path d="M5.33553 15.0706L6.03309 14.371C6.09216 14.3118 6.17235 14.2785 6.25601 14.2783C6.33967 14.2782 6.41995 14.3113 6.47919 14.3704L11.6394 19.5161C11.6982 19.5747 11.7449 19.6444 11.7769 19.7211C11.8088 19.7979 11.8252 19.8801 11.8254 19.9632C11.8255 20.0463 11.8092 20.1286 11.7775 20.2055C11.7458 20.2823 11.6993 20.3521 11.6407 20.4109L10.9444 21.1091L5.3375 15.518C5.27826 15.4589 5.24491 15.3788 5.24479 15.2951C5.24467 15.2114 5.27779 15.1312 5.33687 15.0719L5.33553 15.0706Z" fill="#F2F2F2"/>
<path d="M6.1367 25.5068L5.43717 24.8092C5.37793 24.7501 5.34459 24.67 5.34447 24.5863C5.34435 24.5026 5.37747 24.4224 5.43654 24.3631L10.9463 18.8378L11.6445 19.534C11.7633 19.6525 11.8302 19.8133 11.8305 19.9812C11.8307 20.149 11.7643 20.31 11.6457 20.4289L6.57747 25.5115C6.5184 25.5707 6.43821 25.6041 6.35455 25.6042C6.27089 25.6043 6.19061 25.5712 6.13137 25.5121L6.1367 25.5068Z" fill="#E6E6E6"/>
<path d="M22.1019 23.8755H14.1893C13.8857 23.8755 13.6396 24.1216 13.6396 24.4252V25.2355C13.6396 25.5391 13.8857 25.7852 14.1893 25.7852H22.1019C22.4054 25.7852 22.6515 25.5391 22.6515 25.2355V24.4252C22.6515 24.1216 22.4054 23.8755 22.1019 23.8755Z" fill="#F2F2F2"/>
<defs>
<linearGradient id="paint0_linear_1497_136679" x1="17" y1="29.9089" x2="17" y2="10.9331" gradientUnits="userSpaceOnUse">
<stop stop-color="#32BEDD"/>
<stop offset="0.175" stop-color="#32CAEA"/>
<stop offset="0.41" stop-color="#32D2F2"/>
<stop offset="0.775" stop-color="#32D4F5"/>
</linearGradient>
</defs>
</svg>

Before

Width:  |  Height:  |  Size: 2.3 KiB

View File

@@ -1,127 +0,0 @@
<svg width="68" height="72" viewBox="0 0 68 72" fill="none" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<circle cx="34" cy="35" r="32" fill="#BFBFBF"/>
<g style="mix-blend-mode:multiply" filter="url(#filter0_ddd_1497_137613)">
<path d="M18 21.3999C18 19.1908 19.7909 17.3999 22 17.3999H43.6L50 23.7999V48.5999C50 50.809 48.2091 52.5999 46 52.5999H22C19.7909 52.5999 18 50.809 18 48.5999V21.3999Z" fill="white"/>
</g>
<g filter="url(#filter1_b_1497_137613)">
<path d="M18 21.3999C18 19.1908 19.7909 17.3999 22 17.3999H43.6L50 23.7999V48.5999C50 50.809 48.2091 52.5999 46 52.5999H22C19.7909 52.5999 18 50.809 18 48.5999V21.3999Z" fill="url(#paint0_linear_1497_137613)"/>
</g>
<g style="mix-blend-mode:hard-light" filter="url(#filter2_ii_1497_137613)">
<path d="M18 21.3999C18 19.1908 19.7909 17.3999 22 17.3999H43.6L50 23.7999V48.5999C50 50.809 48.2091 52.5999 46 52.5999H22C19.7909 52.5999 18 50.809 18 48.5999V21.3999Z" fill="#808080"/>
<path d="M18 21.3999C18 19.1908 19.7909 17.3999 22 17.3999H43.6L50 23.7999V48.5999C50 50.809 48.2091 52.5999 46 52.5999H22C19.7909 52.5999 18 50.809 18 48.5999V21.3999Z" fill="url(#pattern0)" fill-opacity="0.02"/>
</g>
<g style="mix-blend-mode:multiply" filter="url(#filter3_ddd_1497_137613)">
<path d="M43.6006 17.3999L50.0006 23.7999H47.6006C45.3914 23.7999 43.6006 22.009 43.6006 19.7999V17.3999Z" fill="white"/>
</g>
<g filter="url(#filter4_b_1497_137613)">
<path d="M43.6006 17.3999L50.0006 23.7999H47.6006C45.3914 23.7999 43.6006 22.009 43.6006 19.7999V17.3999Z" fill="url(#paint1_linear_1497_137613)"/>
</g>
<g style="mix-blend-mode:hard-light" filter="url(#filter5_ii_1497_137613)">
<path d="M43.6006 17.3999L50.0006 23.7999H47.6006C45.3914 23.7999 43.6006 22.009 43.6006 19.7999V17.3999Z" fill="#808080"/>
<path d="M43.6006 17.3999L50.0006 23.7999H47.6006C45.3914 23.7999 43.6006 22.009 43.6006 19.7999V17.3999Z" fill="url(#pattern1)" fill-opacity="0.02"/>
</g>
<circle cx="33.9994" cy="34.9999" r="9.6" fill="#BFBFBF"/>
<path d="M30.7998 34.9998L33.3598 37.5598L37.8398 32.7598" stroke="white" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M41.6793 34.9998C41.6793 39.2414 38.2409 42.6798 33.9993 42.6798C29.7578 42.6798 26.3193 39.2414 26.3193 34.9998C26.3193 30.7583 29.7578 27.3198 33.9993 27.3198C38.2409 27.3198 41.6793 30.7583 41.6793 34.9998ZM33.9993 42.0398C37.8874 42.0398 41.0393 38.8879 41.0393 34.9998C41.0393 31.1117 37.8874 27.9598 33.9993 27.9598C30.1113 27.9598 26.9593 31.1117 26.9593 34.9998C26.9593 38.8879 30.1113 42.0398 33.9993 42.0398Z" fill="white"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M30.3899 22.3199C30.0451 22.3769 29.7748 22.6471 29.7179 22.9919C29.661 22.6471 29.3907 22.3769 29.0459 22.3199C29.3907 22.263 29.661 21.9928 29.7179 21.6479C29.7748 21.9928 30.0451 22.263 30.3899 22.3199Z" fill="white"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M29.5508 19.4641C30.2404 19.5779 30.781 20.1185 30.8948 20.8081C31.0086 20.1185 31.5491 19.5779 32.2388 19.4641C31.5491 19.3503 31.0086 18.8098 30.8948 18.1201C30.781 18.8098 30.2404 19.3503 29.5508 19.4641Z" fill="white"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M7.20776 22.3199C7.55259 22.3769 7.82285 22.6471 7.87976 22.9919C7.93667 22.6471 8.20693 22.3769 8.55176 22.3199C8.20693 22.263 7.93667 21.9928 7.87976 21.6479C7.82285 21.9928 7.55259 22.263 7.20776 22.3199Z" fill="white"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M8.04688 19.4641C7.35721 19.5779 6.81669 20.1185 6.70287 20.8081C6.58906 20.1185 6.04854 19.5779 5.35887 19.4641C6.04854 19.3503 6.58906 18.8098 6.70287 18.1201C6.81669 18.8098 7.35721 19.3503 8.04688 19.4641Z" fill="white"/>
<defs>
<filter id="filter0_ddd_1497_137613" x="0" y="0.399902" width="68" height="71.2002" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feOffset dy="3"/>
<feGaussianBlur stdDeviation="2.5"/>
<feColorMatrix type="matrix" values="0 0 0 0 0.25098 0 0 0 0 0.25098 0 0 0 0 0.25098 0 0 0 0.16 0"/>
<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow_1497_137613"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feOffset dy="1"/>
<feGaussianBlur stdDeviation="9"/>
<feColorMatrix type="matrix" values="0 0 0 0 0.25098 0 0 0 0 0.25098 0 0 0 0 0.25098 0 0 0 0.12 0"/>
<feBlend mode="normal" in2="effect1_dropShadow_1497_137613" result="effect2_dropShadow_1497_137613"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feOffset dy="6"/>
<feGaussianBlur stdDeviation="5"/>
<feColorMatrix type="matrix" values="0 0 0 0 0.25098 0 0 0 0 0.25098 0 0 0 0 0.25098 0 0 0 0.14 0"/>
<feBlend mode="normal" in2="effect2_dropShadow_1497_137613" result="effect3_dropShadow_1497_137613"/>
<feBlend mode="normal" in="SourceGraphic" in2="effect3_dropShadow_1497_137613" result="shape"/>
</filter>
<filter id="filter1_b_1497_137613" x="16" y="15.3999" width="36" height="39.2002" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feGaussianBlur in="BackgroundImage" stdDeviation="1"/>
<feComposite in2="SourceAlpha" operator="in" result="effect1_backgroundBlur_1497_137613"/>
<feBlend mode="normal" in="SourceGraphic" in2="effect1_backgroundBlur_1497_137613" result="shape"/>
</filter>
<filter id="filter2_ii_1497_137613" x="18" y="17.3999" width="32" height="35.2002" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feOffset dy="1"/>
<feComposite in2="hardAlpha" operator="arithmetic" k2="-1" k3="1"/>
<feColorMatrix type="matrix" values="0 0 0 0 0.94902 0 0 0 0 0.94902 0 0 0 0 0.94902 0 0 0 0.5 0"/>
<feBlend mode="normal" in2="shape" result="effect1_innerShadow_1497_137613"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feOffset/>
<feGaussianBlur stdDeviation="3"/>
<feComposite in2="hardAlpha" operator="arithmetic" k2="-1" k3="1"/>
<feColorMatrix type="matrix" values="0 0 0 0 0.94902 0 0 0 0 0.94902 0 0 0 0 0.94902 0 0 0 1 0"/>
<feBlend mode="normal" in2="effect1_innerShadow_1497_137613" result="effect2_innerShadow_1497_137613"/>
</filter>
<pattern id="pattern0" patternContentUnits="objectBoundingBox" width="1.875" height="1.70455">
<use xlink:href="#image0_1497_137613" transform="scale(0.03125 0.0284091)"/>
</pattern>
<filter id="filter3_ddd_1497_137613" x="25.6006" y="0.399902" width="42.4004" height="42.3999" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feOffset dy="3"/>
<feGaussianBlur stdDeviation="2.5"/>
<feColorMatrix type="matrix" values="0 0 0 0 0.25098 0 0 0 0 0.25098 0 0 0 0 0.25098 0 0 0 0.16 0"/>
<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow_1497_137613"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feOffset dy="1"/>
<feGaussianBlur stdDeviation="9"/>
<feColorMatrix type="matrix" values="0 0 0 0 0.25098 0 0 0 0 0.25098 0 0 0 0 0.25098 0 0 0 0.12 0"/>
<feBlend mode="normal" in2="effect1_dropShadow_1497_137613" result="effect2_dropShadow_1497_137613"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feOffset dy="6"/>
<feGaussianBlur stdDeviation="5"/>
<feColorMatrix type="matrix" values="0 0 0 0 0.25098 0 0 0 0 0.25098 0 0 0 0 0.25098 0 0 0 0.14 0"/>
<feBlend mode="normal" in2="effect2_dropShadow_1497_137613" result="effect3_dropShadow_1497_137613"/>
<feBlend mode="normal" in="SourceGraphic" in2="effect3_dropShadow_1497_137613" result="shape"/>
</filter>
<filter id="filter4_b_1497_137613" x="41.6006" y="15.3999" width="10.4004" height="10.3999" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feGaussianBlur in="BackgroundImage" stdDeviation="1"/>
<feComposite in2="SourceAlpha" operator="in" result="effect1_backgroundBlur_1497_137613"/>
<feBlend mode="normal" in="SourceGraphic" in2="effect1_backgroundBlur_1497_137613" result="shape"/>
</filter>
<filter id="filter5_ii_1497_137613" x="43.6006" y="17.3999" width="6.40039" height="6.3999" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feOffset dy="1"/>
<feComposite in2="hardAlpha" operator="arithmetic" k2="-1" k3="1"/>
<feColorMatrix type="matrix" values="0 0 0 0 0.94902 0 0 0 0 0.94902 0 0 0 0 0.94902 0 0 0 0.5 0"/>
<feBlend mode="normal" in2="shape" result="effect1_innerShadow_1497_137613"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feOffset/>
<feGaussianBlur stdDeviation="3"/>
<feComposite in2="hardAlpha" operator="arithmetic" k2="-1" k3="1"/>
<feColorMatrix type="matrix" values="0 0 0 0 0.94902 0 0 0 0 0.94902 0 0 0 0 0.94902 0 0 0 1 0"/>
<feBlend mode="normal" in2="effect1_innerShadow_1497_137613" result="effect2_innerShadow_1497_137613"/>
</filter>
<pattern id="pattern1" patternContentUnits="objectBoundingBox" width="9.375" height="9.375">
<use xlink:href="#image0_1497_137613" transform="scale(0.15625)"/>
</pattern>
<linearGradient id="paint0_linear_1497_137613" x1="34" y1="52.5999" x2="34" y2="17.3999" gradientUnits="userSpaceOnUse">
<stop stop-color="#F2F2F2" stop-opacity="0.5"/>
<stop offset="1" stop-color="#F2F2F2"/>
</linearGradient>
<linearGradient id="paint1_linear_1497_137613" x1="46.8006" y1="23.7999" x2="46.8006" y2="17.3999" gradientUnits="userSpaceOnUse">
<stop stop-color="#F2F2F2" stop-opacity="0.5"/>
<stop offset="1" stop-color="#F2F2F2"/>
</linearGradient>
<image id="image0_1497_137613" width="60" height="60" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADwAAAA8CAYAAAA6/NlyAAAM9ElEQVRoQ+WbS6iO3RvG1zv/HCcbiRhR2mJESlJbjBwmGwOH0laUHAaEJLXFwCG1FROHgcPEYbRFSaJtRKQYyCltTBxi/v77rc/v+e53efic+fo/k733+z7Peta67+u+7uu+19qNlFKz2Wwmr/fv36e//vorNRqN1NbWll68eJFWrlyZDh06lG/h856enrRq1ap0//79NH78eAbIn3d1deX7+HzcuHH5uSFDhqRdu3alhQsXpkGDBqXDhw/ncXzG927cuDHfV16My707d+5MW7Zsyb9znTx5Mi1atCiPe/r06Wo8xzl48GBavXp1y3Dt7e2pwWp56NSpU3nSXEz8xo0bqbOzM23evDlNnDgxL2Tq1Km1k+3u7k7Lly9PT548SW/evEkPHz7MBtFAdQu8d+9eNsqwYcOyUb2YC9/duXOneteFCxfS3r1708WLFz8a0+eYI89gEO5//fp1unLlSlq3bl3lFNbECrPJuPH58+dpxIgRlRVnzZqVX6K19LjeZIA4MV56/fr1NGDAgDyPjo6O/LyoiBbnfZs2baq8yj19fX1pypQpGRkgQRREBOqciB4dVaKD50Rhb29vdkS1YLyJl7HO4MGD0+XLl7N3gc6RI0eqiTsJ4CECNIgTixPw/hMnTqTFixe3IMTvWKjo0fjRc7t3706zZ8/OhovjAF++8xkd5LOEAWuIKMqQjhN89+5dOn78eMZ/tKyxVOcVJwu0jTPuZyy97SQcUzRhOIwsspxLNKjvNl4/CvQPCPVzx+jv70/Dhw9vCYNGT09Pk/iM+MeaWkUIAV/gFi8GBrY8Sxz698uXL/NnkNvYsWPTnDlzsvEw1s2bN9OBAwfSjBkzEvdJSBDP7du3M19w8TtXJCU9Vs5BD4O0JUuWZNLlAs4gFT7h3aAhQxpPMAm8Ey9wD2yYjGzM9yys9KYLEmJ4yEn7TLzH+OY7Gdh3C1vev2zZsvwxxnFhn+Iax/kc1+QF/2or8z5IZ/To0Wny5MkVAliQ6UYYx3DDyDDvvHnzsievXbuWn/UyhFywiAJtR48e/ZsHOjo6mmPGjKlYkcBnEuREXs53+/fvzy/CyqQMyArvleQUYyjGP+GBxy9dupQhbAqJKOFdkhqxt3Tp0gx7UEdoyCm+M44vWfEew6TUCDq1ysPANl7fwtpYG0P9yazdaGtra0I4JaUbd8ZNhBjW4n48Rkp59OhRTl2ID7xk/kNY4LlJkyZlDnCsFst++IPxZVXfheqD5UuOQRjhfREBhPWsOX/Hjh3p1q1bmf3hAuAMshpdXV1NYgnoMLCyMnpYliXutm/f3pJCmKQpRQka0wKLZTJOKhIPKcN7CZWRI0fmBZaCg3skQaD6+PHjKi8TFuRaWRjCO3/+fItyjA7KkMZbeoeBo3pSUzPpmFejAPF+BUQUIMZsjPlSoGDcuXPn5nDwvihY8CYeYg56TSaPjMwzIMpxTGOm1oxaIU3cQVaICAYDopIMi1aUlyJe65vHhSaeNTfrXYsOoMXCIJlt27alq1evZo/UhZEe5DsLG3OzaUsGVpJqDBELKrhAUKO3t7eJGIg52LSBIGEBwK2MQVHBQMat8GSBa9asqcaMOdkcavEQ41mmLlFmLEeol4a36MCQzI3Uxe979uypNEaultrb23PxwJfKRqSecatVzZHCxXtdJN6bOXNmjnEGJq6ix/gdj1DFYCCIJ5aKpqpoABdYR3LRKHXP+CyG3bdvX34XKM0xzAIV58aXrI3VYWEKCiSaLEjiVyczKESiCHAMIAaBRJXE5Bj72LFj+Z1CG/hj3GfPnuWxuCwzZW0NGHMwnxmjhMi5c+dyWMYFi04MnmNYSieOgTE5mZTiBQxhVLwKgWApjIQ3WZD1rF7XWLEQIMYhp1isx5RXpiyeFQVMHi2P0QkVuCVmB9DBfCLrR/hjCMIshygeVpXwUpnWuDWnxs4GL4OUtCZw9mJQvGbXIzYXuA+CAmJldeQETYexaGBBFC5kEn7yN8al42HBEtWi8tQCyLAk7lsaAN9DDixUIiG+5AVhKHNKiBb4kSPwEuixzuZZ5aIGjfk8xi7jYwAFEQw9bdq0KsXqzJbi4Uf0jEACsBUhpiI8YUcjavA6whGuos1c+yNSZwXpsm78nRUNRmBx9sVMV8Z0LCa4j0ahuiFygWQnpxBm2cNfIypUW8bcv4kK4jl2PCNRxU7ljxAVymLegVGePn2aVVds8LW0eBQIsVBwgU6uLM+IMYp0Cn+L+s/lVJQT+dq2kMwd+1r+zngwMhe/K3+j+lL6RqET05akRjMRovuItMpAjypJQrADSI0aCw7jMXqfOpq45hl+37p1a0ufq+w78Tf3WQkxpjFMakJBlXmdhSAvyRpohvisi1fONvr6+ppQvbm27DQYy7wYZo1dQxaB2ICg4IC6Ij0igglHUVAaKMZfbBZGweF4zENBRNjQf47awWf46TzhgLxgJ+EEzJ0xl5aCwclBGvPnz88vfPXqVe6QELOOESsWPGdBUZaAsSNZVx6a+33euRKrvA+nvX37NlddpCdJr1SROYZLC1owx8/5HQOws/A1iJBRo6W/BxGxHPwWRDQ6OzubeMaghtUspmU7oYq36G4SQxqlbpcA6FL2xfISOFG52EK1X4bxREFdj8wQI+Toczkmc1MolbkctHBNnz49x3VUYRVLl5UJZGWngoeBBpDEILZto4Uj9TMRmvkWG/G+qKycaCwO+MzOSUvh/mFTLcZmWcbyN+Nv2LAh801s8ltdNbq7u5t4jdiQVFRHDG4slOmonAxQw6vuH1nvWgTQRsJQFBEyP0bCqLGJT3HCFcvLWChopG/e5Sy3S7+m5YkUZaEQhdqYCdmWHTp0aO5kfGp30i7nr9ydrCAdC3IW8eDBg5wv3fON8EMEGBdCRZEgOohRvEXJJnKMe4wqm4ucKGwUO3W7FzFemSc9LutquIcGg8qOe4n9s2fP/pMygTS9rP9yjUu4xFqYharWYmcEhZZZOm6GS14xNUWp6HYHrB7jKJZ9piB+ooCsnhAGqrUyLgkD5WHMwyV3MKbziUWEmoH7ESWIEeSuY4FUmhUteVg2jenhd+3UI4YsTGKDXr2u4YR42fZhDeh0LhxaScv+/v4m3YefUXtq3T+pwqo8LDt/yZYjC1iwYEE6c+bMFx9viHu7tn49+CLD1533wDvferzB8tBeeY5ztlp+V7sFlWWeBnolu4K8UkUZbsDVwy8gydZyeX/LcYdG45827Zee6/gv7BCW5zpYNBekWLG0RxrqzlEQ3x5y4UFyLIwH+7rHq6jXwpAEn61fvz5L0oEDB2b1pGwsO6XUudbOP7NTmhsAdvyiTnXikfoVEDAlKooFlydwGAtRYUfDFMGChHCZDWTYsnjwb8VPhG3U/vwuCzM2AmTUqFGV2LAnlp+J57Qc0O5ibNvieSQkXqDqiduacQEMyguoj2NnIhYIHj7hyAIqiIY+hGLlxXimn5hf7a7EZoVHl2JruGxiMJ7FUNXEQ5LZ6I6BXx4g0YJUTbH7EDfUypzIMxhvxYoVLbuEThYDwyE06Lk88KZKgpwwCoxtk93QiOInGj4WL7G533LkAauycz5hwoTKg1iYM5Juf7pgVExdM436k8nTxyIc3IJVKztBJgxSPJjiuwkFDMD35Sm/eEAtanwQw44GIeYxKreP4rZPhjQdj7iJ/L27guXpuF+1K+hxKZzgxh/OscVDSK5du/bvBf/JBbvQjMeZWEhsJrYk63BulMOuHqYDBaCvti8tW8cDYm6nxj5yPJknUaCosLCNANnUOEVdyfagQfaWiHy3pWHcW2IsOcV4jWmQgsH2EqGk17mn2vLhBMDXHu5igK/ZCuF+YyxOtG4rpDzxV9bjEiC9sXgmWiRgEC7LRQmUWCau88E0zyHHDWmMYDzQqfQsZIQPEy4bAHomniLQa/HoBN7lqEXZCCh3DWKOLnNv2QtzbrFvFhsMZKKqeNBysCaTQSXFk3PAxdMAtHacvAornmP2KIMT+JMOuVULLvdpPeMRC3D3kfAMxohNAr3IzygzSWvm0CgIyi5p3PyK7zS2eTfNBOYljyhr4wGZKHvrjlll4VHqYHIg2xj0pNC/ETplH9rOhd60Vfon7lFlp9DT+n84NmwN39LTiv0qvBoLAzwXd+Bl2zqCiN6O8pM9H686eMc+VzyHZQUHlBEP36MEqyMPTORndz3Kfx8w9n7mP3WUXY+PtlpIK7+jyHdLE8N/yz9vxCLffz3yDBhc5GG5iqXVvPG0zZe2Pr/3+DGsj+z7FcePq+KBOtcNKCxTV2zD5ljLPraiwONGQNYyEU/ZuOMnwgUpat/KDkss+n/Ff9RUaclyirxHcX/37t3ctRBeLJZ6lQXZIKh6vR/+oy32gSWzWC19TkXVFQCQFedHovS1Vx1P6cUT+BrwU+dV/gf5nFrpDQ6oIQAAAABJRU5ErkJggg=="/>
</defs>
</svg>

Before

Width:  |  Height:  |  Size: 15 KiB

View File

@@ -1,3 +0,0 @@
<svg width="334" height="154" viewBox="0 0 334 154" fill="none" xmlns="http://www.w3.org/2000/svg">
<rect x="0.5" y="0.5" width="333" height="153" fill="#F3F2F1" stroke="#E1DFDD"/>
</svg>

Before

Width:  |  Height:  |  Size: 188 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 26 KiB

View File

@@ -1,5 +1,5 @@
<?xml version="1.0" ?>
<!DOCTYPE svg PUBLIC '-//W3C//DTD SVG 1.1//EN' 'http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd'>
<svg enable-background="new 0 0 256 256" height="256px" id="Layer_1" version="1.1" viewBox="0 0 256 256" width="256px" xml:space="preserve" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<path stroke="white" stroke-width="0.5" fill="#000" d="M179.199,38.399c0,1.637-0.625,3.274-1.875,4.524l-85.076,85.075l85.076,85.075c2.5,2.5,2.5,6.55,0,9.05s-6.55,2.5-9.05,0 l-89.601-89.6c-2.5-2.5-2.5-6.551,0-9.051l89.601-89.6c2.5-2.5,6.55-2.5,9.05,0C178.574,35.124,179.199,36.762,179.199,38.399z"/>
<path stroke="white" stroke-width="0.5" fill="#b5a3a3" d="M179.199,38.399c0,1.637-0.625,3.274-1.875,4.524l-85.076,85.075l85.076,85.075c2.5,2.5,2.5,6.55,0,9.05s-6.55,2.5-9.05,0 l-89.601-89.6c-2.5-2.5-2.5-6.551,0-9.051l89.601-89.6c2.5-2.5,6.55-2.5,9.05,0C178.574,35.124,179.199,36.762,179.199,38.399z"/>
</svg>

Before

Width:  |  Height:  |  Size: 649 B

After

Width:  |  Height:  |  Size: 652 B

View File

@@ -18,8 +18,7 @@ module.exports = {
// clearMocks: false,
// Indicates whether the coverage information should be collected while executing the test
collectCoverage: process.env.skipCodeCoverage === "true" ? false : true,
collectCoverage: true,
// An array of glob patterns indicating a set of files for which coverage information should be collected
collectCoverageFrom: ["src/**/*.{js,jsx,ts,tsx}"],
@@ -37,9 +36,9 @@ module.exports = {
coverageThreshold: {
global: {
branches: 25,
functions: 24,
lines: 28,
statements: 28,
functions: 25,
lines: 29,
statements: 29,
},
},

View File

@@ -3,337 +3,337 @@
@import "../Common/Constants";
.query-panel {
display: table;
display: none;
width: 100%;
border-top: 1px solid #dddddd;
/*[{environment-commandbar-toolbar-separator}]*/
background-color: #ffffff;
/*[{plugin-background-color}]*/
padding: 2px 0px 0px 2px;
resize: vertical;
display: table;
display: none;
width: 100%;
border-top: 1px solid #DDDDDD;
/*[{environment-commandbar-toolbar-separator}]*/
background-color: #ffffff;
/*[{plugin-background-color}]*/
padding: 2px 0px 0px 2px;
resize: vertical;
}
.query-panel .row {
display: table-row;
display: table-row;
}
.query-panel .row .cell {
display: table-cell;
display: table-cell;
}
.query-panel.transition-in {
display: table;
top: 0px;
-webkit-transition: top 2s linear;
-ms-transition: top 2s linear;
-moz-transition: top 2s linear;
-khtml-transition: top 2s linear;
-o-transition: top 2s linear;
transition: top 2s linear;
display: table;
top: 0px;
-webkit-transition: top 2s linear;
-ms-transition: top 2s linear;
-moz-transition: top 2s linear;
-khtml-transition: top 2s linear;
-o-transition: top 2s linear;
transition: top 2s linear;
}
.query-builder {
width: 100%;
padding-right: @DefaultSpace;
border-bottom: 1px solid @BaseMedium;
margin-bottom: @DefaultSpace;
width:100%;
padding-right: @DefaultSpace;
border-bottom: 1px solid @BaseMedium;
margin-bottom: @DefaultSpace;
}
.query-builder-toolbar {
background-color: #ffffff;
/*[{plugin-background-color}]*/
min-width: 600px;
height: 30px;
border-bottom: 1px solid #dddddd;
/*[1px solid {environment-commandbar-toolbar-separator}]*/
background-color: #ffffff;
/*[{plugin-background-color}]*/
min-width: 600px;
height: 30px;
border-bottom: 1px solid #DDDDDD;
/*[1px solid {environment-commandbar-toolbar-separator}]*/
}
.query-builder-toolbar .query-toolbar-group {
display: inline-block;
height: 24px;
margin: 2px 0px;
vertical-align: middle;
display: inline-block;
height: 24px;
margin: 2px 0px;
vertical-align: middle;
}
.query-builder-toolbar .query-toolbar-group .query-toolbar-button {
min-width: 0px;
padding: 0px;
margin-left: 2px;
background-color: transparent;
border: solid transparent;
min-width: 0px;
padding: 0px;
margin-left: 2px;
background-color: transparent;
border: solid transparent;
}
.query-builder-toolbar .query-toolbar-group .query-toolbar-button:active {
outline: 2px solid dodgerblue;
/*[2px solid {common-common-controls-button-border-hover}]*/
outline: 2px solid dodgerblue;
/*[2px solid {common-common-controls-button-border-hover}]*/
}
.query-builder-toolbar .query-toolbar-group .query-toolbar-button:hover {
background-color: #cccedb;
/*[{common-controls-button-hover-background}]*/
background-color: #CCCEDB;
/*[{common-controls-button-hover-background}]*/
}
.query-builder-toolbar .query-toolbar-group .query-toolbar-button.active {
background-color: #e6e7ed;
/*[{common-controls-inner-tab-active-background}]*/
outline: none;
background-color: #E6E7ED;
/*[{common-controls-inner-tab-active-background}]*/
outline: none
}
.query-builder-toolbar .query-toolbar-group .query-toolbar-button:disabled,
.query-builder-toolbar .query-toolbar-group .query-toolbar-button.disabled {
background-color: #ffffff;
/*[{common-controls-button-disabled-background}]*/
background: transparent;
border: 1px solid transparent;
outline: none;
opacity: 0.4;
background-color: #ffffff;
/*[{common-controls-button-disabled-background}]*/
background: transparent;
border: 1px solid transparent;
outline: none;
opacity: 0.4;
}
.tableContainer {
overflow: hidden;
.flex-display();
.flex-direction();
overflow: hidden;
.flex-display();
.flex-direction();
}
.tablesQueryTab {
padding-left: @MediumSpace;
width: 100%;
margin-bottom: @LargeSpace;
.tablesQueryTab{
padding-left: @MediumSpace;
width: 100%;
margin-bottom:@LargeSpace;
}
.entity-error-Img {
width: @WarningErrorIconSize;
height: @WarningErrorIconSize;
margin: @DefaultSpace 0px 0px @SmallSpace;
width: @WarningErrorIconSize;
height: @WarningErrorIconSize;
margin: @DefaultSpace 0px 0px @SmallSpace;
}
.query-editor-panel {
margin-right: 16px;
margin-left: 16px;
margin-top: 25px;
position: relative;
vertical-align: middle;
cursor: default;
margin-right: 16px;
margin-left: 16px;
margin-top: 25px;
position: relative;
vertical-align: middle;
cursor: default;
}
.query-editor-text {
width: 100%;
margin: 2px;
border: solid 1px #a9acb3;
/*[{plugin-textbox-disabled-color}]*/
resize: none;
margin-top: -39px;
background-color: #ddd;
padding: 5px;
width: 100%;
margin: 2px;
border: solid 1px #A9ACB3;
/*[{plugin-textbox-disabled-color}]*/
resize: none;
margin-top: -39px;
background-color: #ddd;
padding: 5px;
}
.error-bar {
padding: @LargeSpace 34px @MediumSpace 24px;
padding: @LargeSpace 34px @MediumSpace 24px;
}
.error-message {
background-color: @BaseLow;
padding: @DefaultSpace;
display: inline-flex;
background-color: @BaseLow;
padding: @DefaultSpace;
display: inline-flex;
}
.error-text {
padding-left: @MediumSpace;
padding-left: @MediumSpace;
}
.query-editor-text-invalid {
width: 100%;
margin: 2px;
border: 1px solid #e51400;
resize: none;
margin-top: -30px;
width: 100%;
margin: 2px;
border: 1px solid #e51400;
resize: none;
margin-top: -30px;
}
.query-editor-panel .warning-bar {
width: 100%;
height: 20px;
background-color: #ffffff;
/*[{plugin-background-color}]*/
position: absolute;
top: -24px;
width: 100%;
height: 20px;
background-color: #ffffff;
/*[{plugin-background-color}]*/
position: absolute;
top: -24px;
}
.query-editor-panel .warning-bar .warning-message {
display: inline-flex;
padding-top: 2px;
vertical-align: middle;
display: inline-flex;
padding-top: 2px;
vertical-align: middle;
}
.query-editor-panel .warning-bar .warning-message .warning-text {
margin-left: 2px;
margin-left: 2px;
}
.advanced-options-panel {
margin-bottom: @DefaultSpace;
.advanced-options-panel{
margin-bottom: @DefaultSpace;
}
.advanced-options-panel .advanced-heading .advanced-title {
display: inline-flex;
margin-left: 27px;
margin-top: 10px;
cursor: default;
display: inline-flex;
margin-left: 27px;
margin-top: 10px;
cursor: default;
}
.advanced-options-panel .advanced-options {
margin-left: 32px;
margin-top: 5px;
border: 1px solid transparent;
margin-left: 32px;
margin-top: 5px;
border: 1px solid transparent;
}
hr {
margin-top: 10px;
margin-bottom: 12px;
border: 0;
border-top: 1px solid #ccc;
margin-top: 10px;
margin-bottom: 12px;
border: 0;
border-top: 1px solid #ccc;
}
input::-webkit-outer-spin-button,
input::-webkit-inner-spin-button {
-webkit-appearance: none;
-webkit-appearance: none;
}
.advanced-options-panel .advanced-options .top .top-input {
width: 100px;
word-spacing: normal;
color: #1e1e1e;
/*[{common-controls-button-foreground}]*/
border: 1px solid #cccedb;
/*[1px solid {plugin-textbox-border-color}]*/
height: 20px;
margin-left: 8px;
width: 100px;
word-spacing: normal;
color: #1E1E1E;
/*[{common-controls-button-foreground}]*/
border: 1px solid #CCCEDB;
/*[1px solid {plugin-textbox-border-color}]*/
height: 20px;
margin-left: 8px;
}
.advanced-options-panel .advanced-options .top .invalid-top {
color: red;
color: red;
}
.advanced-options-panel .advanced-options .select {
margin-top: 18px;
display: inline-flex;
margin-top: 18px;
display: inline-flex;
}
.advanced-options-icon {
margin-left: 2px;
vertical-align: sub;
margin-left: 2px;
vertical-align: sub;
}
.advanced-options-panel .advanced-options .select .select-options-text {
margin-left: 4px;
margin-left: 4px;
}
.advanced-options-panel .advanced-options .select .select-options-link {
margin-left: 4px;
cursor: pointer;
outline: none;
margin-left: 4px;
cursor: pointer;
outline: none;
}
.query-panel .row .column-headers .Field {
padding-left: 95px;
padding-right: 0px;
padding-bottom: 6px;
padding-left: 95px;
padding-right: 0px;
padding-bottom: 6px;
}
.clause-table {
border-spacing: 0px;
display: table;
width: 100%;
margin-top: -3px;
border-spacing: 0px;
display: table;
width: 100%;
margin-top: -3px;
}
.clause-table-row {
display: row;
margin-bottom: 10px;
display: row;
margin-bottom: 10px;
}
.clause-table-cell {
display: table-cell;
text-align: left;
vertical-align: middle;
display: table-cell;
text-align: left;
vertical-align: middle;
}
.action-column > button,
.group-control-header > button,
.group-indicator-column > button {
min-width: 20px;
width: 20px;
padding: 0px;
background-color: transparent;
border-color: transparent;
cursor: pointer;
.action-column>button,
.group-control-header>button,
.group-indicator-column>button {
min-width: 20px;
width: 20px;
padding: 0px;
background-color: transparent;
border-color: transparent;
cursor: pointer;
}
.group-control-header > button:disabled {
min-width: 20px;
width: 20px;
padding: 0px;
background-color: transparent;
border-color: transparent;
outline: none;
opacity: 0.4;
cursor: default;
.group-control-header>button:disabled {
min-width: 20px;
width: 20px;
padding: 0px;
background-color: transparent;
border-color: transparent;
outline: none;
opacity: 0.4;
cursor: default;
}
.clause-table-field {
width: 100%;
border: 1px solid #bbbbbb;
width: 100%;
border: 1px solid #bbbbbb;
}
.clause-table-cell button {
height: 20px;
height: 20px;
}
.clause-table-cell input[type="checkbox"] {
padding: 0px;
margin-bottom: 12px;
padding: 0px;
margin-bottom: 12px;
}
.and-or-svg {
margin-top: -8px;
margin-right: -5px;
margin-top: -8px;
margin-right: -5px;
}
.scroll-box {
border-bottom: 1px transparent #ddd;
/*[1px solid {plugin-table-border-color}]*/
border-top: 1px transparent #ddd;
/*[1px solid {plugin-table-border-color}]*/
max-height: 20vh;
width: 100%;
border-bottom: 1px transparent #DDD;
/*[1px solid {plugin-table-border-color}]*/
border-top: 1px transparent #DDD;
/*[1px solid {plugin-table-border-color}]*/
max-height: 20vh;
width: 100%;
}
.scrollable {
overflow: auto;
overflow-x: hidden;
overflow: auto;
overflow-x: hidden;
}
.and-or-column,
.and-or-header {
min-width: 65px;
padding-right: 10px;
padding-left: 5px;
min-width: 65px;
padding-right: 10px;
padding-left: 5px;
}
.operator-column,
.operator-header {
min-width: 65px;
padding-right: 10px;
min-width: 65px;
padding-right: 10px;
}
.field-header,
.field-column {
min-width: 125px;
padding-right: 10px;
min-width: 125px;
padding-right: 10px;
}
.type-header,
.type-column {
min-width: 85px;
min-width: 85px;
}
.and-or-column,
@@ -345,41 +345,41 @@ input::-webkit-inner-spin-button {
.type-header,
.type-column,
.action-header {
padding-right: 10px;
margin-bottom: 8px;
padding-right: 10px;
margin-bottom: 8px;
}
.value-header,
.value-column,
.time-column {
min-width: 230px;
padding: 0px 4px 0px 0px;
width: 100%;
margin-bottom: 8px;
min-width: 230px;
padding: 0px 4px 0px 0px;
width: 100%;
margin-bottom: 8px;
}
.group-control-header,
.group-control-column {
min-width: 25px;
text-align: right;
min-width: 25px;
text-align: right;
}
.group-indicator-table {
border-spacing: 0px;
min-height: 24px;
border-spacing: 0px;
min-height: 24px
}
.group-indicator-column {
min-width: 21px;
padding: 0px;
border-style: none;
height: 29px;
min-width: 21px;
padding: 0px;
border-style: none;
height: 29px;
}
.clause-table-cell.action-column,
.clause-table-cell.action-column,
.clause-table-cell.action-header {
min-width: 60px;
padding-left: @SmallSpace;
min-width: 60px;
padding-left: @SmallSpace;
}
.action-header,
@@ -388,14 +388,15 @@ input::-webkit-inner-spin-button {
.operator-header,
.value-header,
.and-or-header {
padding-right: 4px;
padding-bottom: 5px;
padding-right: 4px;
padding-bottom: 5px;
}
.header-background {
background-color: #ffffff;
background-color: #ffffff;
}
/*.type-header {
padding-right: 4px;
}
@@ -409,111 +410,112 @@ input::-webkit-inner-spin-button {
}*/
.clause-table-field[readonly] {
background-color: #eeeef2;
/*[{plugin-table-header-background-color}]*/
border: 1px solid #cccedb;
/*[{plugin-table-border-color}]*/
background-color: #EEEEF2;
/*[{plugin-table-header-background-color}]*/
border: 1px solid #CCCEDB;
/*[{plugin-table-border-color}]*/
}
.addClause-title {
/*[{common-common-controls-button-border-hover}]*/
cursor: pointer;
margin-left: -5px;
/*[{common-common-controls-button-border-hover}]*/
cursor: pointer;
margin-left: -5px;
}
.addClause {
width: 125px;
padding: 8px 0px 5px 5px;
border: 1px solid #fff;
margin-left: 5px;
width: 125px;
padding: 8px 0px 5px 5px;
border: 1px solid #fff;
margin-left: 5px;
}
.addClause:hover {
.hover();
.hover();
}
.addClause:active {
.active();
border: 1px dashed @AccentMedium;
.active();
border: 1px dashed @AccentMedium;
}
.clause-table-row {
min-width: 550px;
width: 100%;
min-width: 550px;
width: 100%;
}
.clause-table-field field-column {
min-width: 75px;
height: 30px;
width: 100%;
min-width: 75px;
height: 30px;
width: 100%;
}
.clause-table-field field-input {
min-width: 54px;
margin-left: -78px;
height: 25px;
border: none;
min-width: 54px;
margin-left: -78px;
height: 25px;
border: none;
}
.query-panel .row .spacing {
padding-bottom: 6px;
padding-bottom: 6px;
}
.query-panel .divider.horizontal {
height: 10px;
width: 100%;
height: 10px;
width: 100%
}
.inline-div {
display: inline;
display: inline
}
.querybuilder-addpropertyImg,
.querybuilder-cancelImg {
width: 14px;
height: 14px;
margin-left: 3px;
margin-bottom: 8px;
width: 14px;
height: 14px;
margin-left: 3px;
margin-bottom: 8px;
}
.addclauseProperty-Img {
width: 14px;
height: 14px;
margin-bottom: 5px;
margin-left: 12px;
width: 14px;
height: 14px;
margin-bottom: 5px;
margin-left: 12px;
}
.entity-Add-Cancel {
// padding: @DefaultSpace @SmallSpace @SmallSpace;
cursor: pointer;
padding: @DefaultSpace @SmallSpace @SmallSpace;
cursor: pointer;
}
.entity-Add-Cancel:hover {
.hover();
.hover();
}
.entity-Add-Cancel:active {
.active();
.active();
}
.query-builder-isDisabled {
border: 1px solid #cccedb;
color: #ccc;
border: 1px solid #CCCEDB;
color: #ccc;
}
.edit-value-text {
padding-left: @DefaultSpace;
padding-left: @DefaultSpace;
}
.expand-triangle {
width: 10px;
height: 10px;
width: 10px;
height: 10px;
}
.expand-triangle-right {
margin-bottom: 5px;
margin-bottom: 5px;
}
/*
@media only screen and (max-width: 1200px) {
.clause-table {
@@ -522,4 +524,4 @@ input::-webkit-inner-spin-button {
width: 100%;
padding-top: 10px;
}
}*/
}*/

View File

@@ -2576,10 +2576,6 @@ a:link {
.querydropdown.placeholderVisible {
font-style: italic;
}
.querydropdown.placeholderVisible::placeholder { /* Chrome, Firefox, Opera, Safari 10.1+ */
color: #767474;
opacity: 1;
}
.querydropdown:hover {
background-color: @AccentLow;
@@ -3091,4 +3087,3 @@ a:link {
background: white;
height: 100%;
}

View File

@@ -5,17 +5,12 @@
overflow: auto;
.databaseHeader {
padding: 1px;
font-size: 14px;
}
.collectionHeader {
font-size: 12px;
}
.loadMoreHeader {
color: RGB(5, 99, 193);
}
}
.notebookResourceTree {
@@ -28,4 +23,6 @@
.clickDisabled {
pointer-events: none;
}
}
}

35
package-lock.json generated
View File

@@ -9,7 +9,7 @@
"version": "1.0.0",
"dependencies": {
"@azure/arm-cosmosdb": "9.1.0",
"@azure/cosmos": "3.16.2",
"@azure/cosmos": "3.16.1",
"@azure/cosmos-language-service": "0.0.5",
"@azure/identity": "1.2.1",
"@azure/ms-rest-nodeauth": "3.0.7",
@@ -396,13 +396,12 @@
"integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ=="
},
"node_modules/@azure/cosmos": {
"version": "3.16.2",
"resolved": "https://registry.npmjs.org/@azure/cosmos/-/cosmos-3.16.2.tgz",
"integrity": "sha512-sceY5LWj0BHGj8PSyaVCfDRQLVZyoCfIY78kyIROJVEw0k+p9XFs8fhpykN8JklkCftL0WlaVY+X25SQwnhZsw==",
"version": "3.16.1",
"resolved": "https://registry.npmjs.org/@azure/cosmos/-/cosmos-3.16.1.tgz",
"integrity": "sha512-9J76EMiF+ypZwO/Z7OS4PjrU/3hdRLe18dQh/Hj+jwXG2gKJ1NwgkYqcwu1HiCiX73A8+NCeA3PRDbegEnuuNQ==",
"dependencies": {
"@azure/core-auth": "^1.3.0",
"@azure/core-rest-pipeline": "^1.2.0",
"@azure/core-tracing": "^1.0.0",
"debug": "^4.1.1",
"fast-json-stable-stringify": "^2.1.0",
"jsbi": "^3.1.3",
@@ -442,17 +441,6 @@
"node": ">=0.10.0"
}
},
"node_modules/@azure/cosmos/node_modules/@azure/core-tracing": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/@azure/core-tracing/-/core-tracing-1.0.1.tgz",
"integrity": "sha512-I5CGMoLtX+pI17ZdiFJZgxMJApsK6jjfm85hpgp3oazCdq5Wxgh4wMr7ge/TTWW1B5WBuvIOI1fMU/FrOAMKrw==",
"dependencies": {
"tslib": "^2.2.0"
},
"engines": {
"node": ">=12.0.0"
}
},
"node_modules/@azure/cosmos/node_modules/tslib": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.2.0.tgz",
@@ -31470,13 +31458,12 @@
}
},
"@azure/cosmos": {
"version": "3.16.2",
"resolved": "https://registry.npmjs.org/@azure/cosmos/-/cosmos-3.16.2.tgz",
"integrity": "sha512-sceY5LWj0BHGj8PSyaVCfDRQLVZyoCfIY78kyIROJVEw0k+p9XFs8fhpykN8JklkCftL0WlaVY+X25SQwnhZsw==",
"version": "3.16.1",
"resolved": "https://registry.npmjs.org/@azure/cosmos/-/cosmos-3.16.1.tgz",
"integrity": "sha512-9J76EMiF+ypZwO/Z7OS4PjrU/3hdRLe18dQh/Hj+jwXG2gKJ1NwgkYqcwu1HiCiX73A8+NCeA3PRDbegEnuuNQ==",
"requires": {
"@azure/core-auth": "^1.3.0",
"@azure/core-rest-pipeline": "^1.2.0",
"@azure/core-tracing": "^1.0.0",
"debug": "^4.1.1",
"fast-json-stable-stringify": "^2.1.0",
"jsbi": "^3.1.3",
@@ -31488,14 +31475,6 @@
"uuid": "^8.3.0"
},
"dependencies": {
"@azure/core-tracing": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/@azure/core-tracing/-/core-tracing-1.0.1.tgz",
"integrity": "sha512-I5CGMoLtX+pI17ZdiFJZgxMJApsK6jjfm85hpgp3oazCdq5Wxgh4wMr7ge/TTWW1B5WBuvIOI1fMU/FrOAMKrw==",
"requires": {
"tslib": "^2.2.0"
}
},
"tslib": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.2.0.tgz",

View File

@@ -5,7 +5,7 @@
"main": "index.js",
"dependencies": {
"@azure/arm-cosmosdb": "9.1.0",
"@azure/cosmos": "3.16.2",
"@azure/cosmos": "3.16.1",
"@azure/cosmos-language-service": "0.0.5",
"@azure/identity": "1.2.1",
"@azure/ms-rest-nodeauth": "3.0.7",
@@ -212,7 +212,7 @@
"strict:find": "node ./strict-null-checks/find.js",
"strict:add": "node ./strict-null-checks/auto-add.js",
"compile:fullStrict": "tsc -p ./tsconfig.json --strictNullChecks",
"generateARMClients": "npx ts-node utils/armClientGenerator/generator.ts"
"generateARMClients": "npx ts-node --compiler-options '{\"module\":\"commonjs\"}' utils/armClientGenerator/generator.ts"
},
"repository": {
"type": "git",
@@ -232,4 +232,4 @@
"prettier": {
"printWidth": 120
}
}
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1,6 +1,6 @@
import React, { FunctionComponent, MutableRefObject, useEffect, useRef } from "react";
import arrowLeftImg from "../../images/imgarrowlefticon.svg";
import { getApiShortDisplayName } from "../Utils/APITypeUtils";
import { userContext } from "../UserContext";
import { NormalizedEventKey } from "./Constants";
export interface CollapsedResourceTreeProps {
@@ -36,7 +36,7 @@ export const CollapsedResourceTree: FunctionComponent<CollapsedResourceTreeProps
id="collapseToggleLeftPaneButton"
role="button"
tabIndex={0}
aria-label={getApiShortDisplayName() + `Expand tree`}
aria-label="Expand Tree"
onClick={toggleLeftPaneExpanded}
onKeyPress={onKeyPressToggleLeftPaneExpanded}
ref={focusButton}
@@ -45,7 +45,7 @@ export const CollapsedResourceTree: FunctionComponent<CollapsedResourceTreeProps
<img className="arrowCollapsed" src={arrowLeftImg} alt="Expand" />
</span>
<span className="collectionCollapsed">
<span>{getApiShortDisplayName()}</span>
<span>{userContext.apiType} API</span>
</span>
</li>
</ul>

View File

@@ -45,8 +45,6 @@ export class ArmResourceTypes {
export class BackendDefaults {
public static partitionKeyKind = "Hash";
public static partitionKeyMultiHash = "MultiHash";
public static maxNumMultiHashPartition = 2;
public static singlePartitionStorageInGb: string = "10";
public static multiPartitionStorageInGb: string = "100";
public static maxChangeFeedRetentionDuration: number = 10;
@@ -141,7 +139,7 @@ export class Queries {
public static UnlimitedPageOption: string = "unlimited";
public static itemsPerPage: number = 100;
public static unlimitedItemsPerPage: number = 100; // TODO: Figure out appropriate value so it works for accounts with a large number of partitions
public static containersPerPage: number = 50;
public static QueryEditorMinHeightRatio: number = 0.1;
public static QueryEditorMaxHeightRatio: number = 0.4;
public static readonly DefaultMaxDegreeOfParallelism = 6;
@@ -428,91 +426,3 @@ export class JunoEndpoints {
public static readonly Prod = "https://tools.cosmos.azure.com";
public static readonly Stage = "https://tools-staging.cosmos.azure.com";
}
export const QueryCopilotSampleDatabaseId = "CopilotSampleDb";
export const QueryCopilotSampleContainerId = "SampleContainer";
export const QueryCopilotSampleContainerSchema = {
product: {
sampleData: {
id: "de6fadec-0384-43c8-93ea-16c0170b5460",
name: "Premium Phone Mini (Red)",
price: 652.04,
category: "Electronics",
description:
"This Premium Phone Mini (Red) is designed by the company under agreement with the FCC, so we'd give it a pass in either direction, but no one should be using this handset without a compatible handset. All in all, this phone is one of the most affordable Android handsets out there at $100. Check them out.\n\n9. HTC One M9 4",
stock: 74,
countryOfOrigin: "Mexico",
firstAvailable: "2018-07-07 17:42:28",
priceHistory: [592.81],
customerRatings: [
{ username: "dannyhowell", stars: 1, date: "2022-03-12 17:01:23", verifiedUser: true },
{ username: "lindsay26", stars: 1, date: "2022-12-29 07:18:20", verifiedUser: false },
{ username: "smithmiguel", stars: 3, date: "2022-09-08 11:43:27", verifiedUser: false },
{ username: "julie07", stars: 3, date: "2021-03-14 23:54:10", verifiedUser: true },
{ username: "kelly93", stars: 3, date: "2022-11-05 12:45:43", verifiedUser: false },
{ username: "katherinereynolds", stars: 2, date: "2022-09-14 11:49:36", verifiedUser: false },
{ username: "chandlerkenneth", stars: 1, date: "2022-01-14 12:14:43", verifiedUser: true },
],
rareProperty: true,
},
schema: {
properties: {
id: {
type: "string",
},
name: {
type: "string",
},
price: {
type: "number",
},
category: {
type: "string",
},
description: {
type: "string",
},
stock: {
type: "number",
},
countryOfOrigin: {
type: "string",
},
firstAvailable: {
type: "string",
},
priceHistory: {
items: {
type: "number",
},
type: "array",
},
customerRatings: {
items: {
properties: {
username: {
type: "string",
},
stars: {
type: "number",
},
date: {
type: "string",
},
verifiedUser: {
type: "boolean",
},
},
type: "object",
},
type: "array",
},
rareProperty: {
type: "boolean",
},
},
type: "object",
},
},
};

View File

@@ -55,6 +55,7 @@ export const EntityValue: FunctionComponent<TableEntityProps> = ({
label={entityValueLabel && entityValueLabel}
className="addEntityTextField"
id="entityValueId"
autoFocus
disabled={isEntityValueDisable}
type={entityValueType}
placeholder={entityValuePlaceholder}

View File

@@ -1,14 +0,0 @@
import * as EnvironmentUtility from "./EnvironmentUtility";
describe("Environment Utility Test", () => {
it("Test sample URI with /", () => {
const uri = "test/";
expect(EnvironmentUtility.normalizeArmEndpoint(uri)).toEqual(uri);
});
it("Test sample URI without /", () => {
const uri = "test";
const expectedResult = "test/";
expect(EnvironmentUtility.normalizeArmEndpoint(uri)).toEqual(expectedResult);
});
});

View File

@@ -299,7 +299,7 @@ export function createMongoCollectionWithProxy(
db: params.databaseId,
coll: params.collectionId,
pk: shardKey,
offerThroughput: params.autoPilotMaxThroughput || params.offerThroughput,
offerThroughput: params.offerThroughput,
cd: params.createNewDatabase,
st: params.databaseLevelThroughput,
is: !!shardKey,
@@ -309,6 +309,7 @@ export function createMongoCollectionWithProxy(
rg: userContext.resourceGroup,
dba: databaseAccount.name,
isAutoPilot: !!params.autoPilotMaxThroughput,
autoPilotThroughput: params.autoPilotMaxThroughput?.toString(),
};
const endpoint = getFeatureEndpointOrDefault("createCollectionWithProxy");

View File

@@ -1,6 +1,6 @@
import { OfferResponse } from "@azure/cosmos";
import { Offer, SDKOfferDefinition } from "../Contracts/DataModels";
import * as OfferUtility from "./OfferUtility";
import { SDKOfferDefinition, Offer } from "../Contracts/DataModels";
import { OfferResponse } from "@azure/cosmos";
describe("parseSDKOfferResponse", () => {
it("manual throughput", () => {
@@ -31,26 +31,6 @@ describe("parseSDKOfferResponse", () => {
expect(OfferUtility.parseSDKOfferResponse(mockResponse)).toEqual(expectedResult);
});
it("offerContent not defined", () => {
const mockOfferDefinition = {
id: "test",
} as SDKOfferDefinition;
const mockResponse = {
resource: mockOfferDefinition,
} as OfferResponse;
expect(OfferUtility.parseSDKOfferResponse(mockResponse)).toEqual(undefined);
});
it("offerDefinition is null", () => {
const mockResponse = {
resource: undefined,
} as OfferResponse;
expect(OfferUtility.parseSDKOfferResponse(mockResponse)).toEqual(undefined);
});
it("autoscale throughput", () => {
const mockOfferDefinition = {
content: {

View File

@@ -6,7 +6,6 @@ import Explorer from "../Explorer/Explorer";
import { ResourceTokenTree } from "../Explorer/Tree/ResourceTokenTree";
import { ResourceTree } from "../Explorer/Tree/ResourceTree";
import { userContext } from "../UserContext";
import { getApiShortDisplayName } from "../Utils/APITypeUtils";
import { NormalizedEventKey } from "./Constants";
export interface ResourceTreeContainerProps {
@@ -43,7 +42,7 @@ export const ResourceTreeContainer: FunctionComponent<ResourceTreeContainerProps
{/* Collections Window Title/Command Bar - Start */}
<div className="collectiontitle">
<div className="coltitle">
<span className="titlepadcol">{getApiShortDisplayName()}</span>
<span className="titlepadcol">{userContext.apiType} API</span>
<div className="float-right">
<span
className="padimgcolrefresh"
@@ -51,7 +50,7 @@ export const ResourceTreeContainer: FunctionComponent<ResourceTreeContainerProps
role="button"
data-bind="click: onRefreshResourcesClick, clickBubble: false, event: { keypress: onRefreshDatabasesKeyPress }"
tabIndex={0}
aria-label={getApiShortDisplayName() + `Refresh tree`}
aria-label="Refresh tree"
title="Refresh tree"
>
<img className="refreshcol" src={refreshImg} alt="Refresh Tree" />
@@ -63,7 +62,7 @@ export const ResourceTreeContainer: FunctionComponent<ResourceTreeContainerProps
onClick={toggleLeftPaneExpanded}
onKeyPress={onKeyPressToggleLeftPaneExpanded}
tabIndex={0}
aria-label={getApiShortDisplayName() + `Collapse Tree`}
aria-label="Collapse Tree"
title="Collapse Tree"
ref={focusButton}
>

View File

@@ -73,17 +73,6 @@ export const TableEntity: FunctionComponent<TableEntityProps> = ({
const sectionStackTokens: IStackTokens = { childrenGap: 12 };
const handleKeyPress = (event: React.KeyboardEvent<HTMLElement>) => {
if (event.key === "Enter" || event.key === "Space") {
onEditEntity();
}
};
const handleKeyPressdelete = (event: React.KeyboardEvent<HTMLElement>) => {
if (event.key === "Enter" || event.key === "Space") {
onDeleteEntity();
}
};
const getEntityValueType = (): string => {
const { Int, Smallint, Tinyint } = CassandraType;
const { Double, Int32, Int64 } = TableType;
@@ -137,29 +126,12 @@ export const TableEntity: FunctionComponent<TableEntityProps> = ({
/>
{!isEntityValueDisable && (
<TooltipHost content="Edit property" id="editTooltip">
<div tabIndex={0}>
<Image
{...imageProps}
src={EditIcon}
alt="editEntity"
onClick={onEditEntity}
tabIndex={0}
onKeyPress={handleKeyPress}
/>
</div>
<Image {...imageProps} src={EditIcon} alt="editEntity" id="editEntity" onClick={onEditEntity} />
</TooltipHost>
)}
{isDeleteOptionVisible && userContext.apiType !== "Cassandra" && (
<TooltipHost content="Delete property" id="deleteTooltip">
<Image
{...imageProps}
src={DeleteIcon}
alt="delete entity"
id="deleteEntity"
onClick={onDeleteEntity}
tabIndex={0}
onKeyPress={handleKeyPressdelete}
/>
<Image {...imageProps} src={DeleteIcon} alt="delete entity" id="deleteEntity" onClick={onDeleteEntity} />
</TooltipHost>
)}
</Stack>

View File

@@ -9,7 +9,7 @@ export const InfoTooltip: React.FunctionComponent<TooltipProps> = ({ children }:
return (
<span>
<TooltipHost content={children}>
<Icon iconName="Info" ariaLabel={children} className="panelInfoIcon" tabIndex={0} />
<Icon iconName="Info" ariaLabel="Info" className="panelInfoIcon" tabIndex={0} />
</TooltipHost>
</span>
);

View File

@@ -1,49 +0,0 @@
import * as UrlUtility from "./UrlUtility";
describe("parseDocumentsPath", () => {
it("empty resource path", () => {
const resourcePath = "";
expect(UrlUtility.parseDocumentsPath(resourcePath)).toEqual({});
});
it("resourcePath does not begin or end with /", () => {
const resourcePath = "localhost/portal/home";
const expectedResult = {
type: "home",
objectBody: {
id: "portal",
self: "/localhost/portal/home/",
},
};
expect(UrlUtility.parseDocumentsPath(resourcePath)).toEqual(expectedResult);
});
it("resourcePath length is even", () => {
const resourcePath = "/localhost/portal/src/home/";
const expectedResult = {
type: "src",
objectBody: {
id: "home",
self: resourcePath,
},
};
expect(UrlUtility.parseDocumentsPath(resourcePath)).toEqual(expectedResult);
});
it("createUri", () => {
const baseUri = "http://foo.com/bar/";
const relativeUri = "/index.html";
const expectedUri = "http://foo.com/bar/index.html";
expect(UrlUtility.createUri(baseUri, relativeUri)).toEqual(expectedUri);
});
it("should throw an error if baseUri is empty", () => {
expect(() => {
UrlUtility.createUri("", "/home");
}).toThrow("baseUri is null or empty");
});
});

View File

@@ -24,7 +24,7 @@ export const createCollection = async (params: DataModels.CreateCollectionParams
);
try {
let collection: DataModels.Collection;
if (userContext.authType === AuthType.AAD && !userContext.features.enableSDKoperations) {
if (userContext.authType === AuthType.AAD && !userContext.useSDKOperations) {
if (params.createNewDatabase) {
const createDatabaseParams: DataModels.CreateDatabaseParams = {
autoPilotMaxThroughput: params.autoPilotMaxThroughput,

View File

@@ -25,8 +25,7 @@ export async function createDatabase(params: DataModels.CreateDatabaseParams): P
if (userContext.apiType === "Tables") {
throw new Error("Creating database resources is not allowed for tables accounts");
}
const database: DataModels.Database = await (userContext.authType === AuthType.AAD &&
!userContext.features.enableSDKoperations
const database: DataModels.Database = await (userContext.authType === AuthType.AAD && !userContext.useSDKOperations
? createDatabaseWithARM(params)
: createDatabaseWithSDK(params));

View File

@@ -20,11 +20,7 @@ export async function createStoredProcedure(
): Promise<StoredProcedureDefinition & Resource> {
const clearMessage = logConsoleProgress(`Creating stored procedure ${storedProcedure.id}`);
try {
if (
userContext.authType === AuthType.AAD &&
!userContext.features.enableSDKoperations &&
userContext.apiType === "SQL"
) {
if (userContext.authType === AuthType.AAD && !userContext.useSDKOperations && userContext.apiType === "SQL") {
try {
const getResponse = await getSqlStoredProcedure(
userContext.subscriptionId,

View File

@@ -14,11 +14,7 @@ export async function createTrigger(
): Promise<TriggerDefinition | SqlTriggerResource> {
const clearMessage = logConsoleProgress(`Creating trigger ${trigger.id}`);
try {
if (
userContext.authType === AuthType.AAD &&
!userContext.features.enableSDKoperations &&
userContext.apiType === "SQL"
) {
if (userContext.authType === AuthType.AAD && !userContext.useSDKOperations && userContext.apiType === "SQL") {
try {
const getResponse = await getSqlTrigger(
userContext.subscriptionId,

View File

@@ -20,11 +20,7 @@ export async function createUserDefinedFunction(
): Promise<UserDefinedFunctionDefinition & Resource> {
const clearMessage = logConsoleProgress(`Creating user defined function ${userDefinedFunction.id}`);
try {
if (
userContext.authType === AuthType.AAD &&
!userContext.features.enableSDKoperations &&
userContext.apiType === "SQL"
) {
if (userContext.authType === AuthType.AAD && !userContext.useSDKOperations && userContext.apiType === "SQL") {
try {
const getResponse = await getSqlUserDefinedFunction(
userContext.subscriptionId,

View File

@@ -12,7 +12,7 @@ import { handleError } from "../ErrorHandlingUtils";
export async function deleteCollection(databaseId: string, collectionId: string): Promise<void> {
const clearMessage = logConsoleProgress(`Deleting container ${collectionId}`);
try {
if (userContext.authType === AuthType.AAD && !userContext.features.enableSDKoperations) {
if (userContext.authType === AuthType.AAD && !userContext.useSDKOperations) {
await deleteCollectionWithARM(databaseId, collectionId);
} else {
await client().database(databaseId).container(collectionId).delete();

View File

@@ -12,7 +12,10 @@ export async function deleteDatabase(databaseId: string): Promise<void> {
const clearMessage = logConsoleProgress(`Deleting database ${databaseId}`);
try {
if (userContext.authType === AuthType.AAD && !userContext.features.enableSDKoperations) {
if (userContext.apiType === "Tables") {
throw new Error("Deleting database resources is not allowed for tables accounts");
}
if (userContext.authType === AuthType.AAD && !userContext.useSDKOperations) {
await deleteDatabaseWithARM(databaseId);
} else {
await client().database(databaseId).delete();

View File

@@ -4,7 +4,6 @@ import { logConsoleInfo, logConsoleProgress } from "../../Utils/NotificationCons
import { client } from "../CosmosClient";
import { getEntityName } from "../DocumentUtility";
import { handleError } from "../ErrorHandlingUtils";
import { getPartitionKeyValue } from "./getPartitionKeyValue";
export const deleteDocument = async (collection: CollectionBase, documentId: DocumentId): Promise<void> => {
const entityName: string = getEntityName();
@@ -14,7 +13,7 @@ export const deleteDocument = async (collection: CollectionBase, documentId: Doc
await client()
.database(collection.databaseId)
.container(collection.id())
.item(documentId.id(), getPartitionKeyValue(documentId))
.item(documentId.id(), documentId.partitionKeyValue?.length === 0 ? undefined : documentId.partitionKeyValue)
.delete();
logConsoleInfo(`Successfully deleted ${entityName} ${documentId.id()}`);
} catch (error) {

View File

@@ -12,11 +12,7 @@ export async function deleteStoredProcedure(
): Promise<void> {
const clearMessage = logConsoleProgress(`Deleting stored procedure ${storedProcedureId}`);
try {
if (
userContext.authType === AuthType.AAD &&
!userContext.features.enableSDKoperations &&
userContext.apiType === "SQL"
) {
if (userContext.authType === AuthType.AAD && !userContext.useSDKOperations && userContext.apiType === "SQL") {
await deleteSqlStoredProcedure(
userContext.subscriptionId,
userContext.resourceGroup,

View File

@@ -8,11 +8,7 @@ import { handleError } from "../ErrorHandlingUtils";
export async function deleteTrigger(databaseId: string, collectionId: string, triggerId: string): Promise<void> {
const clearMessage = logConsoleProgress(`Deleting trigger ${triggerId}`);
try {
if (
userContext.authType === AuthType.AAD &&
!userContext.features.enableSDKoperations &&
userContext.apiType === "SQL"
) {
if (userContext.authType === AuthType.AAD && !userContext.useSDKOperations && userContext.apiType === "SQL") {
await deleteSqlTrigger(
userContext.subscriptionId,
userContext.resourceGroup,

View File

@@ -8,11 +8,7 @@ import { handleError } from "../ErrorHandlingUtils";
export async function deleteUserDefinedFunction(databaseId: string, collectionId: string, id: string): Promise<void> {
const clearMessage = logConsoleProgress(`Deleting user defined function ${id}`);
try {
if (
userContext.authType === AuthType.AAD &&
!userContext.features.enableSDKoperations &&
userContext.apiType === "SQL"
) {
if (userContext.authType === AuthType.AAD && !userContext.useSDKOperations && userContext.apiType === "SQL") {
await deleteSqlUserDefinedFunction(
userContext.subscriptionId,
userContext.resourceGroup,

View File

@@ -1,12 +0,0 @@
import { userContext } from "UserContext";
import DocumentId from "../../Explorer/Tree/DocumentId";
export const getPartitionKeyValue = (documentId: DocumentId) => {
if (userContext.apiType === "Tables" && documentId.partitionKeyValue?.length === 0) {
return "";
}
if (documentId.partitionKeyValue?.length === 0) {
return undefined;
}
return documentId.partitionKeyValue;
};

View File

@@ -14,11 +14,7 @@ export const readCollectionOffer = async (params: ReadCollectionOfferParams): Pr
const clearMessage = logConsoleProgress(`Querying offer for collection ${params.collectionId}`);
try {
if (
userContext.authType === AuthType.AAD &&
!userContext.features.enableSDKoperations &&
userContext.apiType !== "Tables"
) {
if (userContext.authType === AuthType.AAD && !userContext.useSDKOperations && userContext.apiType !== "Tables") {
return await readCollectionOfferWithARM(params.databaseId, params.collectionId);
}
@@ -96,14 +92,6 @@ const readCollectionOfferWithARM = async (databaseId: string, collectionId: stri
? parseInt(resource.minimumThroughput)
: resource.minimumThroughput;
const autoscaleSettings = resource.autoscaleSettings;
const instantMaximumThroughput: number =
typeof resource.instantMaximumThroughput === "string"
? parseInt(resource.instantMaximumThroughput)
: resource.instantMaximumThroughput;
const softAllowedMaximumThroughput: number =
typeof resource.softAllowedMaximumThroughput === "string"
? parseInt(resource.softAllowedMaximumThroughput)
: resource.softAllowedMaximumThroughput;
if (autoscaleSettings) {
return {
@@ -112,8 +100,6 @@ const readCollectionOfferWithARM = async (databaseId: string, collectionId: stri
manualThroughput: undefined,
minimumThroughput,
offerReplacePending: resource.offerReplacePending === "true",
instantMaximumThroughput,
softAllowedMaximumThroughput,
};
}
@@ -123,8 +109,6 @@ const readCollectionOfferWithARM = async (databaseId: string, collectionId: stri
manualThroughput: resource.throughput,
minimumThroughput,
offerReplacePending: resource.offerReplacePending === "true",
instantMaximumThroughput,
softAllowedMaximumThroughput,
};
}

View File

@@ -1,4 +1,3 @@
import { Queries } from "Common/Constants";
import { AuthType } from "../../AuthType";
import * as DataModels from "../../Contracts/DataModels";
import { userContext } from "../../UserContext";
@@ -14,11 +13,7 @@ import { handleError } from "../ErrorHandlingUtils";
export async function readCollections(databaseId: string): Promise<DataModels.Collection[]> {
const clearMessage = logConsoleProgress(`Querying containers for database ${databaseId}`);
try {
if (
userContext.authType === AuthType.AAD &&
!userContext.features.enableSDKoperations &&
userContext.apiType !== "Tables"
) {
if (userContext.authType === AuthType.AAD && !userContext.useSDKOperations && userContext.apiType !== "Tables") {
return await readCollectionsWithARM(databaseId);
}
@@ -32,35 +27,6 @@ export async function readCollections(databaseId: string): Promise<DataModels.Co
}
}
export async function readCollectionsWithPagination(
databaseId: string,
continuationToken?: string
): Promise<DataModels.CollectionsWithPagination> {
const clearMessage = logConsoleProgress(`Querying containers for database ${databaseId}`);
try {
const sdkResponse = await client()
.database(databaseId)
.containers.query(
{ query: "SELECT * FROM c" },
{
continuationToken,
maxItemCount: Queries.containersPerPage,
}
)
.fetchNext();
const collectionsWithPagination: DataModels.CollectionsWithPagination = {
collections: sdkResponse.resources as DataModels.Collection[],
continuationToken: sdkResponse.continuationToken,
};
return collectionsWithPagination;
} catch (error) {
handleError(error, "ReadCollections", `Error while querying containers for database ${databaseId}`);
throw error;
} finally {
clearMessage();
}
}
async function readCollectionsWithARM(databaseId: string): Promise<DataModels.Collection[]> {
let rpResponse;

View File

@@ -13,11 +13,7 @@ export const readDatabaseOffer = async (params: ReadDatabaseOfferParams): Promis
const clearMessage = logConsoleProgress(`Querying offer for database ${params.databaseId}`);
try {
if (
userContext.authType === AuthType.AAD &&
!userContext.features.enableSDKoperations &&
userContext.apiType !== "Tables"
) {
if (userContext.authType === AuthType.AAD && !userContext.useSDKOperations && userContext.apiType !== "Tables") {
return await readDatabaseOfferWithARM(params.databaseId);
}
@@ -68,14 +64,6 @@ const readDatabaseOfferWithARM = async (databaseId: string): Promise<Offer> => {
? parseInt(resource.minimumThroughput)
: resource.minimumThroughput;
const autoscaleSettings = resource.autoscaleSettings;
const instantMaximumThroughput: number =
typeof resource.instantMaximumThroughput === "string"
? parseInt(resource.instantMaximumThroughput)
: resource.instantMaximumThroughput;
const softAllowedMaximumThroughput: number =
typeof resource.softAllowedMaximumThroughput === "string"
? parseInt(resource.softAllowedMaximumThroughput)
: resource.softAllowedMaximumThroughput;
if (autoscaleSettings) {
return {
@@ -84,8 +72,6 @@ const readDatabaseOfferWithARM = async (databaseId: string): Promise<Offer> => {
manualThroughput: undefined,
minimumThroughput,
offerReplacePending: resource.offerReplacePending === "true",
instantMaximumThroughput,
softAllowedMaximumThroughput,
};
}
@@ -95,8 +81,6 @@ const readDatabaseOfferWithARM = async (databaseId: string): Promise<Offer> => {
manualThroughput: resource.throughput,
minimumThroughput,
offerReplacePending: resource.offerReplacePending === "true",
instantMaximumThroughput,
softAllowedMaximumThroughput,
};
}

View File

@@ -13,11 +13,7 @@ export async function readDatabases(): Promise<DataModels.Database[]> {
let databases: DataModels.Database[];
const clearMessage = logConsoleProgress(`Querying databases`);
try {
if (
userContext.authType === AuthType.AAD &&
!userContext.features.enableSDKoperations &&
userContext.apiType !== "Tables"
) {
if (userContext.authType === AuthType.AAD && !userContext.useSDKOperations && userContext.apiType !== "Tables") {
databases = await readDatabasesWithARM();
} else {
const sdkResponse = await client().databases.readAll().fetchAll();

View File

@@ -6,7 +6,6 @@ import { HttpHeaders } from "../Constants";
import { client } from "../CosmosClient";
import { getEntityName } from "../DocumentUtility";
import { handleError } from "../ErrorHandlingUtils";
import { getPartitionKeyValue } from "./getPartitionKeyValue";
export const readDocument = async (collection: CollectionBase, documentId: DocumentId): Promise<Item> => {
const entityName = getEntityName();
@@ -22,7 +21,8 @@ export const readDocument = async (collection: CollectionBase, documentId: Docum
const response = await client()
.database(collection.databaseId)
.container(collection.id())
.item(documentId.id(), getPartitionKeyValue(documentId))
// use undefined if the partitionKeyValue is empty
.item(documentId.id(), documentId.partitionKeyValue?.length === 0 ? undefined : documentId.partitionKeyValue)
.read(options);
return response?.resource;

View File

@@ -1,9 +1,8 @@
import { Resource, StoredProcedureDefinition } from "@azure/cosmos";
import { CloudError, SqlStoredProcedureListResult } from "Utils/arm/generatedClients/cosmos/types";
import { AuthType } from "../../AuthType";
import { userContext } from "../../UserContext";
import { logConsoleProgress } from "../../Utils/NotificationConsoleUtils";
import { listSqlStoredProcedures } from "../../Utils/arm/generatedClients/cosmos/sqlResources";
import { logConsoleProgress } from "../../Utils/NotificationConsoleUtils";
import { client } from "../CosmosClient";
import { handleError } from "../ErrorHandlingUtils";
@@ -13,11 +12,7 @@ export async function readStoredProcedures(
): Promise<(StoredProcedureDefinition & Resource)[]> {
const clearMessage = logConsoleProgress(`Querying stored procedures for container ${collectionId}`);
try {
if (
userContext.authType === AuthType.AAD &&
!userContext.features.enableSDKoperations &&
userContext.apiType === "SQL"
) {
if (userContext.authType === AuthType.AAD && !userContext.useSDKOperations && userContext.apiType === "SQL") {
const rpResponse = await listSqlStoredProcedures(
userContext.subscriptionId,
userContext.resourceGroup,
@@ -25,13 +20,7 @@ export async function readStoredProcedures(
databaseId,
collectionId
);
const listResult = rpResponse as SqlStoredProcedureListResult;
if (listResult) {
return listResult?.value?.map((sproc) => sproc.properties?.resource as StoredProcedureDefinition & Resource);
}
const cloudError = rpResponse as CloudError;
throw new Error(cloudError?.error?.message);
return rpResponse?.value?.map((sproc) => sproc.properties?.resource as StoredProcedureDefinition & Resource);
}
const response = await client()

View File

@@ -13,11 +13,7 @@ export async function readTriggers(
): Promise<SqlTriggerResource[] | TriggerDefinition[]> {
const clearMessage = logConsoleProgress(`Querying triggers for container ${collectionId}`);
try {
if (
userContext.authType === AuthType.AAD &&
!userContext.features.enableSDKoperations &&
userContext.apiType === "SQL"
) {
if (userContext.authType === AuthType.AAD && !userContext.useSDKOperations && userContext.apiType === "SQL") {
const rpResponse = await listSqlTriggers(
userContext.subscriptionId,
userContext.resourceGroup,

View File

@@ -11,9 +11,9 @@ export async function readUserDefinedFunctions(
collectionId: string
): Promise<(UserDefinedFunctionDefinition & Resource)[]> {
const clearMessage = logConsoleProgress(`Querying user defined functions for container ${collectionId}`);
const { authType, apiType, subscriptionId, resourceGroup, databaseAccount } = userContext;
const { authType, useSDKOperations, apiType, subscriptionId, resourceGroup, databaseAccount } = userContext;
try {
if (authType === AuthType.AAD && !userContext.features.enableSDKoperations && apiType === "SQL") {
if (authType === AuthType.AAD && !useSDKOperations && apiType === "SQL") {
const rpResponse = await listSqlUserDefinedFunctions(
subscriptionId,
resourceGroup,

View File

@@ -33,11 +33,7 @@ export async function updateCollection(
const clearMessage = logConsoleProgress(`Updating container ${collectionId}`);
try {
if (
userContext.authType === AuthType.AAD &&
!userContext.features.enableSDKoperations &&
userContext.apiType !== "Tables"
) {
if (userContext.authType === AuthType.AAD && !userContext.useSDKOperations && userContext.apiType !== "Tables") {
collection = await updateCollectionWithARM(databaseId, collectionId, newCollection);
} else {
const sdkResponse = await client()

View File

@@ -6,7 +6,6 @@ import { logConsoleInfo, logConsoleProgress } from "../../Utils/NotificationCons
import { client } from "../CosmosClient";
import { getEntityName } from "../DocumentUtility";
import { handleError } from "../ErrorHandlingUtils";
import { getPartitionKeyValue } from "./getPartitionKeyValue";
export const updateDocument = async (
collection: CollectionBase,
@@ -26,7 +25,7 @@ export const updateDocument = async (
const response = await client()
.database(collection.databaseId)
.container(collection.id())
.item(documentId.id(), getPartitionKeyValue(documentId))
.item(documentId.id(), documentId.partitionKeyValue?.length === 0 ? undefined : documentId.partitionKeyValue)
.replace(newDocument, options);
logConsoleInfo(`Successfully updated ${entityName} ${documentId.id()}`);

View File

@@ -56,7 +56,7 @@ export const updateOffer = async (params: UpdateOfferParams): Promise<Offer> =>
const clearMessage = logConsoleProgress(`Updating offer for ${offerResourceText}`);
try {
if (userContext.authType === AuthType.AAD && !userContext.features.enableSDKoperations) {
if (userContext.authType === AuthType.AAD && !userContext.useSDKOperations) {
if (params.collectionId) {
updatedOffer = await updateCollectionOfferWithARM(params);
} else if (userContext.apiType === "Tables") {

View File

@@ -20,9 +20,9 @@ export async function updateStoredProcedure(
): Promise<StoredProcedureDefinition & Resource> {
const clearMessage = logConsoleProgress(`Updating stored procedure ${storedProcedure.id}`);
try {
const { authType, apiType, subscriptionId, resourceGroup, databaseAccount } = userContext;
const { authType, useSDKOperations, apiType, subscriptionId, resourceGroup, databaseAccount } = userContext;
if (authType === AuthType.AAD && !userContext.features.enableSDKoperations && apiType === "SQL") {
if (authType === AuthType.AAD && !useSDKOperations && apiType === "SQL") {
const getResponse = await getSqlStoredProcedure(
subscriptionId,
resourceGroup,

View File

@@ -13,9 +13,9 @@ export async function updateTrigger(
trigger: SqlTriggerResource
): Promise<SqlTriggerResource | TriggerDefinition> {
const clearMessage = logConsoleProgress(`Updating trigger ${trigger.id}`);
const { authType, apiType, subscriptionId, resourceGroup, databaseAccount } = userContext;
const { authType, useSDKOperations, apiType, subscriptionId, resourceGroup, databaseAccount } = userContext;
try {
if (authType === AuthType.AAD && !userContext.features.enableSDKoperations && apiType === "SQL") {
if (authType === AuthType.AAD && !useSDKOperations && apiType === "SQL") {
const getResponse = await getSqlTrigger(
subscriptionId,
resourceGroup,

View File

@@ -19,9 +19,9 @@ export async function updateUserDefinedFunction(
userDefinedFunction: UserDefinedFunctionDefinition
): Promise<UserDefinedFunctionDefinition & Resource> {
const clearMessage = logConsoleProgress(`Updating user defined function ${userDefinedFunction.id}`);
const { authType, apiType, subscriptionId, resourceGroup, databaseAccount } = userContext;
const { authType, useSDKOperations, apiType, subscriptionId, resourceGroup, databaseAccount } = userContext;
try {
if (authType === AuthType.AAD && !userContext.features.enableSDKoperations && apiType === "SQL") {
if (authType === AuthType.AAD && !useSDKOperations && apiType === "SQL") {
const getResponse = await getSqlUserDefinedFunction(
subscriptionId,
resourceGroup,

View File

@@ -33,8 +33,6 @@ export interface DatabaseAccountExtendedProperties {
privateEndpointConnections?: unknown[];
capacity?: { totalThroughputLimit: number };
locations?: DatabaseAccountResponseLocation[];
postgresqlEndpoint?: string;
publicNetworkAccess?: string;
}
export interface DatabaseAccountResponseLocation {
@@ -156,11 +154,6 @@ export interface Collection extends Resource {
requestSchema?: () => void;
}
export interface CollectionsWithPagination {
continuationToken?: string;
collections?: Collection[];
}
export interface Database extends Resource {
collections?: Collection[];
}
@@ -242,8 +235,6 @@ export interface Offer {
minimumThroughput: number | undefined;
offerDefinition?: SDKOfferDefinition;
offerReplacePending: boolean;
instantMaximumThroughput?: number;
softAllowedMaximumThroughput?: number;
}
export interface SDKOfferDefinition extends Resource {
@@ -490,10 +481,6 @@ export interface IMaxUsersPerDbAccountExceeded extends IPhoenixError {
}
export interface IPhoenixConnectionInfoResult {
readonly phoenixServiceInfo?: IPhoenixServiceInfo;
}
export interface IPhoenixServiceInfo {
readonly authToken?: string;
readonly phoenixServiceUrl?: string;
readonly forwardingId?: string;
@@ -575,16 +562,6 @@ export interface ContainerConnectionInfo {
//need to add ram and rom info
}
export interface PostgresFirewallRule {
id: string;
name: string;
type: string;
properties: {
startIpAddress: string;
endIpAddress: string;
};
}
export enum PhoenixErrorType {
MaxAllocationTimeExceeded = "MaxAllocationTimeExceeded",
MaxDbAccountsPerUserExceeded = "MaxDbAccountsPerUserExceeded",
@@ -594,5 +571,4 @@ export enum PhoenixErrorType {
SubscriptionNotAllowed = "SubscriptionNotAllowed",
UnknownError = "UnknownError",
PhoenixFlightFallback = "PhoenixFlightFallback",
UserMissingPermissionsError = "UserMissingPermissionsError",
}

View File

@@ -35,9 +35,6 @@ export enum MessageTypes {
RefreshDatabaseAccount,
CloseTab,
OpenQuickstartBlade,
OpenPostgreSQLPasswordReset,
OpenPostgresNetworkingBlade,
OpenCosmosDBNetworkingBlade,
}
export { Versions, ActionContracts, Diagnostics };

View File

@@ -87,13 +87,13 @@ export interface Database extends TreeNode {
isDatabaseExpanded: ko.Observable<boolean>;
isDatabaseShared: ko.Computed<boolean>;
isSampleDB?: boolean;
collectionsContinuationToken?: string;
selectedSubnodeKind: ko.Observable<CollectionTabKind>;
expandDatabase(): Promise<void>;
collapseDatabase(): void;
loadCollections(restart?: boolean): Promise<void>;
loadCollections(): Promise<void>;
findCollectionWithId(collectionId: string): Collection;
openAddCollection(database: Database, event: MouseEvent): void;
onSettingsClick: () => void;
@@ -186,6 +186,7 @@ export interface Collection extends CollectionBase {
onDrop(source: Collection, event: { originalEvent: DragEvent }): void;
uploadFiles(fileList: FileList): Promise<{ data: UploadDetailsRecord[] }>;
getLabel(): string;
getPendingThroughputSplitNotification(): Promise<DataModels.Notification>;
}
@@ -371,7 +372,6 @@ export enum TerminalKind {
Default = 0,
Mongo = 1,
Cassandra = 2,
Postgres = 3,
}
export interface DataExplorerInputsFrame {
@@ -395,11 +395,6 @@ export interface DataExplorerInputsFrame {
sharedThroughputDefault?: number;
dataExplorerVersion?: string;
defaultCollectionThroughput?: CollectionCreationDefaults;
isPostgresAccount?: boolean;
isReplica?: boolean;
clientIpAddress?: string;
// TODO: Update this param in the OSS extension to remove isFreeTier, isMarlinServerGroup, and make nodes a flat array instead of an nested array
connectionStringParams?: any;
flights?: readonly string[];
features?: {
[key: string]: string;

View File

@@ -11,9 +11,9 @@ import DeleteTriggerIcon from "../../images/DeleteTrigger.svg";
import DeleteUDFIcon from "../../images/DeleteUDF.svg";
import HostedTerminalIcon from "../../images/Hosted-Terminal.svg";
import * as ViewModels from "../Contracts/ViewModels";
import { useSidePanel } from "../hooks/useSidePanel";
import { userContext } from "../UserContext";
import { getCollectionName, getDatabaseName } from "../Utils/APITypeUtils";
import { useSidePanel } from "../hooks/useSidePanel";
import { TreeNodeMenuItem } from "./Controls/TreeComponent/TreeComponent";
import Explorer from "./Explorer";
import { useNotebook } from "./Notebook/useNotebook";
@@ -44,7 +44,7 @@ export const createDatabaseContextMenu = (container: Explorer, databaseId: strin
},
];
if (userContext.apiType !== "Tables" || userContext.features.enableSDKoperations) {
if (userContext.apiType !== "Tables") {
items.push({
iconSrc: DeleteDatabaseIcon,
onClick: () =>
@@ -152,7 +152,7 @@ export const createStoreProcedureContextMenuItems = (
{
iconSrc: DeleteSprocIcon,
onClick: () => storedProcedure.delete(),
label: "Delete Stored Procedure",
label: "Delete Store Procedure",
},
];
};

View File

@@ -73,7 +73,7 @@ export class AccordionItemComponent extends React.Component<AccordionItemCompone
<img
className="expandCollapseIcon"
src={this.state.isExpanded ? TriangleDownIcon : TriangleRightIcon}
alt={this.state.isExpanded ? `${this.props.title} hide` : `${this.props.title} expand`}
alt="Hide"
tabIndex={0}
role="button"
/>

View File

@@ -2,7 +2,6 @@
* Wrapper around Notebook server terminal
*/
import { useTerminal } from "hooks/useTerminal";
import postRobot from "post-robot";
import * as React from "react";
import * as DataModels from "../../../Contracts/DataModels";
@@ -41,7 +40,6 @@ export class NotebookTerminalComponent extends React.Component<NotebookTerminalC
handleFrameLoad(event: React.SyntheticEvent<HTMLIFrameElement, Event>): void {
this.terminalWindow = (event.target as HTMLIFrameElement).contentWindow;
useTerminal.getState().setTerminal(this.terminalWindow);
this.sendPropsToTerminalFrame();
}
@@ -76,8 +74,6 @@ export class NotebookTerminalComponent extends React.Component<NotebookTerminalC
this.props.databaseAccount?.properties.mongoEndpoint || this.props.databaseAccount?.properties.documentEndpoint;
} else if (StringUtils.endsWith(notebookServerEndpoint, "cassandra")) {
terminalEndpoint = this.props.databaseAccount?.properties.cassandraEndpoint;
} else if (StringUtils.endsWith(notebookServerEndpoint, "postgresql")) {
return this.props.databaseAccount?.properties.postgresqlEndpoint;
}
if (terminalEndpoint) {

View File

@@ -1,5 +1,5 @@
import { HoverCard, HoverCardType, Icon, Label, Link, Stack } from "@fluentui/react";
import * as React from "react";
import { Icon, Label, Stack, HoverCard, HoverCardType, Link } from "@fluentui/react";
import { CodeOfConductEndpoints } from "../../../../Common/Constants";
import "./InfoComponent.less";
@@ -41,7 +41,7 @@ export class InfoComponent extends React.Component<InfoComponentProps> {
public render(): JSX.Element {
return (
<HoverCard plainCardProps={{ onRenderPlainCard: this.onHover }} instantOpenOnClick type={HoverCardType.plain}>
<div className="infoPanelMain" tabIndex={0}>
<div className="infoPanelMain">
<Icon className="infoIconMain" iconName="Help" styles={{ root: { verticalAlign: "middle" } }} />
<Label className="infoLabelMain">Help</Label>
</div>

View File

@@ -12,7 +12,6 @@ exports[`InfoComponent renders 1`] = `
>
<div
className="infoPanelMain"
tabIndex={0}
>
<Icon
className="infoIconMain"

View File

@@ -1,29 +1,46 @@
import { shallow } from "enzyme";
import React from "react";
import { IColumn, Text } from "@fluentui/react";
import {
PriceBreakdown,
changeFeedPolicyToolTip,
conflictResolutionCustomToolTip,
conflictResolutionLwwTooltip,
getAutoPilotV3SpendElement,
getEstimatedSpendingElement,
getRuPriceBreakdown,
getThroughputApplyDelayedMessage,
getThroughputApplyLongDelayMessage,
getThroughputApplyShortDelayMessage,
getToolTipContainer,
indexingPolicynUnsavedWarningMessage,
manualToAutoscaleDisclaimerElement,
mongoIndexTransformationRefreshingMessage,
mongoIndexingPolicyAADError,
mongoIndexingPolicyDisclaimer,
renderMongoIndexTransformationRefreshMessage,
ttlWarning,
indexingPolicynUnsavedWarningMessage,
updateThroughputBeyondLimitWarningMessage,
updateThroughputDelayedApplyWarningMessage,
getThroughputApplyDelayedMessage,
getThroughputApplyShortDelayMessage,
getThroughputApplyLongDelayMessage,
getToolTipContainer,
conflictResolutionCustomToolTip,
changeFeedPolicyToolTip,
conflictResolutionLwwTooltip,
mongoIndexingPolicyDisclaimer,
mongoIndexingPolicyAADError,
mongoIndexTransformationRefreshingMessage,
renderMongoIndexTransformationRefreshMessage,
ManualEstimatedSpendingDisplayProps,
PriceBreakdown,
getRuPriceBreakdown,
} from "./SettingsRenderUtils";
class SettingsRenderUtilsTestComponent extends React.Component {
public render(): JSX.Element {
const costElement: JSX.Element = <></>;
const estimatedSpendingColumns: IColumn[] = [
{ key: "costType", name: "", fieldName: "costType", minWidth: 100, maxWidth: 200, isResizable: true },
{ key: "hourly", name: "Hourly", fieldName: "hourly", minWidth: 100, maxWidth: 200, isResizable: true },
{ key: "daily", name: "Daily", fieldName: "daily", minWidth: 100, maxWidth: 200, isResizable: true },
{ key: "monthly", name: "Monthly", fieldName: "monthly", minWidth: 100, maxWidth: 200, isResizable: true },
];
const estimatedSpendingItems: ManualEstimatedSpendingDisplayProps[] = [
{
costType: <Text>Current Cost</Text>,
hourly: <Text>$ 1.02</Text>,
daily: <Text>$ 24.48</Text>,
monthly: <Text>$ 744.6</Text>,
},
];
const priceBreakdown: PriceBreakdown = {
hourlyPrice: 1.02,
dailyPrice: 24.48,
@@ -35,11 +52,17 @@ class SettingsRenderUtilsTestComponent extends React.Component {
return (
<>
{getEstimatedSpendingElement(costElement, 1000, 2, priceBreakdown, false)}
{getAutoPilotV3SpendElement(1000, false)}
{getAutoPilotV3SpendElement(undefined, false)}
{getAutoPilotV3SpendElement(1000, true)}
{getAutoPilotV3SpendElement(undefined, true)}
{getEstimatedSpendingElement(estimatedSpendingColumns, estimatedSpendingItems, 1000, 2, priceBreakdown, false)}
{manualToAutoscaleDisclaimerElement}
{ttlWarning}
{indexingPolicynUnsavedWarningMessage}
{updateThroughputBeyondLimitWarningMessage}
{updateThroughputDelayedApplyWarningMessage}
{getThroughputApplyDelayedMessage(false, 1000, "RU/s", "sampleDb", "sampleCollection", 2000)}

View File

@@ -1,7 +1,10 @@
import {
DetailsList,
DetailsListLayoutMode,
DetailsRow,
ICheckboxStyles,
IChoiceGroupStyles,
IColumn,
IDetailsColumnStyles,
IDetailsListStyles,
IDetailsRowProps,
@@ -17,6 +20,7 @@ import {
Link,
MessageBar,
MessageBarType,
SelectionMode,
Spinner,
SpinnerSize,
Stack,
@@ -24,7 +28,8 @@ import {
} from "@fluentui/react";
import * as React from "react";
import { StyleConstants, Urls } from "../../../Common/Constants";
import { hoursInAMonth } from "../../../Shared/Constants";
import { AutopilotDocumentation, hoursInAMonth } from "../../../Shared/Constants";
import * as AutoPilotUtils from "../../../Utils/AutoPilotUtils";
import {
computeRUUsagePriceHourly,
estimatedCostDisclaimer,
@@ -98,10 +103,6 @@ export const checkBoxAndInputStackProps: Partial<IStackProps> = {
tokens: { childrenGap: 10 },
};
export const relaxedSpacingStackProps: Partial<IStackProps> = {
tokens: { childrenGap: 20 },
};
export const toolTipLabelStackTokens: IStackTokens = {
childrenGap: 6,
};
@@ -173,6 +174,41 @@ export function onRenderRow(props: IDetailsRowProps): JSX.Element {
return <DetailsRow {...props} styles={transparentDetailsRowStyles} />;
}
export const getAutoPilotV3SpendElement = (
maxAutoPilotThroughputSet: number,
isDatabaseThroughput: boolean,
requestUnitsUsageCostElement?: JSX.Element
): JSX.Element => {
if (!maxAutoPilotThroughputSet) {
return <></>;
}
const resource: string = isDatabaseThroughput ? "database" : "container";
return (
<>
<Text>
Your {resource} throughput will automatically scale from{" "}
<b>
{AutoPilotUtils.getMinRUsBasedOnUserInput(maxAutoPilotThroughputSet)} RU/s (10% of max RU/s) -{" "}
{maxAutoPilotThroughputSet} RU/s
</b>{" "}
based on usage.
<br />
</Text>
{requestUnitsUsageCostElement}
<Text>
After the first {AutoPilotUtils.getStorageBasedOnUserInput(maxAutoPilotThroughputSet)} GB of data stored, the
max RU/s will be automatically upgraded based on the new storage value.
<Link href={AutopilotDocumentation.Url} target="_blank">
{" "}
Learn more
</Link>
.
</Text>
</>
);
};
export const getRuPriceBreakdown = (
throughput: number,
serverId: string,
@@ -202,7 +238,8 @@ export const getRuPriceBreakdown = (
};
export const getEstimatedSpendingElement = (
costElement: JSX.Element,
estimatedSpendingColumns: IColumn[],
estimatedSpendingItems: EstimatedSpendingDisplayProps[],
throughput: number,
numberOfRegions: number,
priceBreakdown: PriceBreakdown,
@@ -210,25 +247,22 @@ export const getEstimatedSpendingElement = (
): JSX.Element => {
const ruRange: string = isAutoscale ? throughput / 10 + " RU/s - " : "";
return (
<Stack>
<Text style={{ fontWeight: 600 }}>Cost estimate*</Text>
{costElement}
<Text style={{ fontWeight: 600, marginTop: 15 }}>How we calculate this</Text>
<Stack id="throughputSpendElement" style={{ marginTop: 5 }}>
<span>
{numberOfRegions} region{numberOfRegions > 1 && <span>s</span>}
</span>
<span>
{ruRange}
{throughput} RU/s
</span>
<span>
{priceBreakdown.currencySign}
{priceBreakdown.pricePerRu}/RU
</span>
</Stack>
<Text style={{ marginTop: 15 }}>
<em>*{estimatedCostDisclaimer}</em>
<Stack {...addMongoIndexStackProps} styles={mediumWidthStackStyles}>
<DetailsList
disableSelectionZone
items={estimatedSpendingItems}
columns={estimatedSpendingColumns}
selectionMode={SelectionMode.none}
layoutMode={DetailsListLayoutMode.justified}
onRenderRow={onRenderRow}
/>
<Text id="throughputSpendElement">
({"regions: "} {numberOfRegions}, {ruRange}
{throughput} RU/s, {priceBreakdown.currencySign}
{priceBreakdown.pricePerRu}/RU)
</Text>
<Text>
<em>{estimatedCostDisclaimer}</em>
</Text>
</Stack>
);
@@ -259,6 +293,14 @@ export const indexingPolicynUnsavedWarningMessage: JSX.Element = (
</Text>
);
export const updateThroughputBeyondLimitWarningMessage: JSX.Element = (
<Text styles={infoAndToolTipTextStyle} id="updateThroughputBeyondLimitWarningMessage">
You are about to request an increase in throughput beyond the pre-allocated capacity. The service will scale out and
increase throughput for the selected container. This operation will take 1-3 business days to complete. You can
track the status of this request in Notifications.
</Text>
);
export const updateThroughputDelayedApplyWarningMessage: JSX.Element = (
<Text styles={infoAndToolTipTextStyle} id="updateThroughputDelayedApplyWarningMessage">
You are about to request an increase in throughput beyond the pre-allocated capacity. This operation will take some
@@ -266,61 +308,6 @@ export const updateThroughputDelayedApplyWarningMessage: JSX.Element = (
</Text>
);
export const getUpdateThroughputBeyondInstantLimitMessage = (instantMaximumThroughput: number): JSX.Element => {
return (
<Text styles={infoAndToolTipTextStyle} id="updateThroughputDelayedApplyWarningMessage">
Scaling up will take 4-6 hours as it exceeds what Azure Cosmos DB can instantly support currently based on your
number of physical partitions. You can increase your throughput to {instantMaximumThroughput} instantly or proceed
with this value and wait until the scale-up is completed.
</Text>
);
};
export const getUpdateThroughputBeyondSupportLimitMessage = (
instantMaximumThroughput: number,
maximumThroughput: number
): JSX.Element => {
return (
<>
<Text styles={infoAndToolTipTextStyle} id="updateThroughputDelayedApplyWarningMessage">
Your request to increase throughput exceeds the pre-allocated capacity which may take longer than expected.
There are three options you can choose from to proceed:
</Text>
<ol style={{ fontSize: 14, color: "windowtext", marginTop: "5px" }}>
<li>You can instantly scale up to {instantMaximumThroughput} RU/s.</li>
{instantMaximumThroughput < maximumThroughput && (
<li>You can asynchronously scale up to any value under {maximumThroughput} RU/s in 4-6 hours.</li>
)}
<li>
Your current quota max is {maximumThroughput} RU/s. To go over this limit, you must request a quota increase
and the Azure Cosmos DB team will review.
<Link
href="https://learn.microsoft.com/en-us/azure/cosmos-db/nosql/create-support-request-quota-increase"
target="_blank"
>
Learn more
</Link>
</li>
</ol>
</>
);
};
export const getUpdateThroughputBelowMinimumMessage = (minimum: number): JSX.Element => {
return (
<Text styles={infoAndToolTipTextStyle}>
You are not able to lower throughput below your current minimum of {minimum} RU/s. For more information on this
limit, please refer to our service quote documentation.
<Link
href="https://learn.microsoft.com/en-us/azure/cosmos-db/concepts-limits#minimum-throughput-limits"
target="_blank"
>
Learn more
</Link>
</Text>
);
};
export const saveThroughputWarningMessage: JSX.Element = (
<Text styles={infoAndToolTipTextStyle}>
Your bill will be affected as you update your throughput settings. Please review the updated cost estimate below
@@ -512,11 +499,7 @@ export const getTextFieldStyles = (current: isDirtyTypes, baseline: isDirtyTypes
},
});
export const getChoiceGroupStyles = (
current: isDirtyTypes,
baseline: isDirtyTypes,
isHorizontal?: boolean
): Partial<IChoiceGroupStyles> => ({
export const getChoiceGroupStyles = (current: isDirtyTypes, baseline: isDirtyTypes): Partial<IChoiceGroupStyles> => ({
flexContainer: [
{
selectors: {
@@ -533,8 +516,6 @@ export const getChoiceGroupStyles = (
padding: "2px 5px",
},
},
display: isHorizontal ? "inline-flex" : "default",
columnGap: isHorizontal ? "30px" : "default",
},
],
});

View File

@@ -3,6 +3,7 @@ import ko from "knockout";
import React from "react";
import * as Constants from "../../../../Common/Constants";
import * as DataModels from "../../../../Contracts/DataModels";
import * as SharedConstants from "../../../../Shared/Constants";
import { updateUserContext } from "../../../../UserContext";
import Explorer from "../../../Explorer";
import { throughputUnit } from "../SettingsRenderUtils";
@@ -11,6 +12,7 @@ import { ScaleComponent, ScaleComponentProps } from "./ScaleComponent";
import { ThroughputInputAutoPilotV3Component } from "./ThroughputInputComponents/ThroughputInputAutoPilotV3Component";
describe("ScaleComponent", () => {
const nonNationalCloudContainer = new Explorer();
const targetThroughput = 6000;
const baseProps: ScaleComponentProps = {
@@ -123,4 +125,11 @@ describe("ScaleComponent", () => {
scaleComponent = new ScaleComponent(newProps);
expect(scaleComponent.canThroughputExceedMaximumValue()).toEqual(true);
});
it("getThroughputWarningMessage", () => {
const throughputBeyondLimit = SharedConstants.CollectionCreation.DefaultCollectionRUs1Million + 1000;
const newProps = { ...baseProps, container: nonNationalCloudContainer, throughput: throughputBeyondLimit };
const scaleComponent = new ScaleComponent(newProps);
expect(scaleComponent.getThroughputWarningMessage().props.id).toEqual("updateThroughputBeyondLimitWarningMessage");
});
});

View File

@@ -1,7 +1,7 @@
import { Link, MessageBar, MessageBarType, Stack, Text, TextField } from "@fluentui/react";
import { Label, Link, MessageBar, MessageBarType, Stack, Text, TextField } from "@fluentui/react";
import * as React from "react";
import * as Constants from "../../../../Common/Constants";
import { Platform, configContext } from "../../../../ConfigContext";
import { configContext, Platform } from "../../../../ConfigContext";
import * as DataModels from "../../../../Contracts/DataModels";
import * as ViewModels from "../../../../Contracts/ViewModels";
import * as SharedConstants from "../../../../Shared/Constants";
@@ -15,6 +15,7 @@ import {
subComponentStackProps,
throughputUnit,
titleAndInputStackProps,
updateThroughputBeyondLimitWarningMessage,
} from "../SettingsRenderUtils";
import { hasDatabaseSharedThroughput } from "../SettingsUtils";
import { ThroughputInputAutoPilotV3Component } from "./ThroughputInputComponents/ThroughputInputAutoPilotV3Component";
@@ -67,6 +68,16 @@ export class ScaleComponent extends React.Component<ScaleComponentProps> {
return !!enableAutoScaleCapability;
};
private getStorageCapacityTitle = (): JSX.Element => {
const capacity: string = this.props.isFixedContainer ? "Fixed" : "Unlimited";
return (
<Stack {...titleAndInputStackProps}>
<Label>Storage capacity</Label>
<Text>{capacity}</Text>
</Stack>
);
};
public getMaxRUs = (): number => {
if (userContext.isTryCosmosDBSubscription) {
return Constants.TryCosmosExperience.maxRU;
@@ -120,6 +131,18 @@ export class ScaleComponent extends React.Component<ScaleComponentProps> {
return undefined;
};
public getThroughputWarningMessage = (): JSX.Element => {
const throughputExceedsBackendLimits: boolean =
this.canThroughputExceedMaximumValue() &&
this.props.throughput > SharedConstants.CollectionCreation.DefaultCollectionRUs1Million;
if (throughputExceedsBackendLimits && !this.props.isFixedContainer) {
return updateThroughputBeyondLimitWarningMessage;
}
return undefined;
};
public getLongDelayMessage = (): JSX.Element => {
const matches: string[] = this.props.initialNotification?.description.match(
`Throughput update for (.*) ${throughputUnit}`
@@ -165,10 +188,9 @@ export class ScaleComponent extends React.Component<ScaleComponentProps> {
spendAckChecked={false}
onScaleSaveableChange={this.props.onScaleSaveableChange}
onScaleDiscardableChange={this.props.onScaleDiscardableChange}
getThroughputWarningMessage={this.getThroughputWarningMessage}
usageSizeInKB={this.props.collection?.usageSizeInKB()}
throughputError={this.props.throughputError}
instantMaximumThroughput={this.offer?.instantMaximumThroughput}
softAllowedMaximumThroughput={this.offer?.softAllowedMaximumThroughput}
/>
);
@@ -207,7 +229,12 @@ export class ScaleComponent extends React.Component<ScaleComponentProps> {
{this.getInitialNotificationElement() && (
<MessageBar messageBarType={MessageBarType.warning}>{this.getInitialNotificationElement()}</MessageBar>
)}
{!this.isAutoScaleEnabled() && <Stack {...subComponentStackProps}>{this.getThroughputInputComponent()}</Stack>}
{!this.isAutoScaleEnabled() && (
<Stack {...subComponentStackProps}>
{this.getThroughputInputComponent()}
{!this.props.database && this.getStorageCapacityTitle()}
</Stack>
)}
{/* TODO: Replace link with call to the Azure Support blade */}
{this.isAutoScaleEnabled() && (

View File

@@ -310,16 +310,7 @@ export class SubSettingsComponent extends React.Component<SubSettingsComponentPr
/>
)}
{userContext.apiType === "SQL" && this.isLargePartitionKeyEnabled() && (
<Text>Large {this.partitionKeyName.toLowerCase()} has been enabled.</Text>
)}
{userContext.apiType === "SQL" &&
(this.isHierarchicalPartitionedContainer() ? (
<Text>Hierarchically partitioned container.</Text>
) : (
<Text>Non-hierarchically partitioned container.</Text>
))}
{this.isLargePartitionKeyEnabled() && <Text>Large {this.partitionKeyName.toLowerCase()} has been enabled</Text>}
</Stack>
);
@@ -337,7 +328,6 @@ export class SubSettingsComponent extends React.Component<SubSettingsComponentPr
};
public isLargePartitionKeyEnabled = (): boolean => this.props.collection.partitionKey?.version >= 2;
public isHierarchicalPartitionedContainer = (): boolean => this.props.collection.partitionKey?.kind === "MultiHash";
public render(): JSX.Element {
return (

View File

@@ -42,8 +42,7 @@ describe("ThroughputInputAutoPilotV3Component", () => {
onScaleDiscardableChange: () => {
return;
},
instantMaximumThroughput: 5000,
softAllowedMaximumThroughput: 1000000,
getThroughputWarningMessage: () => undefined,
};
it("throughput input visible", () => {

View File

@@ -3,14 +3,10 @@ import {
ChoiceGroup,
FontIcon,
IChoiceGroupOption,
IProgressIndicatorStyles,
ISeparatorStyles,
IColumn,
Label,
Link,
MessageBar,
MessageBarType,
ProgressIndicator,
Separator,
Stack,
Text,
TextField,
@@ -27,24 +23,24 @@ import { autoPilotThroughput1K } from "../../../../../Utils/AutoPilotUtils";
import { calculateEstimateNumber, usageInGB } from "../../../../../Utils/PricingUtils";
import { Int32 } from "../../../../Panes/Tables/Validators/EntityPropertyValidationCommon";
import {
PriceBreakdown,
AutoscaleEstimatedSpendingDisplayProps,
checkBoxAndInputStackProps,
getAutoPilotV3SpendElement,
getChoiceGroupStyles,
getEstimatedSpendingElement,
getRuPriceBreakdown,
getTextFieldStyles,
getToolTipContainer,
getUpdateThroughputBelowMinimumMessage,
getUpdateThroughputBeyondInstantLimitMessage,
getUpdateThroughputBeyondSupportLimitMessage,
ManualEstimatedSpendingDisplayProps,
manualToAutoscaleDisclaimerElement,
messageBarStyles,
noLeftPaddingCheckBoxStyle,
relaxedSpacingStackProps,
PriceBreakdown,
saveThroughputWarningMessage,
titleAndInputStackProps,
transparentDetailsHeaderStyle,
} from "../../SettingsRenderUtils";
import { IsComponentDirtyResult, getSanitizedInputValue, isDirty } from "../../SettingsUtils";
import { getSanitizedInputValue, IsComponentDirtyResult, isDirty } from "../../SettingsUtils";
import { ToolTipLabelComponent } from "../ToolTipLabelComponent";
export interface ThroughputInputAutoPilotV3Props {
@@ -77,16 +73,16 @@ export interface ThroughputInputAutoPilotV3Props {
onMaxAutoPilotThroughputChange: (newThroughput: number) => void;
onScaleSaveableChange: (isScaleSaveable: boolean) => void;
onScaleDiscardableChange: (isScaleDiscardable: boolean) => void;
getThroughputWarningMessage: () => JSX.Element;
usageSizeInKB: number;
throughputError?: string;
instantMaximumThroughput: number;
softAllowedMaximumThroughput: number;
}
interface ThroughputInputAutoPilotV3State {
spendAckChecked: boolean;
exceedFreeTierThroughput: boolean;
}
export class ThroughputInputAutoPilotV3Component extends React.Component<
ThroughputInputAutoPilotV3Props,
ThroughputInputAutoPilotV3State
@@ -191,15 +187,7 @@ export class ThroughputInputAutoPilotV3Component extends React.Component<
let estimatedSpend: JSX.Element;
if (this.props.isAutoPilotSelected) {
estimatedSpend = this.getEstimatedAutoscaleSpendElement(
this.props.maxAutoPilotThroughputBaseline,
userContext.portalEnv,
regions,
multimaster,
isDirty ? this.props.maxAutoPilotThroughput : undefined
);
} else {
if (!this.props.isAutoPilotSelected) {
estimatedSpend = this.getEstimatedManualSpendElement(
// if migrating from autoscale to manual, we use the autoscale RUs value as that is what will be set...
this.overrideWithAutoPilotSettings() ? this.props.maxAutoPilotThroughput : this.props.throughputBaseline,
@@ -208,6 +196,14 @@ export class ThroughputInputAutoPilotV3Component extends React.Component<
multimaster,
isDirty ? this.props.throughput : undefined
);
} else {
estimatedSpend = this.getEstimatedAutoscaleSpendElement(
this.props.maxAutoPilotThroughputBaseline,
userContext.portalEnv,
regions,
multimaster,
isDirty ? this.props.maxAutoPilotThroughput : undefined
);
}
return estimatedSpend;
};
@@ -220,8 +216,52 @@ export class ThroughputInputAutoPilotV3Component extends React.Component<
newThroughput?: number
): JSX.Element => {
const prices: PriceBreakdown = getRuPriceBreakdown(throughput, serverId, numberOfRegions, isMultimaster, true);
const estimatedSpendingColumns: IColumn[] = [
{
key: "costType",
name: "",
fieldName: "costType",
minWidth: 100,
maxWidth: 200,
isResizable: true,
styles: transparentDetailsHeaderStyle,
},
{
key: "minPerMonth",
name: "Min Per Month",
fieldName: "minPerMonth",
minWidth: 100,
maxWidth: 200,
isResizable: true,
styles: transparentDetailsHeaderStyle,
},
{
key: "maxPerMonth",
name: "Max Per Month",
fieldName: "maxPerMonth",
minWidth: 100,
maxWidth: 200,
isResizable: true,
styles: transparentDetailsHeaderStyle,
},
];
const estimatedSpendingItems: AutoscaleEstimatedSpendingDisplayProps[] = [
{
costType: <Text>Current Cost</Text>,
minPerMonth: (
<Text>
{prices.currencySign} {calculateEstimateNumber(prices.monthlyPrice / 10)}
</Text>
),
maxPerMonth: (
<Text>
{prices.currencySign} {calculateEstimateNumber(prices.monthlyPrice)}
</Text>
),
},
];
const newThroughputCostElement = (): JSX.Element => {
if (newThroughput) {
const newPrices: PriceBreakdown = getRuPriceBreakdown(
newThroughput,
serverId,
@@ -229,40 +269,37 @@ export class ThroughputInputAutoPilotV3Component extends React.Component<
isMultimaster,
true
);
return (
<div>
<Text style={{ fontWeight: 600 }}>Updated cost per month</Text>
<Stack horizontal style={{ marginTop: 5, marginBottom: 10 }}>
<Text style={{ width: "50%" }}>
{newPrices.currencySign} {calculateEstimateNumber(newPrices.monthlyPrice / 10)} min
</Text>
<Text style={{ width: "50%" }}>
{newPrices.currencySign} {calculateEstimateNumber(newPrices.monthlyPrice)} max
</Text>
</Stack>
</div>
);
};
estimatedSpendingItems.unshift({
costType: (
<Text>
<b>Updated Cost</b>
</Text>
),
minPerMonth: (
<Text>
<b>
{newPrices.currencySign} {calculateEstimateNumber(newPrices.monthlyPrice / 10)}
</b>
</Text>
),
maxPerMonth: (
<Text>
<b>
{newPrices.currencySign} {calculateEstimateNumber(newPrices.monthlyPrice)}
</b>
</Text>
),
});
}
const costElement = (): JSX.Element => {
const prices: PriceBreakdown = getRuPriceBreakdown(throughput, serverId, numberOfRegions, isMultimaster, true);
return (
<Stack {...checkBoxAndInputStackProps} style={{ marginTop: 15 }}>
{newThroughput && newThroughputCostElement()}
<Text style={{ fontWeight: 600 }}>Current cost per month</Text>
<Stack horizontal style={{ marginTop: 5 }}>
<Text style={{ width: "50%" }}>
{prices.currencySign} {calculateEstimateNumber(prices.monthlyPrice / 10)} min
</Text>
<Text style={{ width: "50%" }}>
{prices.currencySign} {calculateEstimateNumber(prices.monthlyPrice)} max
</Text>
</Stack>
</Stack>
);
};
return getEstimatedSpendingElement(costElement(), newThroughput ?? throughput, numberOfRegions, prices, true);
return getEstimatedSpendingElement(
estimatedSpendingColumns,
estimatedSpendingItems,
newThroughput ?? throughput,
numberOfRegions,
prices,
true
);
};
private getEstimatedManualSpendElement = (
@@ -273,55 +310,122 @@ export class ThroughputInputAutoPilotV3Component extends React.Component<
newThroughput?: number
): JSX.Element => {
const prices: PriceBreakdown = getRuPriceBreakdown(throughput, serverId, numberOfRegions, isMultimaster, false);
const estimatedSpendingColumns: IColumn[] = [
{
key: "costType",
name: "",
fieldName: "costType",
minWidth: 100,
maxWidth: 200,
isResizable: true,
styles: transparentDetailsHeaderStyle,
},
{
key: "hourly",
name: "Hourly",
fieldName: "hourly",
minWidth: 100,
maxWidth: 200,
isResizable: true,
styles: transparentDetailsHeaderStyle,
},
{
key: "daily",
name: "Daily",
fieldName: "daily",
minWidth: 100,
maxWidth: 200,
isResizable: true,
styles: transparentDetailsHeaderStyle,
},
{
key: "monthly",
name: "Monthly",
fieldName: "monthly",
minWidth: 100,
maxWidth: 200,
isResizable: true,
styles: transparentDetailsHeaderStyle,
},
];
const estimatedSpendingItems: ManualEstimatedSpendingDisplayProps[] = [
{
costType: <Text>Current Cost</Text>,
hourly: (
<Text>
{prices.currencySign} {calculateEstimateNumber(prices.hourlyPrice)}
</Text>
),
daily: (
<Text>
{prices.currencySign} {calculateEstimateNumber(prices.dailyPrice)}
</Text>
),
monthly: (
<Text>
{prices.currencySign} {calculateEstimateNumber(prices.monthlyPrice)}
</Text>
),
},
];
const newThroughputCostElement = (): JSX.Element => {
if (newThroughput) {
const newPrices: PriceBreakdown = getRuPriceBreakdown(
newThroughput,
serverId,
numberOfRegions,
isMultimaster,
true
false
);
return (
<div>
<Text style={{ fontWeight: 600 }}>Updated cost per month</Text>
<Stack horizontal style={{ marginTop: 5, marginBottom: 10 }}>
<Text style={{ width: "33%" }}>
{newPrices.currencySign} {calculateEstimateNumber(newPrices.hourlyPrice)}/hr
</Text>
<Text style={{ width: "33%" }}>
{newPrices.currencySign} {calculateEstimateNumber(newPrices.dailyPrice)}/day
</Text>
<Text style={{ width: "33%" }}>
{newPrices.currencySign} {calculateEstimateNumber(newPrices.monthlyPrice)}/mo
</Text>
</Stack>
</div>
);
};
estimatedSpendingItems.unshift({
costType: (
<Text>
<b>Updated Cost</b>
</Text>
),
hourly: (
<Text>
<b>
{newPrices.currencySign} {calculateEstimateNumber(newPrices.hourlyPrice)}
</b>
</Text>
),
daily: (
<Text>
<b>
{newPrices.currencySign} {calculateEstimateNumber(newPrices.dailyPrice)}
</b>
</Text>
),
monthly: (
<Text>
<b>
{newPrices.currencySign} {calculateEstimateNumber(newPrices.monthlyPrice)}
</b>
</Text>
),
});
}
const costElement = (): JSX.Element => {
const prices: PriceBreakdown = getRuPriceBreakdown(throughput, serverId, numberOfRegions, isMultimaster, true);
return (
<Stack {...checkBoxAndInputStackProps} style={{ marginTop: 15 }}>
{newThroughput && newThroughputCostElement()}
<Text style={{ fontWeight: 600 }}>Current cost per month</Text>
<Stack horizontal style={{ marginTop: 5 }}>
<Text style={{ width: "33%" }}>
{prices.currencySign} {calculateEstimateNumber(prices.hourlyPrice)}/hr
</Text>
<Text style={{ width: "33%" }}>
{prices.currencySign} {calculateEstimateNumber(prices.dailyPrice)}/day
</Text>
<Text style={{ width: "33%" }}>
{prices.currencySign} {calculateEstimateNumber(prices.monthlyPrice)}/mo
</Text>
</Stack>
</Stack>
);
};
return getEstimatedSpendingElement(
estimatedSpendingColumns,
estimatedSpendingItems,
newThroughput ?? throughput,
numberOfRegions,
prices,
false
);
};
return getEstimatedSpendingElement(costElement(), newThroughput ?? throughput, numberOfRegions, prices, false);
private getAutoPilotUsageCost = (): JSX.Element => {
if (!this.props.maxAutoPilotThroughput) {
return <></>;
}
return getAutoPilotV3SpendElement(
this.props.maxAutoPilotThroughput,
false /* isDatabaseThroughput */,
!this.props.isEmulator ? this.getRequestUnitsUsageCost() : <></>
);
};
private onAutoPilotThroughputChange = (
@@ -408,7 +512,7 @@ export class ThroughputInputAutoPilotV3Component extends React.Component<
onChange={this.onChoiceGroupChange}
required={this.props.showAsMandatory}
ariaLabelledBy={labelId}
styles={getChoiceGroupStyles(this.props.wasAutopilotOriginallySet, this.props.isAutoPilotSelected, true)}
styles={getChoiceGroupStyles(this.props.wasAutopilotOriginallySet, this.props.isAutoPilotSelected)}
/>
</Stack>
);
@@ -417,266 +521,97 @@ export class ThroughputInputAutoPilotV3Component extends React.Component<
private onSpendAckChecked = (ev?: React.FormEvent<HTMLElement | HTMLInputElement>, checked?: boolean): void =>
this.setState({ spendAckChecked: checked });
private getStorageCapacityTitle = (): JSX.Element => {
const capacity: string = this.props.isFixed ? "Fixed" : "Unlimited";
return (
<Stack {...titleAndInputStackProps}>
<Label>Storage capacity</Label>
<Text>{capacity}</Text>
</Stack>
);
};
private thoughputRangeSeparatorStyles: Partial<ISeparatorStyles> = {
root: [
{
selectors: {
"::before": {
backgroundColor: "rgb(200, 200, 200)",
height: "3px",
marginTop: "-1px",
},
},
},
],
};
private currentThroughputValue = (): number => {
return this.props.isAutoPilotSelected
? this.props.maxAutoPilotThroughput
: this.overrideWithAutoPilotSettings()
? this.props.maxAutoPilotThroughputBaseline
: this.props.throughput;
};
private getCurrentRuRange = (): "below" | "instant" | "delayed" | "requireSupport" => {
if (this.currentThroughputValue() < this.props.minimum) {
return "below";
}
if (
this.currentThroughputValue() >= this.props.minimum &&
this.currentThroughputValue() <= this.props.instantMaximumThroughput
) {
return "instant";
}
if (this.currentThroughputValue() > this.props.softAllowedMaximumThroughput) {
return "requireSupport";
}
return "delayed";
};
private getRuThermometerStyles = (): Partial<IProgressIndicatorStyles> => ({
progressBar: [
{
backgroundColor:
this.getCurrentRuRange() === "instant"
? "rgb(0, 120, 212)"
: this.getCurrentRuRange() === "delayed"
? "rgb(255 216 109)"
: "rgb(251, 217, 203)",
},
],
});
private getRuThermometerPercentValue = (): number => {
let percentValue: number;
const currentRus = this.currentThroughputValue();
switch (this.getCurrentRuRange()) {
case "below":
percentValue = 0;
break;
case "instant": {
const percentOfInstantRange: number = currentRus / this.props.instantMaximumThroughput;
percentValue = percentOfInstantRange * 0.34;
break;
}
case "delayed": {
const adjustedMax = this.props.softAllowedMaximumThroughput - this.props.instantMaximumThroughput;
const adjustedRus = currentRus - this.props.instantMaximumThroughput;
const percentOfDelayedRange = adjustedRus / adjustedMax;
const adjustedPercent = percentOfDelayedRange * 0.66;
percentValue = adjustedPercent + 0.34;
break;
}
default:
// over maximum
percentValue = 1;
}
return percentValue;
};
private getRUThermometer = (): JSX.Element => (
<Stack>
<Stack horizontal>
<Stack.Item style={{ width: "34%" }}>
<span>{this.props.minimum.toLocaleString()}</span>
</Stack.Item>
<Stack.Item style={{ width: "66%" }}>
<span style={{ float: "left", transform: "translateX(-50%)" }}>
{this.props.instantMaximumThroughput.toLocaleString()}
</span>
<span style={{ float: "right" }}>{this.props.softAllowedMaximumThroughput.toLocaleString()}</span>
</Stack.Item>
</Stack>
<ProgressIndicator
barHeight={20}
percentComplete={this.getRuThermometerPercentValue()}
styles={this.getRuThermometerStyles()}
/>
<Stack horizontal>
<Stack.Item style={{ width: "34%", paddingRight: "5px" }}>
<Separator styles={this.thoughputRangeSeparatorStyles}>Instant</Separator>
</Stack.Item>
<Stack.Item style={{ width: "66%", paddingLeft: "5px" }}>
<Separator styles={this.thoughputRangeSeparatorStyles}>4-6 hrs</Separator>
</Stack.Item>
</Stack>
</Stack>
);
private showThroughputWarning = (): boolean => {
return (
this.currentThroughputValue() > this.props.instantMaximumThroughput ||
this.currentThroughputValue() < this.props.minimum
);
};
private getThroughputWarningMessageText = (): JSX.Element => {
switch (this.getCurrentRuRange()) {
case "below":
return getUpdateThroughputBelowMinimumMessage(this.props.minimum);
case "delayed":
return getUpdateThroughputBeyondInstantLimitMessage(this.props.instantMaximumThroughput);
case "requireSupport":
return getUpdateThroughputBeyondSupportLimitMessage(
this.props.instantMaximumThroughput,
this.props.softAllowedMaximumThroughput
);
default:
return <></>;
}
};
private getThroughputWarningMessageBar = (): JSX.Element => {
const isSevereWarning: boolean =
this.currentThroughputValue() > this.props.softAllowedMaximumThroughput ||
this.currentThroughputValue() < this.props.minimum;
return (
<MessageBar messageBarType={isSevereWarning ? MessageBarType.severeWarning : MessageBarType.warning}>
{this.getThroughputWarningMessageText()}
</MessageBar>
);
};
private getThroughputTextField = (): JSX.Element => (
private renderAutoPilotInput = (): JSX.Element => (
<>
{this.props.isAutoPilotSelected ? (
<TextField
label="Maximum RU/s required by this resource"
required
type="number"
id="autopilotInput"
key="auto pilot throughput input"
styles={getTextFieldStyles(this.props.maxAutoPilotThroughput, this.props.maxAutoPilotThroughputBaseline)}
disabled={this.overrideWithProvisionedThroughputSettings()}
step={AutoPilotUtils.autoPilotIncrementStep}
value={this.overrideWithProvisionedThroughputSettings() ? "" : this.props.maxAutoPilotThroughput?.toString()}
onChange={this.onAutoPilotThroughputChange}
min={autoPilotThroughput1K}
onGetErrorMessage={(value: string) => {
const sanitizedValue = getSanitizedInputValue(value);
return sanitizedValue % 1000
? "Throughput value must be in increments of 1000"
: this.props.throughputError;
}}
validateOnLoad={false}
/>
) : (
<TextField
required
type="number"
id="throughputInput"
key="provisioned throughput input"
styles={getTextFieldStyles(this.props.throughput, this.props.throughputBaseline)}
disabled={this.overrideWithAutoPilotSettings()}
step={this.step}
value={
this.overrideWithAutoPilotSettings()
? this.props.maxAutoPilotThroughputBaseline?.toString()
: this.props.throughput?.toString()
}
onChange={this.onThroughputChange}
min={this.props.minimum}
errorMessage={this.props.throughputError}
<Text>
Provision maximum RU/s required by this resource. Estimate your required RU/s with
<Link target="_blank" href="https://cosmos.azure.com/capacitycalculator/">
{` capacity calculator`}
</Link>
</Text>
<TextField
label="Max RU/s"
required
type="number"
id="autopilotInput"
key="auto pilot throughput input"
styles={getTextFieldStyles(this.props.maxAutoPilotThroughput, this.props.maxAutoPilotThroughputBaseline)}
disabled={this.overrideWithProvisionedThroughputSettings()}
step={AutoPilotUtils.autoPilotIncrementStep}
value={this.overrideWithProvisionedThroughputSettings() ? "" : this.props.maxAutoPilotThroughput?.toString()}
onChange={this.onAutoPilotThroughputChange}
min={autoPilotThroughput1K}
errorMessage={this.props.throughputError}
/>
{!this.overrideWithProvisionedThroughputSettings() && this.getAutoPilotUsageCost()}
{this.minRUperGBSurvey()}
{this.props.spendAckVisible && (
<Checkbox
id="spendAckCheckBox"
styles={noLeftPaddingCheckBoxStyle}
label={this.props.spendAckText}
checked={this.state.spendAckChecked}
onChange={this.onSpendAckChecked}
/>
)}
{this.props.isFixed && <p>When using a collection with fixed storage capacity, you can set up to 10,000 RU/s.</p>}
</>
);
private renderThroughputComponent = (): JSX.Element => (
<Stack horizontal>
<Stack.Item style={{ width: "70%", maxWidth: "700px" }}>
<Stack {...relaxedSpacingStackProps} style={{ paddingRight: "50px" }}>
{this.getThroughputTextField()}
{this.props.instantMaximumThroughput && (
<Stack>
{this.getRUThermometer()}
{this.showThroughputWarning() && this.getThroughputWarningMessageBar()}
</Stack>
)}
{this.props.isAutoPilotSelected ? (
<Text style={{ marginTop: "40px" }}>
Based on usage, your {this.props.collectionName ? "container" : "database"} throughput will scale from{" "}
<b>
{AutoPilotUtils.getMinRUsBasedOnUserInput(this.props.maxAutoPilotThroughput)} RU/s (10% of max RU/s) -{" "}
{this.props.maxAutoPilotThroughput} RU/s
</b>
<br />
</Text>
) : (
<>
{this.state.exceedFreeTierThroughput && (
<MessageBar
messageBarIconProps={{ iconName: "WarningSolid", className: "messageBarWarningIcon" }}
styles={messageBarStyles}
style={{ marginTop: "40px" }}
>
{`Billing will apply if you provision more than ${SharedConstants.FreeTierLimits.RU} RU/s of manual throughput, or if the resource scales beyond ${SharedConstants.FreeTierLimits.RU} RU/s with autoscale.`}
</MessageBar>
)}
</>
)}
{!this.overrideWithProvisionedThroughputSettings() && (
<Text>
Estimate your required RU/s with
<Link target="_blank" href="https://cosmos.azure.com/capacitycalculator/">
{` capacity calculator`} <FontIcon iconName="NavigateExternalInline" />
</Link>
</Text>
)}
{this.minRUperGBSurvey()}
{this.props.spendAckVisible && (
<Checkbox
id="spendAckCheckBox"
styles={noLeftPaddingCheckBoxStyle}
label={this.props.spendAckText}
checked={this.state.spendAckChecked}
onChange={this.onSpendAckChecked}
/>
)}
{this.props.isFixed && (
<p>When using a collection with fixed storage capacity, you can set up to 10,000 RU/s.</p>
)}
{this.props.collectionName && (
<Stack.Item style={{ marginTop: "40px" }}>{this.getStorageCapacityTitle()}</Stack.Item>
)}
</Stack>
</Stack.Item>
<Stack.Item style={{ width: "30%", maxWidth: "300px" }}>
{!this.props.isEmulator ? this.getRequestUnitsUsageCost() : <></>}
</Stack.Item>
private renderThroughputInput = (): JSX.Element => (
<Stack {...titleAndInputStackProps}>
<Text>
Estimate your required throughput with
<Link target="_blank" href="https://cosmos.azure.com/capacitycalculator/">
{` capacity calculator`} <FontIcon iconName="NavigateExternalInline" />
</Link>
</Text>
<TextField
required
type="number"
id="throughputInput"
key="provisioned throughput input"
styles={getTextFieldStyles(this.props.throughput, this.props.throughputBaseline)}
disabled={this.overrideWithAutoPilotSettings()}
step={this.step}
value={
this.overrideWithAutoPilotSettings()
? this.props.maxAutoPilotThroughputBaseline?.toString()
: this.props.throughput?.toString()
}
onChange={this.onThroughputChange}
min={this.props.minimum}
errorMessage={this.props.throughputError}
/>
{this.state.exceedFreeTierThroughput && (
<MessageBar
messageBarIconProps={{ iconName: "WarningSolid", className: "messageBarWarningIcon" }}
styles={messageBarStyles}
>
{`Billing will apply if you provision more than ${SharedConstants.FreeTierLimits.RU} RU/s of manual throughput, or if the resource scales beyond ${SharedConstants.FreeTierLimits.RU} RU/s with autoscale.`}
</MessageBar>
)}
{this.props.getThroughputWarningMessage() && (
<MessageBar
messageBarIconProps={{ iconName: "InfoSolid", className: "messageBarInfoIcon" }}
styles={messageBarStyles}
>
{this.props.getThroughputWarningMessage()}
</MessageBar>
)}
{!this.props.isEmulator && this.getRequestUnitsUsageCost()}
{this.minRUperGBSurvey()}
{this.props.spendAckVisible && (
<Checkbox
id="spendAckCheckBox"
styles={noLeftPaddingCheckBoxStyle}
label={this.props.spendAckText}
checked={this.state.spendAckChecked}
onChange={this.onSpendAckChecked}
/>
)}
<br />
{this.props.isFixed && <p>When using a collection with fixed storage capacity, you can set up to 10,000 RU/s.</p>}
</Stack>
);
@@ -689,10 +624,7 @@ export class ThroughputInputAutoPilotV3Component extends React.Component<
return (
<>
{warningMessage && (
<MessageBar
messageBarIconProps={{ iconName: "WarningSolid", className: "messageBarWarningIcon" }}
role="alert"
>
<MessageBar messageBarIconProps={{ iconName: "WarningSolid", className: "messageBarWarningIcon" }}>
{warningMessage}
</MessageBar>
)}
@@ -706,7 +638,7 @@ export class ThroughputInputAutoPilotV3Component extends React.Component<
{this.renderWarningMessage()}
{this.renderThroughputModeChoices()}
{this.renderThroughputComponent()}
{this.props.isAutoPilotSelected ? this.renderAutoPilotInput() : this.renderThroughputInput()}
</Stack>
);
}

View File

@@ -28,8 +28,6 @@ exports[`ConflictResolutionComponent Path text field displayed 1`] = `
Object {
"flexContainer": Array [
Object {
"columnGap": "default",
"display": "default",
"selectors": Object {
".ms-ChoiceField-field.is-checked::after": Object {
"borderColor": undefined,
@@ -102,8 +100,6 @@ exports[`ConflictResolutionComponent Sproc text field displayed 1`] = `
Object {
"flexContainer": Array [
Object {
"columnGap": "default",
"display": "default",
"selectors": Object {
".ms-ChoiceField-field.is-checked::after": Object {
"borderColor": "",

View File

@@ -39,6 +39,7 @@ exports[`ScaleComponent renders with correct initial notification 1`] = `
canExceedMaximumValue={true}
collectionName="test"
databaseName="test"
getThroughputWarningMessage={[Function]}
isAutoPilotSelected={false}
isEmulator={false}
isEnabled={true}
@@ -59,6 +60,20 @@ exports[`ScaleComponent renders with correct initial notification 1`] = `
usageSizeInKB={100}
wasAutopilotOriginallySet={true}
/>
<Stack
tokens={
Object {
"childrenGap": 5,
}
}
>
<StyledLabelBase>
Storage capacity
</StyledLabelBase>
<Text>
Unlimited
</Text>
</Stack>
</Stack>
</Stack>
`;

View File

@@ -40,8 +40,6 @@ exports[`SubSettingsComponent analyticalTimeToLive hidden 1`] = `
Object {
"flexContainer": Array [
Object {
"columnGap": "default",
"display": "default",
"selectors": Object {
".ms-ChoiceField-field.is-checked::after": Object {
"borderColor": "",
@@ -108,8 +106,6 @@ exports[`SubSettingsComponent analyticalTimeToLive hidden 1`] = `
Object {
"flexContainer": Array [
Object {
"columnGap": "default",
"display": "default",
"selectors": Object {
".ms-ChoiceField-field.is-checked::after": Object {
"borderColor": "",
@@ -172,8 +168,6 @@ exports[`SubSettingsComponent analyticalTimeToLive hidden 1`] = `
Object {
"flexContainer": Array [
Object {
"columnGap": "default",
"display": "default",
"selectors": Object {
".ms-ChoiceField-field.is-checked::after": Object {
"borderColor": "",
@@ -224,10 +218,7 @@ exports[`SubSettingsComponent analyticalTimeToLive hidden 1`] = `
<Text>
Large
partition key
has been enabled.
</Text>
<Text>
Non-hierarchically partitioned container.
has been enabled
</Text>
</Stack>
</Stack>
@@ -273,8 +264,6 @@ exports[`SubSettingsComponent analyticalTimeToLiveSeconds hidden 1`] = `
Object {
"flexContainer": Array [
Object {
"columnGap": "default",
"display": "default",
"selectors": Object {
".ms-ChoiceField-field.is-checked::after": Object {
"borderColor": "",
@@ -341,8 +330,6 @@ exports[`SubSettingsComponent analyticalTimeToLiveSeconds hidden 1`] = `
Object {
"flexContainer": Array [
Object {
"columnGap": "default",
"display": "default",
"selectors": Object {
".ms-ChoiceField-field.is-checked::after": Object {
"borderColor": "",
@@ -395,8 +382,6 @@ exports[`SubSettingsComponent analyticalTimeToLiveSeconds hidden 1`] = `
Object {
"flexContainer": Array [
Object {
"columnGap": "default",
"display": "default",
"selectors": Object {
".ms-ChoiceField-field.is-checked::after": Object {
"borderColor": undefined,
@@ -460,8 +445,6 @@ exports[`SubSettingsComponent analyticalTimeToLiveSeconds hidden 1`] = `
Object {
"flexContainer": Array [
Object {
"columnGap": "default",
"display": "default",
"selectors": Object {
".ms-ChoiceField-field.is-checked::after": Object {
"borderColor": "",
@@ -512,10 +495,7 @@ exports[`SubSettingsComponent analyticalTimeToLiveSeconds hidden 1`] = `
<Text>
Large
partition key
has been enabled.
</Text>
<Text>
Non-hierarchically partitioned container.
has been enabled
</Text>
</Stack>
</Stack>
@@ -561,8 +541,6 @@ exports[`SubSettingsComponent changeFeedPolicy hidden 1`] = `
Object {
"flexContainer": Array [
Object {
"columnGap": "default",
"display": "default",
"selectors": Object {
".ms-ChoiceField-field.is-checked::after": Object {
"borderColor": "",
@@ -629,8 +607,6 @@ exports[`SubSettingsComponent changeFeedPolicy hidden 1`] = `
Object {
"flexContainer": Array [
Object {
"columnGap": "default",
"display": "default",
"selectors": Object {
".ms-ChoiceField-field.is-checked::after": Object {
"borderColor": "",
@@ -683,8 +659,6 @@ exports[`SubSettingsComponent changeFeedPolicy hidden 1`] = `
Object {
"flexContainer": Array [
Object {
"columnGap": "default",
"display": "default",
"selectors": Object {
".ms-ChoiceField-field.is-checked::after": Object {
"borderColor": "",
@@ -760,10 +734,7 @@ exports[`SubSettingsComponent changeFeedPolicy hidden 1`] = `
<Text>
Large
partition key
has been enabled.
</Text>
<Text>
Non-hierarchically partitioned container.
has been enabled
</Text>
</Stack>
</Stack>
@@ -809,8 +780,6 @@ exports[`SubSettingsComponent renders 1`] = `
Object {
"flexContainer": Array [
Object {
"columnGap": "default",
"display": "default",
"selectors": Object {
".ms-ChoiceField-field.is-checked::after": Object {
"borderColor": "",
@@ -877,8 +846,6 @@ exports[`SubSettingsComponent renders 1`] = `
Object {
"flexContainer": Array [
Object {
"columnGap": "default",
"display": "default",
"selectors": Object {
".ms-ChoiceField-field.is-checked::after": Object {
"borderColor": "",
@@ -931,8 +898,6 @@ exports[`SubSettingsComponent renders 1`] = `
Object {
"flexContainer": Array [
Object {
"columnGap": "default",
"display": "default",
"selectors": Object {
".ms-ChoiceField-field.is-checked::after": Object {
"borderColor": "",
@@ -1021,8 +986,6 @@ exports[`SubSettingsComponent renders 1`] = `
Object {
"flexContainer": Array [
Object {
"columnGap": "default",
"display": "default",
"selectors": Object {
".ms-ChoiceField-field.is-checked::after": Object {
"borderColor": "",
@@ -1073,10 +1036,7 @@ exports[`SubSettingsComponent renders 1`] = `
<Text>
Large
partition key
has been enabled.
</Text>
<Text>
Non-hierarchically partitioned container.
has been enabled
</Text>
</Stack>
</Stack>
@@ -1122,8 +1082,6 @@ exports[`SubSettingsComponent timeToLiveSeconds hidden 1`] = `
Object {
"flexContainer": Array [
Object {
"columnGap": "default",
"display": "default",
"selectors": Object {
".ms-ChoiceField-field.is-checked::after": Object {
"borderColor": undefined,
@@ -1165,8 +1123,6 @@ exports[`SubSettingsComponent timeToLiveSeconds hidden 1`] = `
Object {
"flexContainer": Array [
Object {
"columnGap": "default",
"display": "default",
"selectors": Object {
".ms-ChoiceField-field.is-checked::after": Object {
"borderColor": "",
@@ -1219,8 +1175,6 @@ exports[`SubSettingsComponent timeToLiveSeconds hidden 1`] = `
Object {
"flexContainer": Array [
Object {
"columnGap": "default",
"display": "default",
"selectors": Object {
".ms-ChoiceField-field.is-checked::after": Object {
"borderColor": "",
@@ -1309,8 +1263,6 @@ exports[`SubSettingsComponent timeToLiveSeconds hidden 1`] = `
Object {
"flexContainer": Array [
Object {
"columnGap": "default",
"display": "default",
"selectors": Object {
".ms-ChoiceField-field.is-checked::after": Object {
"borderColor": "",
@@ -1361,10 +1313,7 @@ exports[`SubSettingsComponent timeToLiveSeconds hidden 1`] = `
<Text>
Large
partition key
has been enabled.
</Text>
<Text>
Non-hierarchically partitioned container.
has been enabled
</Text>
</Stack>
</Stack>

View File

@@ -35,7 +35,6 @@ exports[`SettingsComponent renders 1`] = `
"onRefreshDatabasesKeyPress": [Function],
"onRefreshResourcesClick": [Function],
"phoenixClient": PhoenixClient {
"armResourceId": undefined,
"retryOptions": Object {
"maxTimeout": 5000,
"minTimeout": 5000,
@@ -112,7 +111,6 @@ exports[`SettingsComponent renders 1`] = `
"onRefreshDatabasesKeyPress": [Function],
"onRefreshResourcesClick": [Function],
"phoenixClient": PhoenixClient {
"armResourceId": undefined,
"retryOptions": Object {
"maxTimeout": 5000,
"minTimeout": 5000,

View File

@@ -2,60 +2,154 @@
exports[`SettingsUtils functions render 1`] = `
<Fragment>
<Stack>
<Text
style={
Object {
"fontWeight": 600,
}
}
<Text>
Your
container
throughput will automatically scale from
<b>
100
RU/s (10% of max RU/s) -
1000
RU/s
</b>
based on usage.
<br />
</Text>
<Text>
After the first
10
GB of data stored, the max RU/s will be automatically upgraded based on the new storage value.
<StyledLinkBase
href="https://aka.ms/cosmos-autoscale-info"
target="_blank"
>
Cost estimate*
</Text>
<Text
style={
Object {
"fontWeight": 600,
"marginTop": 15,
}
}
Learn more
</StyledLinkBase>
.
</Text>
<Text>
Your
database
throughput will automatically scale from
<b>
100
RU/s (10% of max RU/s) -
1000
RU/s
</b>
based on usage.
<br />
</Text>
<Text>
After the first
10
GB of data stored, the max RU/s will be automatically upgraded based on the new storage value.
<StyledLinkBase
href="https://aka.ms/cosmos-autoscale-info"
target="_blank"
>
How we calculate this
</Text>
<Stack
Learn more
</StyledLinkBase>
.
</Text>
<Stack
styles={
Object {
"root": Object {
"width": 600,
},
}
}
tokens={
Object {
"childrenGap": 10,
}
}
>
<StyledWithViewportComponent
columns={
Array [
Object {
"fieldName": "costType",
"isResizable": true,
"key": "costType",
"maxWidth": 200,
"minWidth": 100,
"name": "",
},
Object {
"fieldName": "hourly",
"isResizable": true,
"key": "hourly",
"maxWidth": 200,
"minWidth": 100,
"name": "Hourly",
},
Object {
"fieldName": "daily",
"isResizable": true,
"key": "daily",
"maxWidth": 200,
"minWidth": 100,
"name": "Daily",
},
Object {
"fieldName": "monthly",
"isResizable": true,
"key": "monthly",
"maxWidth": 200,
"minWidth": 100,
"name": "Monthly",
},
]
}
disableSelectionZone={true}
items={
Array [
Object {
"costType": <Text>
Current Cost
</Text>,
"daily": <Text>
$ 24.48
</Text>,
"hourly": <Text>
$ 1.02
</Text>,
"monthly": <Text>
$ 744.6
</Text>,
},
]
}
layoutMode={1}
onRenderRow={[Function]}
selectionMode={0}
/>
<Text
id="throughputSpendElement"
style={
Object {
"marginTop": 5,
}
}
>
<span>
2
region
<span>
s
</span>
</span>
<span>
1000
RU/s
</span>
<span>
¥
0.00051
/RU
</span>
</Stack>
<Text
style={
Object {
"marginTop": 15,
}
}
>
(
regions:
2
,
1000
RU/s,
¥
0.00051
/RU)
</Text>
<Text>
<em>
*
This cost is an estimate and may vary based on the regions where your account is deployed and potential discounts applied to your account
</em>
</Text>
@@ -111,6 +205,19 @@ exports[`SettingsUtils functions render 1`] = `
>
You have not saved the latest changes made to your indexing policy. Please click save to confirm the changes.
</Text>
<Text
id="updateThroughputBeyondLimitWarningMessage"
styles={
Object {
"root": Object {
"color": "windowtext",
"fontSize": 14,
},
}
}
>
You are about to request an increase in throughput beyond the pre-allocated capacity. The service will scale out and increase throughput for the selected container. This operation will take 1-3 business days to complete. You can track the status of this request in Notifications.
</Text>
<Text
id="updateThroughputDelayedApplyWarningMessage"
styles={

View File

@@ -46,13 +46,10 @@ export class TabComponent extends React.Component<TabComponentProps> {
}
let className = "toggleSwitch";
let ariaselected;
if (index === this.props.currentTabIndex) {
className += " selectedToggle";
ariaselected = true;
} else {
className += " unselectedToggle";
ariaselected = false;
}
return (
@@ -60,10 +57,9 @@ export class TabComponent extends React.Component<TabComponentProps> {
<AccessibleElement
as="span"
className={className}
role="tab"
role="presentation"
onActivated={() => this.setActiveTab(index)}
aria-label={`Select tab: ${tab.title}`}
aria-selected={ariaselected}
>
{tab.title}
</AccessibleElement>
@@ -81,11 +77,7 @@ export class TabComponent extends React.Component<TabComponentProps> {
return (
<div className="tabComponentContainer">
{!this.props.hideHeader && (
<div className="tabs tabSwitch" role="tablist">
{this.renderTabTitles()}
</div>
)}
{!this.props.hideHeader && <div className="tabs tabSwitch">{this.renderTabTitles()}</div>}
<div className={className}>{currentTabContent.render()}</div>
</div>
);

View File

@@ -23,12 +23,12 @@ describe("ThroughputInput Pane", () => {
});
it("should switch mode properly", () => {
wrapper.find('[aria-label="Manual database throughput"]').simulate("change");
wrapper.find('[aria-label="Manual mode"]').simulate("change");
expect(wrapper.find('[aria-label="Throughput header"]').at(0).text()).toBe(
"Container throughput (400 - unlimited RU/s)"
);
wrapper.find('[aria-label="Autoscale database throughput"]').simulate("change");
wrapper.find('[aria-label="Autoscale mode"]').simulate("change");
expect(wrapper.find('[aria-label="Throughput header"]').at(0).text()).toBe("Container throughput (autoscale)");
});
});

View File

@@ -28,7 +28,6 @@ export const ThroughputInput: FunctionComponent<ThroughputInputProps> = ({
isSharded,
isFreeTier,
showFreeTierExceedThroughputTooltip,
isQuickstart,
setThroughputValue,
setIsAutoscale,
setIsThroughputCapExceeded,
@@ -36,7 +35,7 @@ export const ThroughputInput: FunctionComponent<ThroughputInputProps> = ({
}: ThroughputInputProps) => {
const [isAutoscaleSelected, setIsAutoScaleSelected] = useState<boolean>(true);
const [throughput, setThroughput] = useState<number>(
isFreeTier || isQuickstart ? AutoPilotUtils.autoPilotThroughput1K : AutoPilotUtils.autoPilotThroughput4K
isFreeTier ? AutoPilotUtils.autoPilotThroughput1K : AutoPilotUtils.autoPilotThroughput4K
);
const [isCostAcknowledged, setIsCostAcknowledged] = useState<boolean>(false);
const [throughputError, setThroughputError] = useState<string>("");
@@ -185,48 +184,36 @@ export const ThroughputInput: FunctionComponent<ThroughputInputProps> = ({
</Stack>
<Stack horizontal verticalAlign="center">
<div role="radiogroup">
<input
id="Autoscale-input"
className="throughputInputRadioBtn"
aria-label="Autoscale database throughput"
aria-required={true}
checked={isAutoscaleSelected}
type="radio"
role="radio"
tabIndex={0}
onChange={(e) => handleOnChangeMode(e, "Autoscale")}
/>
<label htmlFor="Autoscale-input" className="throughputInputRadioBtnLabel">
Autoscale
</label>
<input
className="throughputInputRadioBtn"
aria-label="Autoscale mode"
aria-required={true}
checked={isAutoscaleSelected}
type="radio"
role="radio"
tabIndex={0}
onChange={(e) => handleOnChangeMode(e, "Autoscale")}
/>
<span className="throughputInputRadioBtnLabel">Autoscale</span>
<input
id="Manual-input"
className="throughputInputRadioBtn"
aria-label="Manual database throughput"
checked={!isAutoscaleSelected}
type="radio"
aria-required={true}
role="radio"
tabIndex={0}
onChange={(e) => handleOnChangeMode(e, "Manual")}
/>
<label className="throughputInputRadioBtnLabel" htmlFor="Manual-input">
Manual
</label>
</div>
<input
className="throughputInputRadioBtn"
aria-label="Manual mode"
checked={!isAutoscaleSelected}
type="radio"
aria-required={true}
role="radio"
tabIndex={0}
onChange={(e) => handleOnChangeMode(e, "Manual")}
/>
<span className="throughputInputRadioBtnLabel">Manual</span>
</Stack>
{isAutoscaleSelected && (
<Stack className="throughputInputSpacing">
<Text variant="small" aria-label="capacity calculator of azure cosmos db">
<Text variant="small" aria-label="ruDescription">
Estimate your required RU/s with{" "}
<Link
target="_blank"
href="https://cosmos.azure.com/capacitycalculator/"
aria-label="capacity calculator of azure cosmos db"
>
<Link target="_blank" href="https://cosmos.azure.com/capacitycalculator/" aria-label="ruDescription">
capacity calculator
</Link>
.
@@ -250,7 +237,7 @@ export const ThroughputInput: FunctionComponent<ThroughputInputProps> = ({
step={AutoPilotUtils.autoPilotIncrementStep}
min={AutoPilotUtils.autoPilotThroughput1K}
value={throughput.toString()}
ariaLabel={`${isDatabase ? "Database" : getCollectionName()} max RU/s`}
aria-label="Max request units per second"
required={true}
errorMessage={throughputError}
/>

View File

@@ -344,13 +344,13 @@ exports[`ThroughputInput Pane should render Default properly 1`] = `
onMouseLeave={[Function]}
>
<StyledIconBase
ariaLabel="Set the throughput — Request Units per second (RU/s) — required for the workload. A read of a 1 KB document uses 1 RU. Select manual if you plan to scale RU/s yourself. Select autoscale to allow the system to scale RU/s based on usage."
ariaLabel="Info"
className="panelInfoIcon"
iconName="Info"
tabIndex={0}
>
<IconBase
ariaLabel="Set the throughput — Request Units per second (RU/s) — required for the workload. A read of a 1 KB document uses 1 RU. Select manual if you plan to scale RU/s yourself. Select autoscale to allow the system to scale RU/s based on usage."
ariaLabel="Info"
className="panelInfoIcon"
iconName="Info"
styles={[Function]}
@@ -630,7 +630,7 @@ exports[`ThroughputInput Pane should render Default properly 1`] = `
}
>
<i
aria-label="Set the throughput — Request Units per second (RU/s) — required for the workload. A read of a 1 KB document uses 1 RU. Select manual if you plan to scale RU/s yourself. Select autoscale to allow the system to scale RU/s based on usage."
aria-label="Info"
className="panelInfoIcon root-57"
data-icon-name="Info"
role="img"
@@ -654,45 +654,40 @@ exports[`ThroughputInput Pane should render Default properly 1`] = `
<div
className="ms-Stack css-58"
>
<div
<input
aria-label="Autoscale mode"
aria-required={true}
checked={true}
className="throughputInputRadioBtn"
key=".0:$.0"
role="radiogroup"
onChange={[Function]}
role="radio"
tabIndex={0}
type="radio"
/>
<span
className="throughputInputRadioBtnLabel"
key=".0:$.1"
>
<input
aria-label="Autoscale database throughput"
aria-required={true}
checked={true}
className="throughputInputRadioBtn"
id="Autoscale-input"
onChange={[Function]}
role="radio"
tabIndex={0}
type="radio"
/>
<label
className="throughputInputRadioBtnLabel"
htmlFor="Autoscale-input"
>
Autoscale
</label>
<input
aria-label="Manual database throughput"
aria-required={true}
checked={false}
className="throughputInputRadioBtn"
id="Manual-input"
onChange={[Function]}
role="radio"
tabIndex={0}
type="radio"
/>
<label
className="throughputInputRadioBtnLabel"
htmlFor="Manual-input"
>
Manual
</label>
</div>
Autoscale
</span>
<input
aria-label="Manual mode"
aria-required={true}
checked={false}
className="throughputInputRadioBtn"
key=".0:$.2"
onChange={[Function]}
role="radio"
tabIndex={0}
type="radio"
/>
<span
className="throughputInputRadioBtnLabel"
key=".0:$.3"
>
Manual
</span>
</div>
</Stack>
<Stack
@@ -702,23 +697,23 @@ exports[`ThroughputInput Pane should render Default properly 1`] = `
className="ms-Stack throughputInputSpacing css-59"
>
<Text
aria-label="capacity calculator of azure cosmos db"
aria-label="ruDescription"
key=".0:$.0"
variant="small"
>
<span
aria-label="capacity calculator of azure cosmos db"
aria-label="ruDescription"
className="css-54"
>
Estimate your required RU/s with
<StyledLinkBase
aria-label="capacity calculator of azure cosmos db"
aria-label="ruDescription"
href="https://cosmos.azure.com/capacitycalculator/"
target="_blank"
>
<LinkBase
aria-label="capacity calculator of azure cosmos db"
aria-label="ruDescription"
href="https://cosmos.azure.com/capacitycalculator/"
styles={[Function]}
target="_blank"
@@ -997,7 +992,7 @@ exports[`ThroughputInput Pane should render Default properly 1`] = `
}
>
<a
aria-label="capacity calculator of azure cosmos db"
aria-label="ruDescription"
className="ms-Link root-60"
href="https://cosmos.azure.com/capacitycalculator/"
onClick={[Function]}
@@ -1336,13 +1331,13 @@ exports[`ThroughputInput Pane should render Default properly 1`] = `
onMouseLeave={[Function]}
>
<StyledIconBase
ariaLabel="Set the max RU/s to the highest RU/s you want your container to scale to. The container will scale between 10% of max RU/s to the max RU/s based on usage."
ariaLabel="Info"
className="panelInfoIcon"
iconName="Info"
tabIndex={0}
>
<IconBase
ariaLabel="Set the max RU/s to the highest RU/s you want your container to scale to. The container will scale between 10% of max RU/s to the max RU/s based on usage."
ariaLabel="Info"
className="panelInfoIcon"
iconName="Info"
styles={[Function]}
@@ -1622,7 +1617,7 @@ exports[`ThroughputInput Pane should render Default properly 1`] = `
}
>
<i
aria-label="Set the max RU/s to the highest RU/s you want your container to scale to. The container will scale between 10% of max RU/s to the max RU/s based on usage."
aria-label="Info"
className="panelInfoIcon root-57"
data-icon-name="Info"
role="img"
@@ -1640,7 +1635,7 @@ exports[`ThroughputInput Pane should render Default properly 1`] = `
</div>
</Stack>
<StyledTextFieldBase
ariaLabel="Container max RU/s"
aria-label="Max request units per second"
errorMessage=""
id="autoscaleRUValueField"
key=".0:$.2"
@@ -1663,7 +1658,7 @@ exports[`ThroughputInput Pane should render Default properly 1`] = `
value="4000"
>
<TextFieldBase
ariaLabel="Container max RU/s"
aria-label="Max request units per second"
deferredValidationTime={200}
errorMessage=""
id="autoscaleRUValueField"
@@ -1961,7 +1956,6 @@ exports[`ThroughputInput Pane should render Default properly 1`] = `
>
<input
aria-invalid={false}
aria-label="Container max RU/s"
className="ms-TextField-field field-64"
id="autoscaleRUValueField"
min={1000}

View File

@@ -195,7 +195,7 @@ export class TreeNodeComponent extends React.Component<TreeNodeComponentProps, T
</div>
{node.children && (
<AnimateHeight duration={TreeNodeComponent.transitionDurationMS} height={this.state.isExpanded ? "auto" : 0}>
<div className="nodeChildren" data-test={node.label} role="group">
<div className="nodeChildren" data-test={node.label}>
{TreeNodeComponent.getSortedChildren(node).map((childNode: TreeNode) => (
<TreeNodeComponent
key={`${childNode.label}-${generation + 1}-${childNode.timestamp}`}

View File

@@ -100,7 +100,6 @@ exports[`TreeNodeComponent does not render children by default 1`] = `
<div
className="nodeChildren"
data-test="label"
role="group"
>
<TreeNodeComponent
generation={3}
@@ -252,7 +251,6 @@ exports[`TreeNodeComponent renders a simple node (sorted children, expanded) 1`]
<div
className="nodeChildren"
data-test="label"
role="group"
>
<TreeNodeComponent
generation={13}
@@ -354,7 +352,6 @@ exports[`TreeNodeComponent renders loading icon 1`] = `
<div
className="nodeChildren"
data-test="label"
role="group"
/>
</AnimateHeight>
</div>
@@ -468,7 +465,6 @@ exports[`TreeNodeComponent renders sorted children, expanded, leaves and parents
<div
className="nodeChildren"
data-test="label"
role="group"
>
<TreeNodeComponent
generation={13}
@@ -598,7 +594,6 @@ exports[`TreeNodeComponent renders unsorted children by default 1`] = `
<div
className="nodeChildren"
data-test="label"
role="group"
>
<TreeNodeComponent
generation={3}

View File

@@ -3,7 +3,7 @@
.treeComponent {
.nodeItem {
&:focus {
outline: 2px @AccentMedium;
outline: 1px dashed @AccentMedium;
}
.treeNodeHeader {

View File

@@ -133,6 +133,7 @@ describe("ContainerSampleGenerator", () => {
} as DatabaseAccount,
});
// Rejects with error that contains experience
expect(ContainerSampleGenerator.createSampleGeneratorAsync(explorerStub)).rejects.toMatch(experience);
});

View File

@@ -1,6 +1,5 @@
import { createCollection } from "../../Common/dataAccess/createCollection";
import { createDocument } from "../../Common/dataAccess/createDocument";
import { createDocument as createMongoDocument } from "../../Common/MongoProxyClient";
import * as DataModels from "../../Contracts/DataModels";
import * as ViewModels from "../../Contracts/ViewModels";
import { userContext } from "../../UserContext";
@@ -22,21 +21,14 @@ export class ContainerSampleGenerator {
/**
* Factory function to load the json data file
*/
public static async createSampleGeneratorAsync(
container: Explorer,
isCopilot?: boolean
): Promise<ContainerSampleGenerator> {
public static async createSampleGeneratorAsync(container: Explorer): Promise<ContainerSampleGenerator> {
const generator = new ContainerSampleGenerator(container);
let dataFileContent: any;
if (isCopilot) {
dataFileContent = await import(
/* webpackChunkName: "queryCopilotSampleData" */ "../../../sampleData/queryCopilotSampleData.json"
);
} else if (userContext.apiType === "Gremlin") {
if (userContext.apiType === "Gremlin") {
dataFileContent = await import(
/* webpackChunkName: "gremlinSampleJsonData" */ "../../../sampleData/gremlinSampleData.json"
);
} else if (userContext.apiType === "SQL" || userContext.apiType === "Mongo") {
} else if (userContext.apiType === "SQL") {
dataFileContent = await import(
/* webpackChunkName: "sqlSampleJsonData" */ "../../../sampleData/sqlSampleData.json"
);
@@ -76,7 +68,7 @@ export class ContainerSampleGenerator {
return database.findCollectionWithId(this.sampleDataFile.collectionId);
}
public async populateContainerAsync(collection: ViewModels.Collection, shardKey?: string): Promise<void> {
public async populateContainerAsync(collection: ViewModels.Collection): Promise<void> {
if (!collection) {
throw new Error("No container to populate");
}
@@ -107,9 +99,7 @@ export class ContainerSampleGenerator {
await Promise.all(
this.sampleDataFile.data.map(async (doc) => {
try {
userContext.apiType === "Mongo"
? await createMongoDocument(collection.databaseId, collection, shardKey, doc)
: await createDocument(collection, doc);
await createDocument(collection, doc);
} catch (error) {
NotificationConsoleUtils.logConsoleError(error);
}

View File

@@ -16,7 +16,12 @@ import { getErrorMessage, getErrorStack, handleError } from "../Common/ErrorHand
import * as Logger from "../Common/Logger";
import { QueriesClient } from "../Common/QueriesClient";
import * as DataModels from "../Contracts/DataModels";
import { ContainerConnectionInfo, IPhoenixServiceInfo, IProvisionData, IResponse } from "../Contracts/DataModels";
import {
ContainerConnectionInfo,
IPhoenixConnectionInfoResult,
IProvisionData,
IResponse,
} from "../Contracts/DataModels";
import * as ViewModels from "../Contracts/ViewModels";
import { GitHubOAuthService } from "../GitHub/GitHubOAuthService";
import { useSidePanel } from "../hooks/useSidePanel";
@@ -93,8 +98,7 @@ export default class Explorer {
dataExplorerArea: Constants.Areas.ResourceTree,
});
this._isInitializingNotebooks = false;
this.phoenixClient = new PhoenixClient(userContext?.databaseAccount?.id);
this.phoenixClient = new PhoenixClient();
useNotebook.subscribe(
() => this.refreshCommandBarButtons(),
(state) => state.isNotebooksEnabledForAccount
@@ -352,7 +356,7 @@ export default class Explorer {
(notebookServerInfo && notebookServerInfo.notebookServerEndpoint === undefined))
) {
const provisionData: IProvisionData = {
cosmosEndpoint: userContext?.databaseAccount?.properties?.documentEndpoint,
cosmosEndpoint: userContext.databaseAccount.properties.documentEndpoint,
poolId: PoolIdType.DefaultPoolId,
};
const connectionStatus: ContainerConnectionInfo = {
@@ -403,7 +407,7 @@ export default class Explorer {
}
private async setNotebookInfo(
connectionInfo: IResponse<IPhoenixServiceInfo>,
connectionInfo: IResponse<IPhoenixConnectionInfoResult>,
connectionStatus: DataModels.ContainerConnectionInfo
) {
const containerData = {
@@ -577,7 +581,7 @@ export default class Explorer {
try {
await Promise.all(
databasesToLoad.map(async (database: ViewModels.Database) => {
await database.loadCollections(true);
await database.loadCollections();
const isNewDatabase: boolean = _.some(newDatabases, (db: ViewModels.Database) => db.id() === database.id());
if (isNewDatabase) {
database.expandDatabase();
@@ -1057,10 +1061,6 @@ export default class Explorer {
title = "Cassandra Shell";
break;
case ViewModels.TerminalKind.Postgres:
title = "PSQL Shell";
break;
default:
throw new Error("Terminal kind: ${kind} not supported");
}
@@ -1120,7 +1120,7 @@ export default class Explorer {
account: userContext.databaseAccount,
container: this,
junoClient: this.notebookManager?.junoClient,
selectedTab: selectedTab || GalleryTabKind.OfficialSamples,
selectedTab: selectedTab || GalleryTabKind.PublicGallery,
notebookUrl,
galleryItem,
isFavorite,
@@ -1247,11 +1247,9 @@ export default class Explorer {
}
public async refreshExplorer(): Promise<void> {
if (userContext.apiType !== "Postgres") {
userContext.authType === AuthType.ResourceToken
? this.refreshDatabaseForResourceToken()
: this.refreshAllDatabases();
}
userContext.authType === AuthType.ResourceToken
? this.refreshDatabaseForResourceToken()
: this.refreshAllDatabases();
await useNotebook.getState().refreshNotebooksEnabledStateForAccount();
// TODO: remove reference to isNotebookEnabled and isNotebooksEnabledForAccount

View File

@@ -729,7 +729,6 @@ export class D3ForceGraph implements GraphRenderer {
var iconGroup = newNodes
.append("g")
.attr("class", "iconContainer")
.attr("role", "group")
.attr("tabindex", 0)
.attr("aria-label", (d: D3Node) => {
return this.retrieveNodeCaption(d);

View File

@@ -6,9 +6,9 @@ import * as React from "react";
import LoadGraphIcon from "../../../../images/LoadGraph.png";
import LoadingIndicatorIcon from "../../../../images/LoadingIndicator_3Squares.gif";
import * as Constants from "../../../Common/Constants";
import { getErrorMessage } from "../../../Common/ErrorHandlingUtils";
import { queryDocuments } from "../../../Common/dataAccess/queryDocuments";
import { queryDocumentsPage } from "../../../Common/dataAccess/queryDocumentsPage";
import { getErrorMessage } from "../../../Common/ErrorHandlingUtils";
import * as DataModels from "../../../Contracts/DataModels";
import * as ViewModels from "../../../Contracts/ViewModels";
import { InputProperty } from "../../../Contracts/ViewModels";
@@ -182,8 +182,7 @@ export class GraphExplorer extends React.Component<GraphExplorerProps, GraphExpl
public static readonly WITHOUT_STEP_ARGS_MAX_CHARS = 10000; // maximums char size of the without() step parameter
public static readonly ROOT_LIST_PAGE_SIZE = 100;
private static readonly MAX_LATEST_QUERIES = 10;
// TODO This prevents loading too much data in GraphExplorer and d3. A better is to cap the size of the result, rather than the number of items in the array.
private static readonly MAX_RESULT_SIZE = 100_000;
private static readonly MAX_RESULT_SIZE = 10000;
private static readonly TAB_INDEX_JSON = 0;
private static readonly TAB_INDEX_GRAPH = 1;

View File

@@ -40,7 +40,6 @@ export class GraphVizComponent extends React.Component<GraphVizComponentProps> {
{/* svg load more icon inlined as-is here: remove the style="fill:#374649;" so we can override it */}
<svg
role="img"
aria-label="graph"
version="1.1"
xmlns="http://www.w3.org/2000/svg"
xmlnsXlink="http://www.w3.org/1999/xlink"
@@ -136,7 +135,6 @@ export class GraphVizComponent extends React.Component<GraphVizComponentProps> {
<g id="triangleRight">
<svg
role="img"
aria-label="graph"
version="1.1"
id="Layer_1"
xmlns="http://www.w3.org/2000/svg"

View File

@@ -31,7 +31,7 @@ export class GremlinClient {
public client: GremlinSimpleClient;
public pendingResults: Map<string, PendingResultData>; // public for testing purposes
private maxResultSize: number;
private static readonly PENDING_REQUEST_TIMEOUT_MS = 1 /* hour */ * 3_600 /* seconds */ * 1_000 /* ms */;
private static readonly PENDING_REQUEST_TIMEOUT_MS = 6 /* minutes */ * 60 /* seconds */ * 1000 /* ms */;
private static readonly TIMEOUT_ERROR_MSG = `Pending request timed out (${GremlinClient.PENDING_REQUEST_TIMEOUT_MS} ms)`;
private static readonly LOG_AREA = "GremlinClient";

View File

@@ -17,21 +17,19 @@ export class MiddlePaneComponent extends React.Component<MiddlePaneComponentProp
<div className="middlePane">
<div className="graphTitle">
<span className="paneTitle">Graph</span>
<button
style={{ border: "none", background: "none" }}
<span
className="graphExpandCollapseBtn pull-right"
onClick={this.props.toggleExpandGraph}
role="button"
aria-expanded={this.props.isTabsContentExpanded}
aria-label={
this.props.isTabsContentExpanded ? "Collapse graph to minimized view" : "View graph in full screen"
}
aria-name="View graph in full screen"
tabIndex={0}
>
<img
src={this.props.isTabsContentExpanded ? CollapseArrowIcon : ExpandIcon}
alt={this.props.isTabsContentExpanded ? "collapse graph content" : "expand graph content"}
/>
</button>
</span>
</div>
<div className="maingraphContainer">
<GraphVizComponent forceGraphParams={this.props.graphVizProps.forceGraphParams} />

Some files were not shown because too many files have changed in this diff Show More