Merge branch 'master' into staging/jts-api-distributed
commit
4a800fc7be
|
@ -1,4 +1,4 @@
|
|||
version: 2
|
||||
version: 2.1
|
||||
jobs:
|
||||
build:
|
||||
docker:
|
||||
|
@ -31,17 +31,17 @@ jobs:
|
|||
command: cd api-docs && bash generate-api-docs.sh
|
||||
- run:
|
||||
name: Inject Flux stdlib frontmatter
|
||||
command: node ./flux-build-scripts/inject-flux-stdlib-frontmatter.js
|
||||
command: node ./flux-build-scripts/inject-flux-stdlib-frontmatter.cjs
|
||||
- run:
|
||||
name: Update Flux/InfluxDB versions
|
||||
command: node ./flux-build-scripts/update-flux-versions.js
|
||||
command: node ./flux-build-scripts/update-flux-versions.cjs
|
||||
- save_cache:
|
||||
key: install-{{ .Environment.CACHE_VERSION }}-{{ checksum ".circleci/config.yml" }}
|
||||
paths:
|
||||
- /home/circleci/bin
|
||||
- run:
|
||||
name: Hugo Build
|
||||
command: npx hugo --logLevel info --minify --destination workspace/public
|
||||
command: yarn hugo --environment production --logLevel info --gc --destination workspace/public
|
||||
- persist_to_workspace:
|
||||
root: workspace
|
||||
paths:
|
||||
|
@ -68,7 +68,6 @@ jobs:
|
|||
when: on_success
|
||||
|
||||
workflows:
|
||||
version: 2
|
||||
build:
|
||||
jobs:
|
||||
- build
|
||||
|
|
|
@ -0,0 +1,44 @@
|
|||
# Context Files for LLMs and AI Tools
|
||||
|
||||
This directory contains plans, reports, and other context files that are:
|
||||
- Used to provide context to LLMs during development
|
||||
- Not committed to the repository
|
||||
- May be transient or belong in other repositories
|
||||
|
||||
## Directory Structure
|
||||
|
||||
- `plans/` - Documentation plans and roadmaps
|
||||
- `reports/` - Generated reports and analyses
|
||||
- `research/` - Research notes and findings
|
||||
- `templates/` - Reusable templates for Claude interactions
|
||||
|
||||
## Usage
|
||||
|
||||
Place files here that you want to reference--for example, using @ mentions in Claude--such as:
|
||||
- Documentation planning documents
|
||||
- API migration guides
|
||||
- Performance reports
|
||||
- Architecture decisions
|
||||
|
||||
## Example Structure
|
||||
|
||||
```
|
||||
.context/
|
||||
├── plans/
|
||||
│ ├── v3.2-release-plan.md
|
||||
│ └── api-migration-guide.md
|
||||
├── reports/
|
||||
│ ├── weekly-progress-2025-07.md
|
||||
│ └── pr-summary-2025-06.md
|
||||
├── research/
|
||||
│ └── competitor-analysis.md
|
||||
└── templates/
|
||||
└── release-notes-template.md
|
||||
```
|
||||
|
||||
## Best Practices
|
||||
|
||||
1. Use descriptive filenames that indicate the content and date
|
||||
2. Keep files organized in appropriate subdirectories
|
||||
3. Consider using date prefixes for time-sensitive content (e.g., `2025-07-01-meeting-notes.md`)
|
||||
4. Remove outdated files periodically to keep the context relevant
|
|
@ -1,51 +1,67 @@
|
|||
# GitHub Copilot Instructions for InfluxData Documentation
|
||||
# Instructions for InfluxData Documentation
|
||||
|
||||
## Purpose and Scope
|
||||
## Purpose and scope
|
||||
|
||||
GitHub Copilot should help document InfluxData products by creating clear, accurate technical content with proper code examples, frontmatter, and formatting.
|
||||
Help document InfluxData products by creating clear, accurate technical content with proper code examples, frontmatter, and formatting.
|
||||
|
||||
## Documentation Structure
|
||||
## Documentation structure
|
||||
|
||||
- **Product version data**: `/data/products.yml`
|
||||
- **Products**:
|
||||
- **InfluxData products**:
|
||||
- InfluxDB 3 Explorer
|
||||
- Documentation source path: `/content/influxdb3/explorer`
|
||||
- Published for the web: https://docs.influxdata.com/influxdb3/explorer/
|
||||
- InfluxDB 3 Core
|
||||
- Documentation source path: `/content/influxdb3/core`
|
||||
- Published for the web: https://docs.influxdata.com/influxdb3/core/
|
||||
- Code repositories: https://github.com/influxdata/influxdb, https://github.com/influxdata/influxdb3_core
|
||||
- InfluxDB 3 Enterprise
|
||||
- Documentation source path: `/content/influxdb3/enterprise`
|
||||
- Published for the web: https://docs.influxdata.com/influxdb3/enterprise/
|
||||
- Code repositories: https://github.com/influxdata/influxdb, https://github.com/influxdata/influxdb3_enterprise
|
||||
- InfluxDB Cloud Dedicated
|
||||
- Documentation source path: `/content/influxdb3/cloud-dedicated`
|
||||
- Published for the web: https://docs.influxdata.com/influxdb3/cloud-dedicated/
|
||||
- Code repository: https://github.com/influxdata/influxdb
|
||||
- InfluxDB Cloud Serverless
|
||||
- Documentation source path: `/content/influxdb3/cloud-serverless`
|
||||
- Published for the web: https://docs.influxdata.com/influxdb3/cloud-serverless/
|
||||
- Code repository: https://github.com/influxdata/idpe
|
||||
- InfluxDB Cloud v2 (TSM)
|
||||
- Documentation source path: `/content/influxdb/cloud`
|
||||
- Published for the web: https://docs.influxdata.com/influxdb/cloud/
|
||||
- Code repository: https://github.com/influxdata/idpe
|
||||
- InfluxDB Clustered
|
||||
- Documentation source path: `/content/influxdb3/clustered`
|
||||
- Published for the web: https://docs.influxdata.com/influxdb3/clustered/
|
||||
- Code repository: https://github.com/influxdata/influxdb
|
||||
- InfluxDB Enterprise v1 (1.x)
|
||||
- Documentation source path: `/content/influxdb/enterprise_influxdb`
|
||||
- Published for the web: https://docs.influxdata.com/enterprise_influxdb/v1/
|
||||
- Code repository: https://github.com/influxdata/influxdb
|
||||
- InfluxDB OSS 1.x
|
||||
- Documentation source path: `/content/influxdb/v1`
|
||||
- Published for the web: https://docs.influxdata.com/influxdb/v1/
|
||||
- Code repository: https://github.com/influxdata/influxdb
|
||||
- InfluxDB OSS 2.x
|
||||
- Documentation source path: `/content/influxdb/v2`
|
||||
- Published for the web: https://docs.influxdata.com/influxdb/v2/
|
||||
- Code repository: https://github.com/influxdata/influxdb
|
||||
- Telegraf
|
||||
- Documentation source path: `/content/telegraf/v1`
|
||||
- Published for the web: https://docs.influxdata.com/telegraf/v1/
|
||||
- Code repository: https://github.com/influxdata/telegraf
|
||||
- Kapacitor
|
||||
- Documentation source path: `/content/kapacitor/v1`
|
||||
- Published for the web: https://docs.influxdata.com/kapacitor/v1/
|
||||
- Code repository: https://github.com/influxdata/kapacitor
|
||||
- Chronograf
|
||||
- Documentation source path: `/content/chronograf/v1`
|
||||
- Published for the web: https://docs.influxdata.com/chronograf/v1/
|
||||
- Code repository: https://github.com/influxdata/chronograf
|
||||
- Flux
|
||||
- Documentation source path: `/content/flux/v0`
|
||||
- Published for the web: https://docs.influxdata.com/flux/v0/
|
||||
- Code repository: https://github.com/influxdata/flux
|
||||
- **InfluxData-supported tools**:
|
||||
- InfluxDB API client libraries
|
||||
|
@ -57,11 +73,19 @@ GitHub Copilot should help document InfluxData products by creating clear, accur
|
|||
- **Repository**: https://github.com/influxdata/docs-v2
|
||||
- **Framework**: Hugo static site generator
|
||||
|
||||
## Style Guidelines
|
||||
## Style guidelines
|
||||
|
||||
- Follow Google Developer Documentation style guidelines
|
||||
- For API references, follow YouTube Data API style
|
||||
- Use semantic line feeds (one sentence per line)
|
||||
- Format code examples to fit within 80 characters
|
||||
- Command line examples:
|
||||
- Should be formatted as code blocks
|
||||
- Should use long options (e.g., `--option` instead of `-o`)
|
||||
- Use cURL for API examples
|
||||
- Format to fit within 80 characters
|
||||
- Should use `--data-urlencode` for query parameters
|
||||
- Should use `--header` for headers
|
||||
- Use only h2-h6 headings in content (h1 comes from frontmatter title properties)
|
||||
- Use sentence case for headings
|
||||
- Use GitHub callout syntax
|
||||
|
@ -69,9 +93,10 @@ GitHub Copilot should help document InfluxData products by creating clear, accur
|
|||
- Use appropriate product names and versions consistently
|
||||
- Follow InfluxData vocabulary guidelines
|
||||
|
||||
## Markdown and Shortcodes
|
||||
## Markdown and shortcodes
|
||||
|
||||
- Include proper frontmatter for each page:
|
||||
- Include proper frontmatter for Markdown pages in `content/**/*.md` (except for
|
||||
shared content files in `content/shared/`):
|
||||
|
||||
```yaml
|
||||
title: # Page title (h1)
|
||||
|
@ -82,18 +107,20 @@ GitHub Copilot should help document InfluxData products by creating clear, accur
|
|||
product_version:
|
||||
weight: # Page order (1-99, 101-199, etc.)
|
||||
```
|
||||
|
||||
- Follow the shortcode examples in `content/example.md` and the documentation
|
||||
for docs-v2 contributors in `CONTRIBUTING.md`
|
||||
- Use provided shortcodes correctly:
|
||||
- Notes/warnings: `{{% note %}}`, `{{% warn %}}`
|
||||
- Product-specific: `{{% enterprise %}}`, `{{% cloud %}}`
|
||||
- Tabbed content: `{{< tabs-wrapper >}}`, `{{% tabs %}}`, `{{% tab-content %}}`
|
||||
- Tabbed content for code examples (without additional text): `{{< code-tabs-wrapper >}}`, `{{% code-tabs %}}`, `{{% code-tab-content %}}`
|
||||
- Version links: `{{< latest >}}`, `{{< latest-patch >}}`
|
||||
- API endpoints: `{{< api-endpoint >}}`
|
||||
- Required elements: `{{< req >}}`
|
||||
- Navigation: `{{< page-nav >}}`
|
||||
- Diagrams: `{{< diagram >}}`, `{{< filesystem-diagram >}}`
|
||||
|
||||
## Code Examples and Testing
|
||||
## Code examples and testing
|
||||
|
||||
- Provide complete, working examples with proper testing annotations:
|
||||
|
||||
|
@ -124,27 +151,50 @@ Table: keys: [_start, _stop, _field, _measurement]
|
|||
- Include necessary environment variables
|
||||
- Show proper credential handling for authenticated commands
|
||||
|
||||
## API Documentation
|
||||
## API documentation
|
||||
|
||||
- `/api-docs` contains OpenAPI spec files used for API reference documentation
|
||||
- Follow OpenAPI specification patterns
|
||||
- Match REST API examples to current implementation
|
||||
- Include complete request/response examples
|
||||
- Document required headers and authentication
|
||||
|
||||
## Versioning and Product Differentiation
|
||||
## Versioning and product differentiation
|
||||
|
||||
- Clearly distinguish between different InfluxDB versions (1.x, 2.x, 3.x)
|
||||
- Use correct terminology for each product variant
|
||||
- Apply appropriate UI descriptions and screenshots
|
||||
- Reference appropriate query language per version
|
||||
|
||||
## Development Tools
|
||||
## Development tools
|
||||
|
||||
- Vale.sh linter for style checking
|
||||
- Configuration file: `.vale.ini`
|
||||
- Docker for local development and testing
|
||||
- pytest and pytest-codeblocks for validating code examples
|
||||
- Pre-commit hooks for quality assurance
|
||||
- Use cypress for testing documentation UI and links
|
||||
- Prettier for code formatting
|
||||
- ESLint for JavaScript and TypeScript linting
|
||||
- Lefthook (NPM package) for managing pre-commit hooks for quality assurance
|
||||
|
||||
## Code style
|
||||
|
||||
- Use modern JavaScript (ES6+) syntax
|
||||
|
||||
## Related repositories
|
||||
|
||||
- **Internal dcumentation assistance requests**: https://github.com/influxdata/DAR/issues
|
||||
- **Internal documentation assistance requests**: https://github.com/influxdata/DAR/issues Documentation
|
||||
|
||||
## Additional instruction files
|
||||
|
||||
For specific workflows and content types, also refer to:
|
||||
|
||||
- **InfluxDB 3 code placeholders**: `.github/instructions/influxdb3-code-placeholders.instructions.md` - Guidelines for placeholder formatting, descriptions, and shortcode usage in InfluxDB 3 documentation
|
||||
- **Contributing guidelines**: `.github/instructions/contributing.instructions.md` - Detailed style guidelines, shortcode usage, frontmatter requirements, and development workflows
|
||||
- **Content-specific instructions**: Check `.github/instructions/` directory for specialized guidelines covering specific documentation patterns and requirements
|
||||
|
||||
## Integration with specialized instructions
|
||||
|
||||
When working on InfluxDB 3 documentation (Core/Enterprise), prioritize the placeholder guidelines from `influxdb3-code-placeholders.instructions.md`.
|
||||
|
||||
For general documentation structure, shortcodes, and development workflows, follow the comprehensive guidelines in `contributing.instructions.md`.
|
||||
|
|
|
@ -0,0 +1,429 @@
|
|||
---
|
||||
applyTo: "content/**/*.md, layouts/**/*.html"
|
||||
---
|
||||
|
||||
# Contributing instructions for InfluxData Documentation
|
||||
|
||||
## Purpose and scope
|
||||
|
||||
Help document InfluxData products
|
||||
by creating clear, accurate technical content with proper
|
||||
code examples, frontmatter, shortcodes, and formatting.
|
||||
|
||||
# Contributing to InfluxData Documentation
|
||||
|
||||
### Sign the InfluxData CLA
|
||||
|
||||
The InfluxData Contributor License Agreement (CLA) is part of the legal framework
|
||||
for the open source ecosystem that protects both you and InfluxData.
|
||||
To make substantial contributions to InfluxData documentation, first sign the InfluxData CLA.
|
||||
What constitutes a "substantial" change is at the discretion of InfluxData documentation maintainers.
|
||||
|
||||
[Sign the InfluxData CLA](https://www.influxdata.com/legal/cla/)
|
||||
|
||||
_**Note:** Typo and broken link fixes are greatly appreciated and do not require signing the CLA._
|
||||
|
||||
_If you're new to contributing or you're looking for an easy update, see [`docs-v2` good-first-issues](https://github.com/influxdata/docs-v2/issues?q=is%3Aissue+is%3Aopen+label%3Agood-first-issue)._
|
||||
|
||||
## Make suggested updates
|
||||
|
||||
### Fork and clone InfluxData Documentation Repository
|
||||
|
||||
[Fork this repository](https://help.github.com/articles/fork-a-repo/) and
|
||||
[clone it](https://help.github.com/articles/cloning-a-repository/) to your local machine.
|
||||
|
||||
## Install project dependencies
|
||||
|
||||
docs-v2 automatically runs format (Markdown, JS, and CSS) linting and code block tests for staged files that you try to commit.
|
||||
|
||||
For the linting and tests to run, you need to install Docker and Node.js
|
||||
dependencies.
|
||||
|
||||
\_**Note:**
|
||||
The git pre-commit and pre-push hooks are configured to run linting and tests automatically
|
||||
when you commit or push changes.
|
||||
We strongly recommend letting them run, but you can skip them
|
||||
(and avoid installing related dependencies)
|
||||
by including the `--no-verify` flag with your commit--for example, enter the following command in your terminal:
|
||||
|
||||
sh
|
||||
git commit -m "<COMMIT_MESSAGE>" --no-verify
|
||||
|
||||
You probably don't want to display this syntax in the docs, which unfortunately
|
||||
means you'd need to include the test block separately from the displayed code
|
||||
block.
|
||||
To hide it from users, wrap the code block inside an HTML comment.
|
||||
pytest-codeblocks will still collect and run the code block.
|
||||
|
||||
##### Mark tests to skip
|
||||
|
||||
pytest-codeblocks has features for skipping tests and marking blocks as failed.
|
||||
To learn more, see the pytest-codeblocks README and tests.
|
||||
|
||||
### Vale style linting
|
||||
|
||||
docs-v2 includes Vale writing style linter configurations to enforce documentation writing style rules, guidelines, branding, and vocabulary terms.
|
||||
|
||||
To run Vale, use the Vale extension for your editor or the included Docker configuration.
|
||||
For example, the following command runs Vale in a container and lints `*.md` (Markdown) files in the path `./content/influxdb/cloud-dedicated/write-data/` using the specified configuration for `cloud-dedicated`:
|
||||
|
||||
diff
|
||||
-Data is taking off. This data is time series. You need a database that specializes in time series. You should check out InfluxDB.
|
||||
+Data is taking off. This data is time series. You need a database that specializes in time series. You need InfluxDB.
|
||||
yaml
|
||||
title: # Title of the page used in the page's h1
|
||||
seotitle: # Page title used in the html <head> title and used in search engine results
|
||||
list_title: # Title used in article lists generated using the {{< children >}} shortcode
|
||||
description: # Page description displayed in search engine results
|
||||
menu:
|
||||
influxdb_2_0:
|
||||
name: # Article name that only appears in the left nav
|
||||
parent: # Specifies a parent group and nests navigation items
|
||||
weight: # Determines sort order in both the nav tree and in article lists
|
||||
draft: # If true, will not render page on build
|
||||
product/v2.x/tags: # Tags specific to each version (replace product and .x" with the appropriate product and minor version )
|
||||
related: # Creates links to specific internal and external content at the bottom of the page
|
||||
- /path/to/related/article
|
||||
- https://external-link.com, This is an external link
|
||||
external_url: # Used in children shortcode type="list" for page links that are external
|
||||
list_image: # Image included with article descriptions in children type="articles" shortcode
|
||||
list_note: # Used in children shortcode type="list" to add a small note next to listed links
|
||||
list_code_example: # Code example included with article descriptions in children type="articles" shortcode
|
||||
list_query_example:# Code examples included with article descriptions in children type="articles" shortcode,
|
||||
# References to examples in data/query_examples
|
||||
canonical: # Path to canonical page, overrides auto-gen'd canonical URL
|
||||
v2: # Path to v2 equivalent page
|
||||
alt_links: # Alternate pages in other products/versions for cross-product navigation
|
||||
cloud-dedicated: /influxdb3/cloud-dedicated/path/to/page/
|
||||
core: /influxdb3/core/path/to/page/
|
||||
prepend: # Prepend markdown content to an article (especially powerful with cascade)
|
||||
block: # (Optional) Wrap content in a block style (note, warn, cloud)
|
||||
content: # Content to prepend to article
|
||||
append: # Append markdown content to an article (especially powerful with cascade)
|
||||
block: # (Optional) Wrap content in a block style (note, warn, cloud)
|
||||
content: # Content to append to article
|
||||
metadata: [] # List of metadata messages to include under the page h1
|
||||
updated_in: # Product and version the referenced feature was updated in (displayed as a unique metadata)
|
||||
source: # Specify a file to pull page content from (typically in /content/shared/)
|
||||
yaml
|
||||
related:
|
||||
- /v2.0/write-data/quick-start
|
||||
- /v2.0/write-data/quick-start, This is custom text for an internal link
|
||||
- https://influxdata.com, This is an external link
|
||||
yaml
|
||||
canonical: /path/to/canonical/doc/
|
||||
|
||||
# OR
|
||||
|
||||
canonical: /{{< latest "influxdb" "v2" >}}/path/to/canonical/doc/
|
||||
```
|
||||
|
||||
### v2 equivalent documentation
|
||||
|
||||
To display a notice on a 1.x page that links to an equivalent 2.0 page,
|
||||
add the following frontmatter to the 1.x page:
|
||||
|
||||
```yaml
|
||||
v2: /influxdb/v2.0/get-started/
|
||||
```
|
||||
|
||||
### Alternative links for cross-product navigation
|
||||
|
||||
Use the `alt_links` frontmatter to specify equivalent pages in other InfluxDB products,
|
||||
for example, when a page exists at a different path in a different version or if
|
||||
the feature doesn't exist in that product.
|
||||
This enables the product switcher to navigate users to the corresponding page when they
|
||||
switch between products. If a page doesn't exist in another product (for example, an
|
||||
Enterprise-only feature), point to the nearest parent page if relevant.
|
||||
|
||||
```yaml
|
||||
alt_links:
|
||||
cloud-dedicated: /influxdb3/cloud-dedicated/admin/tokens/create-token/
|
||||
cloud-serverless: /influxdb3/cloud-serverless/admin/tokens/create-token/
|
||||
core: /influxdb3/core/reference/cli/influxdb3/update/ # Points to parent if exact page doesn't exist
|
||||
```
|
||||
|
||||
Supported product keys for InfluxDB 3:
|
||||
- `core`
|
||||
- `enterprise`
|
||||
- `cloud-serverless`
|
||||
- `cloud-dedicated`
|
||||
- `clustered`
|
||||
|
||||
### Prepend and append content to a page
|
||||
|
||||
Use the `prepend` and `append` frontmatter to add content to the top or bottom of a page.
|
||||
Each has the following fields:
|
||||
|
||||
```yaml
|
||||
append: |
|
||||
> [!Note]
|
||||
> #### This is example markdown content
|
||||
> This is just an example note block that gets appended to the article.
|
||||
```
|
||||
|
||||
Use this frontmatter with [cascade](#cascade) to add the same content to
|
||||
all children pages as well.
|
||||
|
||||
md
|
||||
{{% note %}}
|
||||
Insert note markdown content here.
|
||||
{{% /note %}}
|
||||
|
||||
{{% warn %}}
|
||||
Insert warning markdown content here.
|
||||
{{% /warn %}}
|
||||
|
||||
This is content that references {{< enterprise-name >}}.
|
||||
This is content that references {{< enterprise-name "short" >}}.
|
||||
md
|
||||
{{< latest-patch >}}
|
||||
|
||||
{{< latest-patch product="telegraf" >}}
|
||||
|
||||
{{< latest-patch product="chronograf" version="1.7" >}}
|
||||
md
|
||||
{{< api-endpoint method="get" endpoint="/api/v2/tasks" api-ref="/influxdb/cloud/api/#operation/GetTasks">}}
|
||||
md
|
||||
{{< tabs-wrapper >}}
|
||||
|
||||
{{% tabs %}}
|
||||
[Button text for tab 1](#)
|
||||
[Button text for tab 2](#)
|
||||
{{% /tabs %}}
|
||||
|
||||
{{% tab-content %}}
|
||||
Markdown content for tab 1.
|
||||
{{% /tab-content %}}
|
||||
|
||||
{{% tab-content %}}
|
||||
Markdown content for tab 2.
|
||||
{{% /tab-content %}}
|
||||
|
||||
{{< /tabs-wrapper >}}
|
||||
|
||||
{{% /code-tab-content %}}
|
||||
|
||||
{{% code-tab-content %}}
|
||||
|
||||
md
|
||||
{{< req >}}
|
||||
md
|
||||
{{< req type="key" >}}
|
||||
|
||||
- {{< req "\*" >}} **This element is required**
|
||||
- {{< req "\*" >}} **This element is also required**
|
||||
- **This element is NOT required**
|
||||
md
|
||||
|
||||
|
||||
{{ page-nav prev="/path/to/prev/" next="/path/to/next" >}}
|
||||
|
||||
|
||||
|
||||
{{ page-nav prev="/path/to/prev/" prevText="Previous" next="/path/to/next" nextText="Next" >}}
|
||||
|
||||
|
||||
|
||||
{{ page-nav prev="/path/to/prev/" next="/path/to/next" keepTab=true>}}
|
||||
md
|
||||
{{< diagram >}}
|
||||
flowchart TB
|
||||
This --> That
|
||||
That --> There
|
||||
{{< /diagram >}}
|
||||
html
|
||||
{{< img-hd src="/path/to/image" alt="Alternate title" />}}
|
||||
md
|
||||
{{% truncate %}}
|
||||
Truncated markdown content here.
|
||||
{{% /truncate %}}
|
||||
|
||||
Use the optional `{{< expand-wrapper >}}` shortcode around a group of `{{% expand %}}`
|
||||
shortcodes to ensure proper spacing around the expandable elements:
|
||||
|
||||
### Generate a list of children articles
|
||||
|
||||
Section landing pages often contain just a list of articles with links and descriptions for each.
|
||||
This can be cumbersome to maintain as content is added.
|
||||
To automate the listing of articles in a section, use the `{{< children >}}` shortcode.
|
||||
|
||||
md
|
||||
{{< children readmore=true >}}
|
||||
md
|
||||
/shared/text/example1/example.js
|
||||
/shared/text/example1/example.py
|
||||
md
|
||||
content
|
||||
|
|
||||
|--- api
|
||||
| query.pdmc
|
||||
| query.sh
|
||||
| \_index.md
|
||||
yaml
|
||||
list_query_example: cumulative_sum
|
||||
md
|
||||
{{% token-link "database" "resource/" }}
|
||||
|
||||
|
||||
[database token](/influxdb3/enterprise/admin/tokens/resource/)
|
||||
|
||||
{{< icon "icon-name" "v2" >}}
|
||||
|
||||
{{< nav-icon "tasks" "v2" >}}
|
||||
md
|
||||
{{< flex >}}
|
||||
{{% flex-content %}}
|
||||
Column 1
|
||||
{{% /flex-content %}}
|
||||
{{% flex-content %}}
|
||||
Column 2
|
||||
{{% /flex-content %}}
|
||||
{{< /flex >}}
|
||||
|
||||
The rendered output is "I like butterflies" with "butterflies" highlighted.
|
||||
When you hover over "butterflies," a tooltip appears with the text: "Butterflies are awesome!"
|
||||
|
||||
### Flux sample data tables
|
||||
|
||||
The Flux `sample` package provides basic sample datasets that can be used to
|
||||
illustrate how Flux functions work. To quickly display one of the raw sample
|
||||
datasets, use the `{{% flux/sample %}}` shortcode.
|
||||
|
||||
The `flux/sample` shortcode has the following arguments that can be specified
|
||||
by name or positionally.
|
||||
|
||||
#### set
|
||||
|
||||
Sample dataset to output. Use either `set` argument name or provide the set
|
||||
as the first argument. The following sets are available:
|
||||
|
||||
- float
|
||||
- int
|
||||
- uint
|
||||
- string
|
||||
- bool
|
||||
- numericBool
|
||||
|
||||
#### includeNull
|
||||
|
||||
Specify whether or not to include _null_ values in the dataset.
|
||||
Use either `includeNull` argument name or provide the boolean value as the second argument.
|
||||
|
||||
#### includeRange
|
||||
|
||||
Specify whether or not to include time range columns (`_start` and `_stop`) in the dataset.
|
||||
This is only recommended when showing how functions that require a time range
|
||||
(such as `window()`) operate on input data.
|
||||
Use either `includeRange` argument name or provide the boolean value as the third argument.
|
||||
|
||||
#
|
||||
### Duplicate OSS content in Cloud
|
||||
|
||||
Docs for InfluxDB OSS and InfluxDB Cloud share a majority of content.
|
||||
To prevent duplication of content between versions, use the following shortcodes:
|
||||
|
||||
- `{{< duplicate-oss >}}`
|
||||
- `{{% oss-only %}}`
|
||||
- `{{% cloud-only %}}`
|
||||
|
||||
[Similar patterns apply - see full CONTRIBUTING.md for complete examples]}` shortcode.
|
||||
Use the shortcode on both inline and content blocks:
|
||||
|
||||
#### cloud-only
|
||||
|
||||
Wrap content that should only appear in the Cloud version of the doc with the `{{% cloud-only %}}` shortcode.
|
||||
Use the shortcode on both inline and content blocks:
|
||||
|
||||
### Show or hide content blocks in shared content
|
||||
|
||||
The `source` frontmatter lets you source page content from another file and is
|
||||
used to share content across InfluxDB products. Within the shared content, you
|
||||
can use the `show-in` and `hide-in` shortcodes to conditionally show or hide
|
||||
content blocks based on the InfluxDB "version." Valid "versions" include:
|
||||
|
||||
- v2
|
||||
- cloud
|
||||
- cloud-serverless
|
||||
- cloud-dedicated
|
||||
- clustered
|
||||
- core
|
||||
- enterprise
|
||||
|
||||
#### show-in
|
||||
|
||||
The `show-in` shortcode accepts a comma-delimited string of InfluxDB "versions"
|
||||
to show the content block in. The version is the second level of the page
|
||||
path--for example: `/influxdb/<version>/...`.
|
||||
|
||||
### All-Caps
|
||||
|
||||
Clockface v3 introduces many buttons with text formatted as all-caps.
|
||||
Use the `{{< caps >}}` shortcode to format text to match those buttons.
|
||||
|
||||
html
|
||||
|
||||
{{< influxdbu >}}
|
||||
|
||||
|
||||
{{< influxdbu "influxdb-101" >}}
|
||||
|
||||
|
||||
{{< influxdbu title="Course title" summary="Short course summary." action="Take
|
||||
the course" link="https://university.influxdata.com/" >}}
|
||||
yaml
|
||||
# Pattern
|
||||
menu:
|
||||
<project>_<major-version-number>_<minor-version-number>_ref:
|
||||
# ...
|
||||
|
||||
# Example
|
||||
menu:
|
||||
influxdb_2_0_ref:
|
||||
# ...
|
||||
|
||||
`
|
||||
|
||||
{{< influxdb/host >}}
|
||||
|
||||
{{< influxdb/host "serverless" >}}
|
||||
|
||||
{{% /code-placeholders %}}
|
||||
|
||||
Replace the following:
|
||||
|
||||
- {{% code-placeholder-key %}}`DATABASE_NAME` and `RETENTION_POLICY`{{% /code-placeholder-key %}}: the [database and retention policy mapping (DBRP)](/influxdb/v2/reference/api/influxdb-1x/dbrp/) for the InfluxDB v2 bucket that you want to write to
|
||||
- {{% code-placeholder-key %}
|
||||
|
||||
[Similar patterns apply - see full CONTRIBUTING.md for complete examples]}`USERNAME`{{% /code-placeholder-key %}}: your [InfluxDB 1.x username](/influxdb/v2/reference/api/influxdb-1x/#manage-credentials)
|
||||
- {{% code-placeholder-key %}}`PASSWORD_OR_TOKEN`{{% /code-placeholder-key %}}: your [InfluxDB 1.x password or InfluxDB API token](/influxdb/v2/reference/api/influxdb-1x/#manage-credentials)
|
||||
- {{% code-placeholder-key %}}`API_TOKEN`{{% /code-placeholder-key %}}: your [InfluxDB API token](/influxdb/v2/admin/tokens/)
|
||||
html
|
||||
<div data-component="my-component"></div>
|
||||
js
|
||||
import { debugLog, debugBreak, debugInspect } from './utils/debug-helpers.js';
|
||||
|
||||
const data = debugInspect(someData, 'Data');
|
||||
debugLog('Processing data', 'myFunction');
|
||||
|
||||
function processData() {
|
||||
// Add a breakpoint that works with DevTools
|
||||
debugBreak();
|
||||
|
||||
// Your existing code...
|
||||
}
|
||||
```
|
||||
|
||||
3. Start Hugo in development mode--for example:
|
||||
|
||||
```bash
|
||||
yarn hugo server
|
||||
```
|
||||
|
||||
4. In VS Code, go to Run > Start Debugging, and select the "Debug JS (debug-helpers)" configuration.
|
||||
|
||||
Your system uses the configuration in `launch.json` to launch the site in Chrome
|
||||
and attach the debugger to the Developer Tools console.
|
||||
|
||||
Make sure to remove the debug statements before merging your changes.
|
||||
The debug helpers are designed to be used in development and should not be used in production.
|
|
@ -0,0 +1,89 @@
|
|||
---
|
||||
mode: 'edit'
|
||||
applyTo: "content/{influxdb3/core,influxdb3/enterprise,shared/influxdb3*}/**"
|
||||
---
|
||||
## Best Practices
|
||||
|
||||
- Use UPPERCASE for placeholders to make them easily identifiable
|
||||
- Don't use pronouns in placeholders (e.g., "your", "this")
|
||||
- List placeholders in the same order they appear in the code
|
||||
- Provide clear descriptions including:
|
||||
- - Expected data type or format
|
||||
- - Purpose of the value
|
||||
- - Any constraints or requirements
|
||||
- Mark optional placeholders as "Optional:" in their descriptions
|
||||
- Placeholder key descriptions should fit the context of the code snippet
|
||||
- Include examples for complex formats
|
||||
|
||||
## Writing Placeholder Descriptions
|
||||
|
||||
Descriptions should follow consistent patterns:
|
||||
|
||||
1. **Admin Authentication tokens**:
|
||||
- Recommended: "a {{% token-link "admin" %}} for your {{< product-name >}} instance"
|
||||
- Avoid: "your token", "the token", "an authorization token"
|
||||
2. **Database resource tokens**:
|
||||
- Recommended: "your {{% token-link "database" %}}"{{% show-in "enterprise" %}} with permissions on the specified database{{% /show-in %}}
|
||||
- Avoid: "your token", "the token", "an authorization token"
|
||||
3. **Database names**:
|
||||
- Recommended: "the name of the database to [action]"
|
||||
- Avoid: "your database", "the database name"
|
||||
4. **Conditional content**:
|
||||
- Use `{{% show-in "enterprise" %}}` for content specific to enterprise versions
|
||||
- Example: "your {{% token-link "database" %}}{{% show-in "enterprise" %}} with permission to query the specified database{{% /show-in %}}"
|
||||
|
||||
## Common placeholders for InfluxDB 3
|
||||
|
||||
- `AUTH_TOKEN`: your {{% token-link %}}
|
||||
- `DATABASE_NAME`: the database to use
|
||||
- `TABLE_NAME`: Name of the table/measurement to query or write to
|
||||
- `NODE_ID`: Node ID for a specific node in a cluster
|
||||
- `CLUSTER_ID`: Cluster ID for a specific cluster
|
||||
- `HOST`: InfluxDB server hostname or URL
|
||||
- `PORT`: InfluxDB server port (typically 8181)
|
||||
- `QUERY`: SQL or InfluxQL query string
|
||||
- `LINE_PROTOCOL`: Line protocol data for writes
|
||||
- `PLUGIN_FILENAME`: Name of plugin file to use
|
||||
- `CACHE_NAME`: Name for a new or existing cache
|
||||
|
||||
## Hugo shortcodes in Markdown
|
||||
|
||||
- `{{% code-placeholders "PLACEHOLDER1|PLACEHOLDER2" %}}`: Use this shortcode to define placeholders in code snippets.
|
||||
- `{{% /code-placeholders %}}`: End the shortcode.
|
||||
- `{{% code-placeholder-key %}}`: Use this shortcode to define a specific placeholder key.
|
||||
- `{{% /code-placeholder-key %}}`: End the specific placeholder key shortcode.
|
||||
|
||||
## Language-Specific Placeholder Formatting
|
||||
|
||||
- **Bash/Shell**: Use uppercase variables with no quotes or prefix
|
||||
```bash
|
||||
--database DATABASE_NAME
|
||||
```
|
||||
- Python: Use string literals with quotes
|
||||
```python
|
||||
database_name='DATABASE_NAME'
|
||||
```
|
||||
- JSON: Use key-value pairs with quotes
|
||||
```json
|
||||
{
|
||||
"database": "DATABASE_NAME"
|
||||
}
|
||||
```
|
||||
|
||||
## Real-World Examples from Documentation
|
||||
|
||||
### InfluxDB CLI Commands
|
||||
This pattern appears frequently in CLI documentation:
|
||||
|
||||
{{% code-placeholders "DATABASE_NAME|AUTH_TOKEN" %}}
|
||||
```bash
|
||||
influxdb3 write \
|
||||
--database DATABASE_NAME \
|
||||
--token AUTH_TOKEN \
|
||||
--precision ns
|
||||
{{% /code-placeholders %}}
|
||||
|
||||
Replace the following placeholders with your values:
|
||||
|
||||
{{% code-placeholder-key %}}`DATABASE_NAME`{{% /code-placeholder-key %}}: the name of the database to write to
|
||||
{{% code-placeholder-key %}}`AUTH_TOKEN`{{% /code-placeholder-key %}}: your {{% token-link "database" %}}{{% show-in "enterprise" %}} with write permissions on the specified database{{% /show-in %}}
|
|
@ -11,8 +11,22 @@ node_modules
|
|||
/content/influxdb*/**/api/**/*.html
|
||||
!api-docs/**/.config.yml
|
||||
/api-docs/redoc-static.html*
|
||||
/telegraf-build
|
||||
!telegraf-build/templates
|
||||
!telegraf-build/scripts
|
||||
!telegraf-build/README.md
|
||||
/cypress/downloads/*
|
||||
/cypress/screenshots/*
|
||||
/cypress/videos/*
|
||||
test-results.xml
|
||||
/influxdb3cli-build-scripts/content
|
||||
.vscode/*
|
||||
!.vscode/launch.json
|
||||
.idea
|
||||
**/config.toml
|
||||
package-lock.json
|
||||
tmp
|
||||
tmp
|
||||
|
||||
# Context files for LLMs and AI tools
|
||||
.context/*
|
||||
!.context/README.md
|
||||
|
|
|
@ -0,0 +1,57 @@
|
|||
#!/bin/sh
|
||||
|
||||
if [ "$LEFTHOOK_VERBOSE" = "1" -o "$LEFTHOOK_VERBOSE" = "true" ]; then
|
||||
set -x
|
||||
fi
|
||||
|
||||
if [ "$LEFTHOOK" = "0" ]; then
|
||||
exit 0
|
||||
fi
|
||||
|
||||
call_lefthook()
|
||||
{
|
||||
if test -n "$LEFTHOOK_BIN"
|
||||
then
|
||||
"$LEFTHOOK_BIN" "$@"
|
||||
elif lefthook -h >/dev/null 2>&1
|
||||
then
|
||||
lefthook "$@"
|
||||
else
|
||||
dir="$(git rev-parse --show-toplevel)"
|
||||
osArch=$(uname | tr '[:upper:]' '[:lower:]')
|
||||
cpuArch=$(uname -m | sed 's/aarch64/arm64/;s/x86_64/x64/')
|
||||
if test -f "$dir/node_modules/lefthook-${osArch}-${cpuArch}/bin/lefthook"
|
||||
then
|
||||
"$dir/node_modules/lefthook-${osArch}-${cpuArch}/bin/lefthook" "$@"
|
||||
elif test -f "$dir/node_modules/@evilmartians/lefthook/bin/lefthook-${osArch}-${cpuArch}/lefthook"
|
||||
then
|
||||
"$dir/node_modules/@evilmartians/lefthook/bin/lefthook-${osArch}-${cpuArch}/lefthook" "$@"
|
||||
elif test -f "$dir/node_modules/@evilmartians/lefthook-installer/bin/lefthook"
|
||||
then
|
||||
"$dir/node_modules/@evilmartians/lefthook-installer/bin/lefthook" "$@"
|
||||
elif test -f "$dir/node_modules/lefthook/bin/index.js"
|
||||
then
|
||||
"$dir/node_modules/lefthook/bin/index.js" "$@"
|
||||
|
||||
elif bundle exec lefthook -h >/dev/null 2>&1
|
||||
then
|
||||
bundle exec lefthook "$@"
|
||||
elif yarn lefthook -h >/dev/null 2>&1
|
||||
then
|
||||
yarn lefthook "$@"
|
||||
elif pnpm lefthook -h >/dev/null 2>&1
|
||||
then
|
||||
pnpm lefthook "$@"
|
||||
elif swift package plugin lefthook >/dev/null 2>&1
|
||||
then
|
||||
swift package --disable-sandbox plugin lefthook "$@"
|
||||
elif command -v mint >/dev/null 2>&1
|
||||
then
|
||||
mint run csjones/lefthook-plugin "$@"
|
||||
else
|
||||
echo "Can't find lefthook in PATH"
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
call_lefthook run "serve" "$@"
|
|
@ -3,3 +3,4 @@
|
|||
**/.svn
|
||||
**/.hg
|
||||
**/node_modules
|
||||
assets/jsconfig.json
|
|
@ -0,0 +1,47 @@
|
|||
{
|
||||
"version": "0.2.0",
|
||||
"configurations": [
|
||||
{
|
||||
"name": "Debug JS (debug-helpers)",
|
||||
"type": "chrome",
|
||||
"request": "launch",
|
||||
"url": "http://localhost:1313",
|
||||
"webRoot": "${workspaceFolder}",
|
||||
"skipFiles": [
|
||||
"<node_internals>/**"
|
||||
],
|
||||
"sourceMaps": false,
|
||||
"trace": true,
|
||||
"smartStep": false
|
||||
},
|
||||
{
|
||||
"name": "Debug JS (source maps)",
|
||||
"type": "chrome",
|
||||
"request": "launch",
|
||||
"url": "http://localhost:1313",
|
||||
"webRoot": "${workspaceFolder}",
|
||||
"sourceMaps": true,
|
||||
"sourceMapPathOverrides": {
|
||||
"*": "${webRoot}/assets/js/*",
|
||||
"main.js": "${webRoot}/assets/js/main.js",
|
||||
"page-context.js": "${webRoot}/assets/js/page-context.js",
|
||||
"ask-ai-trigger.js": "${webRoot}/assets/js/ask-ai-trigger.js",
|
||||
"ask-ai.js": "${webRoot}/assets/js/ask-ai.js",
|
||||
"utils/*": "${webRoot}/assets/js/utils/*",
|
||||
"services/*": "${webRoot}/assets/js/services/*"
|
||||
},
|
||||
"skipFiles": [
|
||||
"<node_internals>/**",
|
||||
"node_modules/**",
|
||||
"chrome-extension://**"
|
||||
],
|
||||
"trace": true,
|
||||
"smartStep": true,
|
||||
"disableNetworkCache": true,
|
||||
"userDataDir": "${workspaceFolder}/.vscode/chrome-user-data",
|
||||
"runtimeArgs": [
|
||||
"--disable-features=VizDisplayCompositor"
|
||||
]
|
||||
},
|
||||
]
|
||||
}
|
|
@ -0,0 +1,25 @@
|
|||
# Instructions for InfluxData Documentation
|
||||
|
||||
## Purpose and scope
|
||||
|
||||
Claude should help document InfluxData products by creating clear, accurate technical content with proper code examples, frontmatter, and formatting.
|
||||
|
||||
## Project overview
|
||||
|
||||
See @README.md
|
||||
|
||||
## Available NPM commands
|
||||
|
||||
@package.json
|
||||
|
||||
## Instructions for contributing
|
||||
|
||||
See @.github/copilot-instructions.md for style guidelines and
|
||||
product-specific documentation paths and URLs managed in this project.
|
||||
|
||||
See @.github/instructions/contributing.instructions.md for contributing
|
||||
information including using shortcodes and running tests.
|
||||
|
||||
See @.github/instructions/influxdb3-code-placeholders.instructions.md for using
|
||||
placeholders in code samples and CLI commands.
|
||||
|
171
CONTRIBUTING.md
171
CONTRIBUTING.md
|
@ -1,6 +1,6 @@
|
|||
# Contributing to InfluxData Documentation
|
||||
|
||||
## Sign the InfluxData CLA
|
||||
### Sign the InfluxData CLA
|
||||
|
||||
The InfluxData Contributor License Agreement (CLA) is part of the legal framework
|
||||
for the open source ecosystem that protects both you and InfluxData.
|
||||
|
@ -28,8 +28,10 @@ For the linting and tests to run, you need to install Docker and Node.js
|
|||
dependencies.
|
||||
|
||||
\_**Note:**
|
||||
We strongly recommend running linting and tests, but you can skip them
|
||||
(and avoid installing dependencies)
|
||||
The git pre-commit and pre-push hooks are configured to run linting and tests automatically
|
||||
when you commit or push changes.
|
||||
We strongly recommend letting them run, but you can skip them
|
||||
(and avoid installing related dependencies)
|
||||
by including the `--no-verify` flag with your commit--for example, enter the following command in your terminal:
|
||||
|
||||
```sh
|
||||
|
@ -51,7 +53,7 @@ dev dependencies used in pre-commit hooks for linting, syntax-checking, and test
|
|||
Dev dependencies include:
|
||||
|
||||
- [Lefthook](https://github.com/evilmartians/lefthook): configures and
|
||||
manages pre-commit hooks for linting and testing Markdown content.
|
||||
manages git pre-commit and pre-push hooks for linting and testing Markdown content.
|
||||
- [prettier](https://prettier.io/docs/en/): formats code, including Markdown, according to style rules for consistency
|
||||
- [Cypress]: e2e testing for UI elements and URLs in content
|
||||
|
||||
|
@ -93,9 +95,11 @@ Make your suggested changes being sure to follow the [style and formatting guide
|
|||
|
||||
## Lint and test your changes
|
||||
|
||||
`package.json` contains scripts for running tests and linting.
|
||||
|
||||
### Automatic pre-commit checks
|
||||
|
||||
docs-v2 uses Lefthook to manage Git hooks, such as pre-commit hooks that lint Markdown and test code blocks.
|
||||
docs-v2 uses Lefthook to manage Git hooks that run during pre-commit and pre-push. The hooks run the scripts defined in `package.json` to lint Markdown and test code blocks.
|
||||
When you try to commit changes (`git commit`), Git runs
|
||||
the commands configured in `lefthook.yml` which pass your **staged** files to Vale,
|
||||
Prettier, Cypress (for UI tests and link-checking), and Pytest (for testing Python and shell code in code blocks).
|
||||
|
@ -359,6 +363,9 @@ list_query_example:# Code examples included with article descriptions in childre
|
|||
# References to examples in data/query_examples
|
||||
canonical: # Path to canonical page, overrides auto-gen'd canonical URL
|
||||
v2: # Path to v2 equivalent page
|
||||
alt_links: # Alternate pages in other products/versions for cross-product navigation
|
||||
cloud-dedicated: /influxdb3/cloud-dedicated/path/to/page/
|
||||
core: /influxdb3/core/path/to/page/
|
||||
prepend: # Prepend markdown content to an article (especially powerful with cascade)
|
||||
block: # (Optional) Wrap content in a block style (note, warn, cloud)
|
||||
content: # Content to prepend to article
|
||||
|
@ -450,6 +457,29 @@ add the following frontmatter to the 1.x page:
|
|||
v2: /influxdb/v2.0/get-started/
|
||||
```
|
||||
|
||||
### Alternative links for cross-product navigation
|
||||
|
||||
Use the `alt_links` frontmatter to specify equivalent pages in other InfluxDB products,
|
||||
for example, when a page exists at a different path in a different version or if
|
||||
the feature doesn't exist in that product.
|
||||
This enables the product switcher to navigate users to the corresponding page when they
|
||||
switch between products. If a page doesn't exist in another product (for example, an
|
||||
Enterprise-only feature), point to the nearest parent page if relevant.
|
||||
|
||||
```yaml
|
||||
alt_links:
|
||||
cloud-dedicated: /influxdb3/cloud-dedicated/admin/tokens/create-token/
|
||||
cloud-serverless: /influxdb3/cloud-serverless/admin/tokens/create-token/
|
||||
core: /influxdb3/core/reference/cli/influxdb3/update/ # Points to parent if exact page doesn't exist
|
||||
```
|
||||
|
||||
Supported product keys for InfluxDB 3:
|
||||
- `core`
|
||||
- `enterprise`
|
||||
- `cloud-serverless`
|
||||
- `cloud-dedicated`
|
||||
- `clustered`
|
||||
|
||||
### Prepend and append content to a page
|
||||
|
||||
Use the `prepend` and `append` frontmatter to add content to the top or bottom of a page.
|
||||
|
@ -577,14 +607,14 @@ Easier to maintain being you update the version number in the `data/products.yml
|
|||
|
||||
### Latest influx CLI version
|
||||
|
||||
Use the `{{< latest-cli >}}` shortcode to add the latest version of the `influx`
|
||||
Use the `{{< latest-patch cli=true >}}` shortcode to add the latest version of the `influx`
|
||||
CLI supported by the minor version of InfluxDB.
|
||||
By default, this shortcode parses the minor version from the URL.
|
||||
To specify a specific minor version, use the `version` argument.
|
||||
Maintain CLI version numbers in the `data/products.yml` file instead of updating individual links and code examples.
|
||||
|
||||
```md
|
||||
{{< latest-cli >}}
|
||||
{{< latest-patch cli=true >}}
|
||||
|
||||
{{< latest-cli version="2.1" >}}
|
||||
```
|
||||
|
@ -1126,6 +1156,28 @@ The following table shows which children types use which frontmatter properties:
|
|||
| `list_code_example` | ✓ | | |
|
||||
| `list_query_example` | ✓ | | |
|
||||
|
||||
### Authentication token link
|
||||
|
||||
Use the `{{% token-link "<descriptor>" "<link_append>%}}` shortcode to
|
||||
automatically generate links to token management documentation. The shortcode
|
||||
accepts two _optional_ arguments:
|
||||
|
||||
- **descriptor**: An optional token descriptor
|
||||
- **link_append**: An optional path to append to the token management link path,
|
||||
`/<product>/<version>/admin/tokens/`.
|
||||
|
||||
```md
|
||||
{{% token-link "database" "resource/" }}
|
||||
|
||||
<!-- Renders as -->
|
||||
[database token](/influxdb3/enterprise/admin/tokens/resource/)
|
||||
```
|
||||
|
||||
InfluxDB 3 Enterprise and InfluxDB 3 Core support different kinds of tokens.
|
||||
The shortcode has a blacklist of token descriptors for each that will prevent
|
||||
unsupported descriptors from appearing in the rendered output based on the
|
||||
current product.
|
||||
|
||||
### Inline icons
|
||||
|
||||
The `icon` shortcode allows you to inject icons in paragraph text.
|
||||
|
@ -1633,6 +1685,31 @@ Supported argument values:
|
|||
{{< influxdb/host "serverless" >}}
|
||||
```
|
||||
|
||||
### User-populated placeholders
|
||||
|
||||
Use the `code-placeholders` shortcode to format placeholders
|
||||
as text fields that users can populate with their own values.
|
||||
The shortcode takes a regular expression for matching placeholder names.
|
||||
Use the `code-placeholder-key` shortcode to format the placeholder names in
|
||||
text that describes the placeholder--for example:
|
||||
|
||||
```markdown
|
||||
{{% code-placeholders "DATABASE_NAME|USERNAME|PASSWORD_OR_TOKEN|API_TOKEN|exampleuser@influxdata.com" %}}
|
||||
```sh
|
||||
curl --request POST http://localhost:8086/write?db=DATABASE_NAME \
|
||||
--header "Authorization: Token API_TOKEN" \
|
||||
--data-binary @path/to/line-protocol.txt
|
||||
```
|
||||
{{% /code-placeholders %}}
|
||||
|
||||
Replace the following:
|
||||
|
||||
- {{% code-placeholder-key %}}`DATABASE_NAME` and `RETENTION_POLICY`{{% /code-placeholder-key %}}: the [database and retention policy mapping (DBRP)](/influxdb/v2/reference/api/influxdb-1x/dbrp/) for the InfluxDB v2 bucket that you want to write to
|
||||
- {{% code-placeholder-key %}}`USERNAME`{{% /code-placeholder-key %}}: your [InfluxDB 1.x username](/influxdb/v2/reference/api/influxdb-1x/#manage-credentials)
|
||||
- {{% code-placeholder-key %}}`PASSWORD_OR_TOKEN`{{% /code-placeholder-key %}}: your [InfluxDB 1.x password or InfluxDB API token](/influxdb/v2/reference/api/influxdb-1x/#manage-credentials)
|
||||
- {{% code-placeholder-key %}}`API_TOKEN`{{% /code-placeholder-key %}}: your [InfluxDB API token](/influxdb/v2/admin/tokens/)
|
||||
```
|
||||
|
||||
## InfluxDB API documentation
|
||||
|
||||
InfluxData uses [Redoc](https://github.com/Redocly/redoc) to generate the full
|
||||
|
@ -1640,3 +1717,83 @@ InfluxDB API documentation when documentation is deployed.
|
|||
Redoc generates HTML documentation using the InfluxDB `swagger.yml`.
|
||||
For more information about generating InfluxDB API documentation, see the
|
||||
[API Documentation README](https://github.com/influxdata/docs-v2/tree/master/api-docs#readme).
|
||||
|
||||
## JavaScript in the documentation UI
|
||||
|
||||
The InfluxData documentation UI uses JavaScript with ES6+ syntax and
|
||||
`assets/js/main.js` as the entry point to import modules from
|
||||
`assets/js`.
|
||||
Only `assets/js/main.js` should be imported in HTML files.
|
||||
|
||||
`assets/js/main.js` registers components and initializes them on page load.
|
||||
|
||||
If you're adding UI functionality that requires JavaScript, follow these steps:
|
||||
|
||||
1. In your HTML file, add a `data-component` attribute to the element that
|
||||
should be initialized by your JavaScript code. For example:
|
||||
|
||||
```html
|
||||
<div data-component="my-component"></div>
|
||||
```
|
||||
|
||||
2. Following the component pattern, create a single-purpose JavaScript module
|
||||
(`assets/js/components/my-component.js`)
|
||||
that exports a single function that receives the component element and initializes it.
|
||||
3. In `assets/js/main.js`, import the module and register the component to ensure
|
||||
the component is initialized on page load.
|
||||
|
||||
### Debugging JavaScript
|
||||
|
||||
To debug JavaScript code used in the InfluxData documentation UI, choose one of the following methods:
|
||||
|
||||
- Use source maps and the Chrome DevTools debugger.
|
||||
- Use debug helpers that provide breakpoints and console logging as a workaround or alternative for using source maps and the Chrome DevTools debugger.
|
||||
|
||||
#### Using source maps and Chrome DevTools debugger
|
||||
|
||||
1. In VS Code, select Run > Start Debugging.
|
||||
2. Select the "Debug Docs (source maps)" configuration.
|
||||
3. Click the play button to start the debugger.
|
||||
5. Set breakpoints in the JavaScript source files--files in the
|
||||
`assets/js/ns-hugo-imp:` namespace-- in the
|
||||
VS Code editor or in the Chrome Developer Tools Sources panel:
|
||||
|
||||
- In the VS Code Debugger panel > "Loaded Scripts" section, find the
|
||||
`assets/js/ns-hugo-imp:` namespace.
|
||||
- In the Chrome Developer Tools Sources panel, expand
|
||||
`js/ns-hugo-imp:/<YOUR_WORKSPACE_ROOT>/assets/js/`.
|
||||
|
||||
#### Using debug helpers
|
||||
|
||||
1. In your JavaScript module, import debug helpers from `assets/js/utils/debug-helpers.js`.
|
||||
These helpers provide breakpoints and console logging as a workaround or alternative for
|
||||
using source maps and the Chrome DevTools debugger.
|
||||
2. Insert debug statements by calling the helper functions in your code--for example:
|
||||
|
||||
```js
|
||||
import { debugLog, debugBreak, debugInspect } from './utils/debug-helpers.js';
|
||||
|
||||
const data = debugInspect(someData, 'Data');
|
||||
debugLog('Processing data', 'myFunction');
|
||||
|
||||
function processData() {
|
||||
// Add a breakpoint that works with DevTools
|
||||
debugBreak();
|
||||
|
||||
// Your existing code...
|
||||
}
|
||||
```
|
||||
|
||||
3. Start Hugo in development mode--for example:
|
||||
|
||||
```bash
|
||||
yarn hugo server
|
||||
```
|
||||
|
||||
4. In VS Code, go to Run > Start Debugging, and select the "Debug JS (debug-helpers)" configuration.
|
||||
|
||||
Your system uses the configuration in `launch.json` to launch the site in Chrome
|
||||
and attach the debugger to the Developer Tools console.
|
||||
|
||||
Make sure to remove the debug statements before merging your changes.
|
||||
The debug helpers are designed to be used in development and should not be used in production.
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
plugins:
|
||||
- './../openapi/plugins/docs-plugin.js'
|
||||
- './../openapi/plugins/docs-plugin.cjs'
|
||||
extends:
|
||||
- recommended
|
||||
- docs/all
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
plugins:
|
||||
- '../../openapi/plugins/docs-plugin.js'
|
||||
- '../../openapi/plugins/docs-plugin.cjs'
|
||||
extends:
|
||||
- recommended
|
||||
- docs/all
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
plugins:
|
||||
- '../../openapi/plugins/docs-plugin.js'
|
||||
- '../../openapi/plugins/docs-plugin.cjs'
|
||||
extends:
|
||||
- recommended
|
||||
- docs/all
|
||||
|
|
|
@ -218,11 +218,11 @@ tags:
|
|||
|:-----------:|:------------------------ |:--------------------- |
|
||||
| `200` | Success | |
|
||||
| `204` | Success. No content | InfluxDB doesn't return data for the request. |
|
||||
| `400` | Bad request | May indicate one of the following: <ul><li>Line protocol is malformed. The response body contains the first malformed line in the data and indicates what was expected. For partial writes, the number of points written and the number of points rejected are also included. For more information, check the `rejected_points` measurement in your `_monitoring` bucket.</li><li>`Authorization` header is missing or malformed or the API token doesn't have permission for the operation.</li></ul> |
|
||||
| `400` | Bad request | May indicate one of the following:<ul><li>the request body is malformed</li><li>`Authorization` header is missing or malformed</li><li>the API token doesn't have permission for the operation.</li></ul> |
|
||||
| `401` | Unauthorized | May indicate one of the following: <ul><li>`Authorization: Token` header is missing or malformed</li><li>API token value is missing from the header</li><li>API token doesn't have permission. For more information about token types and permissions, see [Manage API tokens](/influxdb/v2/security/tokens/)</li></ul> |
|
||||
| `404` | Not found | Requested resource was not found. `message` in the response body provides details about the requested resource. |
|
||||
| `413` | Request entity too large | Request payload exceeds the size limit. |
|
||||
| `422` | Unprocessable entity | Request data is invalid. `code` and `message` in the response body provide details about the problem. |
|
||||
| `422` | Unprocessable entity | Request data is invalid. The request was well-formed, but couldn't complete due to semantic errors--for example, some or all points in a write request were rejected due to a schema or retention policy violation. The response body provides details about the problem. For more information about rejected points, see how to [Troubleshoot issues writing data](/influxdb/v2/write-data/troubleshoot/)|
|
||||
| `429` | Too many requests | API token is temporarily over the request quota. The `Retry-After` header describes when to try the request again. |
|
||||
| `500` | Internal server error | |
|
||||
| `503` | Service unavailable | Server is temporarily unavailable to process the request. The `Retry-After` header describes when to try the request again. |
|
||||
|
@ -12752,6 +12752,12 @@ paths:
|
|||
|
||||
- Returns this error only if the [Go (golang) `ioutil.ReadAll()`](https://pkg.go.dev/io/ioutil#ReadAll) function raises an error.
|
||||
- Returns `Content-Type: application/json` for this error.
|
||||
'422':
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/Error'
|
||||
description: The request was well-formed, but some or all the points were rejected due to semantic errors--for example, schema conflicts or retention policy violations. Error message contains details for one or more rejected points.
|
||||
'429':
|
||||
description: |
|
||||
Too many requests.
|
||||
|
@ -13190,6 +13196,14 @@ paths:
|
|||
- Legacy Query
|
||||
/write:
|
||||
post:
|
||||
description: |-
|
||||
Writes line protocol to the specified bucket.
|
||||
|
||||
This endpoint provides backward compatibility for InfluxDB 1.x write workloads using tools such as InfluxDB 1.x client libraries, the Telegraf `outputs.influxdb` output plugin, or third-party tools.
|
||||
|
||||
Use this endpoint to send data in [line protocol](https://docs.influxdata.com/influxdb/v2/reference/syntax/line-protocol/) format to InfluxDB.
|
||||
Use query parameters to specify options for writing data.
|
||||
|
||||
operationId: PostLegacyWrite
|
||||
parameters:
|
||||
- $ref: '#/components/parameters/TraceSpan'
|
||||
|
@ -13263,6 +13277,12 @@ paths:
|
|||
schema:
|
||||
$ref: '#/components/schemas/LineProtocolLengthError'
|
||||
description: Write has been rejected because the payload is too large. Error message returns max size supported. All data in body was rejected and not written.
|
||||
'422':
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/Error'
|
||||
description: The request was well-formed, but some or all the points were rejected due to semantic errors--for example, schema conflicts or retention policy violations. Error message contains details for one or more rejected points.
|
||||
'429':
|
||||
description: Token is temporarily over quota. The Retry-After header describes when to try the write again.
|
||||
headers:
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
plugins:
|
||||
- '../../openapi/plugins/docs-plugin.js'
|
||||
- '../../openapi/plugins/docs-plugin.cjs'
|
||||
extends:
|
||||
- recommended
|
||||
- docs/all
|
||||
|
|
|
@ -40,6 +40,7 @@ tags:
|
|||
See how to [create a management token](/influxdb3/cloud-dedicated/admin/tokens/management/).
|
||||
|
||||
By default, management tokens in InfluxDB 3 are short-lived tokens issued by an OAuth2 identity provider that grant a specific user administrative access to your InfluxDB cluster. However, for automation purposes, you can manually create management tokens that authenticate directly with your InfluxDB cluster and do not require human interaction with your identity provider.
|
||||
<!-- ReDoc-Inject: <security-definitions> -->
|
||||
- name: Database tokens
|
||||
description: Manage database read/write tokens for a cluster
|
||||
- name: Databases
|
||||
|
@ -397,6 +398,26 @@ paths:
|
|||
post:
|
||||
operationId: CreateClusterDatabase
|
||||
summary: Create a database
|
||||
description: |
|
||||
Create a database for a cluster.
|
||||
|
||||
The database name must be unique within the cluster.
|
||||
|
||||
**Default maximum number of columns**: 250
|
||||
**Default maximum number of tables**: 500
|
||||
|
||||
The retention period is specified in nanoseconds. For example, to set a retention period of 1 hour, use `3600000000000`.
|
||||
|
||||
InfluxDB Cloud Dedicated lets you define a [custom partitioning](/influxdb3/cloud-dedicated/admin/custom-partitions/) strategy for each database and table.
|
||||
A _partition_ is a logical grouping of data stored in [Apache Parquet](https://parquet.apache.org/).
|
||||
By default, data is partitioned by day,
|
||||
but, depending on your schema and workload, customizing the partitioning
|
||||
strategy can improve query performance.
|
||||
|
||||
To use custom partitioning, you define a [partition template](/influxdb3/cloud-dedicated/admin/custom-partitions/partition-templates/).
|
||||
If a table doesn't have a custom partition template, it inherits the database's template.
|
||||
The partition template is set at the time of database creation and cannot be changed later.
|
||||
For more information, see [Custom partitions](/influxdb3/cloud-dedicated/admin/custom-partitions/).
|
||||
tags:
|
||||
- Databases
|
||||
parameters:
|
||||
|
@ -779,6 +800,18 @@ paths:
|
|||
post:
|
||||
operationId: CreateClusterDatabaseTable
|
||||
summary: Create a database table
|
||||
description: |
|
||||
Create a table. The database must already exist. With InfluxDB Cloud Dedicated, tables and measurements are synonymous.
|
||||
|
||||
Typically, tables are created automatically on write using the measurement name
|
||||
specified in line protocol written to InfluxDB.
|
||||
However, to apply a [custom partition template](/influxdb3/cloud-dedicated/admin/custom-partitions/)
|
||||
to a table, you must manually [create the table with custom partitioning](/influxdb3/cloud-dedicated/admin/tables/#create-a-table-with-custom-partitioning) before you write any data to it.
|
||||
|
||||
Partitioning defaults to `%Y-%m-%d` (daily).
|
||||
When a partition template is applied to a database, it becomes the default template
|
||||
for all tables in that database, but can be overridden when creating a
|
||||
table.
|
||||
tags:
|
||||
- Tables
|
||||
parameters:
|
||||
|
@ -1195,6 +1228,14 @@ paths:
|
|||
get:
|
||||
operationId: GetDatabaseToken
|
||||
summary: Get a database token
|
||||
description: |
|
||||
Retrieve metadata details for a [database token](/influxdb3/cloud-dedicated/admin/tokens/database/).
|
||||
|
||||
#### Store secure tokens in a secret store
|
||||
|
||||
We recommend storing database tokens in a **secure secret store**.
|
||||
|
||||
Token strings are viewable _only_ on token creation and aren't stored by InfluxDB; you can't recover a lost token.
|
||||
tags:
|
||||
- Database tokens
|
||||
parameters:
|
||||
|
@ -1313,6 +1354,8 @@ paths:
|
|||
patch:
|
||||
operationId: UpdateDatabaseToken
|
||||
summary: Update a database token
|
||||
description: |
|
||||
Update the description and permissions of a [database token](/influxdb3/cloud-dedicated/admin/tokens/database/).
|
||||
tags:
|
||||
- Database tokens
|
||||
parameters:
|
||||
|
@ -1331,7 +1374,6 @@ paths:
|
|||
- name: tokenId
|
||||
in: path
|
||||
description: The ID of the [database token](/influxdb3/cloud-dedicated/admin/tokens/database/) to update
|
||||
required: true
|
||||
schema:
|
||||
$ref: '#/components/schemas/UuidV4'
|
||||
requestBody:
|
||||
|
@ -1643,9 +1685,9 @@ components:
|
|||
description: |
|
||||
A template for [partitioning](/influxdb3/cloud-dedicated/admin/custom-partitions/) a cluster database.
|
||||
|
||||
Each template part is evaluated in sequence, concatinating the final
|
||||
partition key from the output of each part, delimited by the partition
|
||||
key delimiter `|`.
|
||||
Each partition template part is evaluated in sequence.
|
||||
The outputs from each part are concatenated with the
|
||||
`|` delimiter to form the final partition key.
|
||||
|
||||
For example, using the partition template below:
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
plugins:
|
||||
- '../../openapi/plugins/docs-plugin.js'
|
||||
- '../../openapi/plugins/docs-plugin.cjs'
|
||||
extends:
|
||||
- recommended
|
||||
- docs/all
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
plugins:
|
||||
- '../../openapi/plugins/docs-plugin.js'
|
||||
- '../../openapi/plugins/docs-plugin.cjs'
|
||||
extends:
|
||||
- recommended
|
||||
- docs/all
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
plugins:
|
||||
- '../../openapi/plugins/docs-plugin.js'
|
||||
- '../../openapi/plugins/docs-plugin.cjs'
|
||||
extends:
|
||||
- recommended
|
||||
- docs/all
|
||||
|
@ -10,3 +10,7 @@ apis:
|
|||
root: v3/ref.yml
|
||||
x-influxdata-docs-aliases:
|
||||
- /influxdb3/core/api/
|
||||
- /influxdb3/core/api/v1/
|
||||
- /influxdb3/core/api/v2/
|
||||
- /influxdb3/core/api/v1-compatibility
|
||||
- /influxdb3/core/api/v2-compatibility
|
||||
|
|
|
@ -2,11 +2,14 @@
|
|||
tags:
|
||||
- Quick start
|
||||
- Authentication
|
||||
- Cache data
|
||||
- Common parameters
|
||||
- Response codes
|
||||
- Compatibility endpoints
|
||||
- Data I/O
|
||||
- Databases
|
||||
- Database
|
||||
- Processing engine
|
||||
- Server information
|
||||
- Tables
|
||||
- Table
|
||||
- Token
|
||||
- Query data
|
||||
- Write data
|
||||
|
|
|
@ -43,8 +43,50 @@ security:
|
|||
tags:
|
||||
- name: Authentication
|
||||
description: |
|
||||
During the Beta phase, InfluxDB 3 Core does not require authentication.
|
||||
Authenticate to the InfluxDB 3 API using a bearer token.
|
||||
|
||||
The InfluxDB 3 API uses tokens for authentication.
|
||||
To authenticate, include the `Authorization` header in your request with the value `Bearer <token>`.
|
||||
The token must be a valid InfluxDB 3 admin token.
|
||||
|
||||
#### Related guides
|
||||
|
||||
- [Manage tokens](/influxdb3/core/admin/tokens/)
|
||||
- [Authentication and authorization](/influxdb3/core/reference/internals/authentication/)
|
||||
x-traitTag: true
|
||||
- name: Cache data
|
||||
description: |
|
||||
Manage the in-memory cache.
|
||||
|
||||
#### Distinct Value Cache
|
||||
|
||||
The Distinct Value Cache (DVC) lets you cache distinct
|
||||
values of one or more columns in a table, improving the performance of
|
||||
queries that return distinct tag and field values.
|
||||
|
||||
The DVC is an in-memory cache that stores distinct values for specific columns
|
||||
in a table. When you create an DVC, you can specify what columns' distinct
|
||||
values to cache, the maximum number of distinct value combinations to cache, and
|
||||
the maximum age of cached values. A DVC is associated with a table, which can
|
||||
have multiple DVCs.
|
||||
|
||||
#### Last value cache
|
||||
|
||||
The Last Value Cache (LVC) lets you cache the most recent
|
||||
values for specific fields in a table, improving the performance of queries that
|
||||
return the most recent value of a field for specific series or the last N values
|
||||
of a field.
|
||||
|
||||
The LVC is an in-memory cache that stores the last N number of values for
|
||||
specific fields of series in a table. When you create an LVC, you can specify
|
||||
what fields to cache, what tags to use to identify each series, and the
|
||||
number of values to cache for each unique series.
|
||||
An LVC is associated with a table, which can have multiple LVCs.
|
||||
|
||||
#### Related guides
|
||||
|
||||
- [Manage the Distinct Value Cache](/influxdb3/core/admin/distinct-value-cache/)
|
||||
- [Manage the Last Value Cache](/influxdb3/core/admin/last-value-cache/)
|
||||
- name: Compatibility endpoints
|
||||
description: |
|
||||
InfluxDB 3 provides compatibility endpoints for InfluxDB 1.x and InfluxDB 2.x workloads and clients.
|
||||
|
@ -72,19 +114,8 @@ tags:
|
|||
### Server information
|
||||
|
||||
Server information endpoints such as `/health` and `metrics` are compatible with InfluxDB 1.x and InfluxDB 2.x clients.
|
||||
- name: Data I/O
|
||||
description: |
|
||||
Write and query data
|
||||
|
||||
#### Data flow in InfluxDB 3 Core
|
||||
|
||||
1. **Incoming writes**: The system validates incoming data and stores it in the write buffer (in memory). If the `no_sync` write option is enabled (`no_sync=true`), the server sends a response to acknowledge the write.
|
||||
2. **WAL flush**: Every second (default), the system flushes the write buffer to the Write-Ahead Log (WAL) for persistence in the Object store. If `no_sync=false` (default), the server sends a response to acknowledge the write.
|
||||
3. **Query availability**: After WAL persistence completes, data moves to the queryable buffer where it becomes available for queries. By default, the server keeps up to 900 WAL files (15 minutes of data) buffered.
|
||||
4. **Long-term storage in Parquet**: Every ten minutes (default), the system persists the oldest data from the queryable buffer to the Object store in Parquet format. InfluxDB keeps the remaining data (the most recent 5 minutes) in memory.
|
||||
5. **In-memory cache**: InfluxDB puts Parquet files into an in-memory cache so that queries against the most recently persisted data don't have to go to object storage.
|
||||
- name: Databases
|
||||
description: Create, read, update, and delete database and cache resources
|
||||
- name: Database
|
||||
description: Manage databases
|
||||
- description: |
|
||||
Most InfluxDB API endpoints require parameters in the request--for example, specifying the database to use.
|
||||
|
||||
|
@ -115,32 +146,42 @@ tags:
|
|||
description: |
|
||||
Manage Processing engine triggers, test plugins, and send requests to trigger On Request plugins.
|
||||
|
||||
InfluxDB 3 Core provides the InfluxDB 3 Processing engine, an embedded Python VM that can dynamically load and trigger Python plugins in response to events in your database.
|
||||
InfluxDB 3 Core provides the InfluxDB 3 processing engine, an embedded Python VM that can dynamically load and trigger Python plugins in response to events in your database.
|
||||
Use Processing engine plugins and triggers to run code and perform tasks for different database events.
|
||||
|
||||
To get started with the Processing engine, see the [Processing engine and Python plugins](/influxdb3/core/processing-engine/) guide.
|
||||
To get started with the processing engine, see the [Processing engine and Python plugins](/influxdb3/core/processing-engine/) guide.
|
||||
- name: Query data
|
||||
description: Query data using SQL or InfluxQL
|
||||
- name: Quick start
|
||||
description: |
|
||||
1. [Check the status](#section/Server-information) of the InfluxDB server.
|
||||
1. [Create an admin token](#section/Authentication) to authorize API requests.
|
||||
|
||||
```bash
|
||||
curl "http://localhost:8181/health"
|
||||
curl -X POST "http://localhost:8181/api/v3/configure/token/admin"
|
||||
```
|
||||
2. [Check the status](#section/Server-information) of the InfluxDB server.
|
||||
|
||||
```bash
|
||||
curl "http://localhost:8181/health" \
|
||||
--header "Authorization: Bearer ADMIN_TOKEN"
|
||||
```
|
||||
|
||||
2. [Write data](#section/Compatibility-endpoints/Write-data) to InfluxDB.
|
||||
3. [Write data](#operation/PostWriteLP) to InfluxDB.
|
||||
|
||||
```bash
|
||||
curl "http://localhost:8181/api/v3/write_lp?db=sensors&precision=auto" \
|
||||
curl "http://localhost:8181/api/v3/write_lp?db=sensors&precision=auto"
|
||||
--header "Authorization: Bearer ADMIN_TOKEN" \
|
||||
--data-raw "home,room=Kitchen temp=72.0
|
||||
home,room=Living\ room temp=71.5"
|
||||
```
|
||||
|
||||
If all data is written, the response is `204 No Content`.
|
||||
|
||||
3. [Query data](#section/Compatibility-endpoints/Query-data) from InfluxDB.
|
||||
4. [Query data](#operation/GetExecuteQuerySQL) from InfluxDB.
|
||||
|
||||
```bash
|
||||
curl -G "http://localhost:8181/api/v3/query_sql" \
|
||||
--header "Authorization: Bearer ADMIN_TOKEN" \
|
||||
--data-urlencode "db=sensors" \
|
||||
--data-urlencode "q=SELECT * FROM home WHERE room='Living room'" \
|
||||
--data-urlencode "format=jsonl"
|
||||
|
@ -156,8 +197,12 @@ tags:
|
|||
x-traitTag: true
|
||||
- name: Server information
|
||||
description: Retrieve server metrics, status, and version information
|
||||
- name: Tables
|
||||
- name: Table
|
||||
description: Manage table schemas and data
|
||||
- name: Token
|
||||
description: Manage tokens for authentication and authorization
|
||||
- name: Write data
|
||||
description: Write data to InfluxDB 3
|
||||
paths:
|
||||
/write:
|
||||
post:
|
||||
|
@ -244,7 +289,7 @@ paths:
|
|||
description: Request entity too large.
|
||||
tags:
|
||||
- Compatibility endpoints
|
||||
- Data I/O
|
||||
- Write data
|
||||
/api/v2/write:
|
||||
post:
|
||||
operationId: PostV2Write
|
||||
|
@ -327,7 +372,7 @@ paths:
|
|||
description: Request entity too large.
|
||||
tags:
|
||||
- Compatibility endpoints
|
||||
- Data I/O
|
||||
- Write data
|
||||
/api/v3/write_lp:
|
||||
post:
|
||||
operationId: PostWriteLP
|
||||
|
@ -340,12 +385,7 @@ paths:
|
|||
parameters:
|
||||
- $ref: '#/components/parameters/dbWriteParam'
|
||||
- $ref: '#/components/parameters/accept_partial'
|
||||
- name: precision
|
||||
in: query
|
||||
required: true
|
||||
schema:
|
||||
$ref: '#/components/schemas/PrecisionWrite'
|
||||
description: Precision of timestamps.
|
||||
- $ref: '#/components/parameters/precisionParam'
|
||||
- name: no_sync
|
||||
in: query
|
||||
schema:
|
||||
|
@ -387,7 +427,7 @@ paths:
|
|||
'422':
|
||||
description: Unprocessable entity.
|
||||
tags:
|
||||
- Data I/O
|
||||
- Write data
|
||||
/api/v3/query_sql:
|
||||
get:
|
||||
operationId: GetExecuteQuerySQL
|
||||
|
@ -395,16 +435,8 @@ paths:
|
|||
description: Executes an SQL query to retrieve data from the specified database.
|
||||
parameters:
|
||||
- $ref: '#/components/parameters/db'
|
||||
- name: q
|
||||
in: query
|
||||
required: true
|
||||
schema:
|
||||
type: string
|
||||
- name: format
|
||||
in: query
|
||||
required: false
|
||||
schema:
|
||||
type: string
|
||||
- $ref: '#/components/parameters/querySqlParam'
|
||||
- $ref: '#/components/parameters/format'
|
||||
- $ref: '#/components/parameters/AcceptQueryHeader'
|
||||
- $ref: '#/components/parameters/ContentType'
|
||||
responses:
|
||||
|
@ -446,7 +478,7 @@ paths:
|
|||
'422':
|
||||
description: Unprocessable entity.
|
||||
tags:
|
||||
- Data I/O
|
||||
- Query data
|
||||
post:
|
||||
operationId: PostExecuteQuerySQL
|
||||
summary: Execute SQL query
|
||||
|
@ -485,7 +517,7 @@ paths:
|
|||
'422':
|
||||
description: Unprocessable entity.
|
||||
tags:
|
||||
- Data I/O
|
||||
- Query data
|
||||
/api/v3/query_influxql:
|
||||
get:
|
||||
operationId: GetExecuteInfluxQLQuery
|
||||
|
@ -533,7 +565,7 @@ paths:
|
|||
'422':
|
||||
description: Unprocessable entity.
|
||||
tags:
|
||||
- Data I/O
|
||||
- Query data
|
||||
post:
|
||||
operationId: PostExecuteQueryInfluxQL
|
||||
summary: Execute InfluxQL query
|
||||
|
@ -572,7 +604,7 @@ paths:
|
|||
'422':
|
||||
description: Unprocessable entity.
|
||||
tags:
|
||||
- Data I/O
|
||||
- Query data
|
||||
/query:
|
||||
get:
|
||||
operationId: GetV1ExecuteQuery
|
||||
|
@ -678,7 +710,7 @@ paths:
|
|||
'422':
|
||||
description: Unprocessable entity.
|
||||
tags:
|
||||
- Data I/O
|
||||
- Query data
|
||||
- Compatibility endpoints
|
||||
post:
|
||||
operationId: PostExecuteV1Query
|
||||
|
@ -789,7 +821,7 @@ paths:
|
|||
'422':
|
||||
description: Unprocessable entity.
|
||||
tags:
|
||||
- Data I/O
|
||||
- Query data
|
||||
- Compatibility endpoints
|
||||
/health:
|
||||
get:
|
||||
|
@ -863,7 +895,7 @@ paths:
|
|||
'404':
|
||||
description: Database not found.
|
||||
tags:
|
||||
- Databases
|
||||
- Database
|
||||
post:
|
||||
operationId: PostConfigureDatabase
|
||||
summary: Create a database
|
||||
|
@ -884,15 +916,31 @@ paths:
|
|||
'409':
|
||||
description: Database already exists.
|
||||
tags:
|
||||
- Databases
|
||||
- Database
|
||||
delete:
|
||||
operationId: DeleteConfigureDatabase
|
||||
summary: Delete a database
|
||||
description: |
|
||||
Soft deletes a database.
|
||||
The database is scheduled for deletion and unavailable for querying.
|
||||
The database is scheduled for deletion and unavailable for querying.
|
||||
Use the `hard_delete_at` parameter to schedule a hard deletion.
|
||||
parameters:
|
||||
- $ref: '#/components/parameters/db'
|
||||
- name: hard_delete_at
|
||||
in: query
|
||||
required: false
|
||||
schema:
|
||||
type: string
|
||||
format: date-time
|
||||
description: |
|
||||
Schedule the database for hard deletion at the specified time.
|
||||
If not provided, the database will be soft deleted.
|
||||
Use ISO 8601 date-time format (for example, "2025-12-31T23:59:59Z").
|
||||
|
||||
#### Deleting a database cannot be undone
|
||||
|
||||
Deleting a database is a destructive action.
|
||||
Once a database is deleted, data stored in that database cannot be recovered.
|
||||
responses:
|
||||
'200':
|
||||
description: Success. Database deleted.
|
||||
|
@ -901,7 +949,7 @@ paths:
|
|||
'404':
|
||||
description: Database not found.
|
||||
tags:
|
||||
- Databases
|
||||
- Database
|
||||
/api/v3/configure/table:
|
||||
post:
|
||||
operationId: PostConfigureTable
|
||||
|
@ -923,13 +971,19 @@ paths:
|
|||
'404':
|
||||
description: Database not found.
|
||||
tags:
|
||||
- Tables
|
||||
- Table
|
||||
delete:
|
||||
operationId: DeleteConfigureTable
|
||||
summary: Delete a table
|
||||
description: |
|
||||
Soft deletes a table.
|
||||
The table is scheduled for deletion and unavailable for querying.
|
||||
The table is scheduled for deletion and unavailable for querying.
|
||||
Use the `hard_delete_at` parameter to schedule a hard deletion.
|
||||
|
||||
#### Deleting a table cannot be undone
|
||||
|
||||
Deleting a table is a destructive action.
|
||||
Once a table is deleted, data stored in that table cannot be recovered.
|
||||
parameters:
|
||||
- $ref: '#/components/parameters/db'
|
||||
- name: table
|
||||
|
@ -937,6 +991,16 @@ paths:
|
|||
required: true
|
||||
schema:
|
||||
type: string
|
||||
- name: hard_delete_at
|
||||
in: query
|
||||
required: false
|
||||
schema:
|
||||
type: string
|
||||
format: date-time
|
||||
description: |
|
||||
Schedule the table for hard deletion at the specified time.
|
||||
If not provided, the table will be soft deleted.
|
||||
Use ISO 8601 format (for example, "2025-12-31T23:59:59Z").
|
||||
responses:
|
||||
'200':
|
||||
description: Success (no content). The table has been deleted.
|
||||
|
@ -945,14 +1009,15 @@ paths:
|
|||
'404':
|
||||
description: Table not found.
|
||||
tags:
|
||||
- Tables
|
||||
- Table
|
||||
/api/v3/configure/distinct_cache:
|
||||
post:
|
||||
operationId: PostConfigureDistinctCache
|
||||
summary: Create distinct cache
|
||||
description: Creates a distinct cache for a table.
|
||||
tags:
|
||||
- Tables
|
||||
- Cache data
|
||||
- Table
|
||||
requestBody:
|
||||
required: true
|
||||
content:
|
||||
|
@ -992,7 +1057,8 @@ paths:
|
|||
'409':
|
||||
description: Cache already exists.
|
||||
tags:
|
||||
- Tables
|
||||
- Cache data
|
||||
- Table
|
||||
delete:
|
||||
operationId: DeleteConfigureLastCache
|
||||
summary: Delete last cache
|
||||
|
@ -1019,20 +1085,110 @@ paths:
|
|||
'404':
|
||||
description: Cache not found.
|
||||
tags:
|
||||
- Tables
|
||||
- Cache data
|
||||
- Table
|
||||
/api/v3/configure/processing_engine_trigger:
|
||||
post:
|
||||
operationId: PostConfigureProcessingEngineTrigger
|
||||
summary: Create processing engine trigger
|
||||
description: Creates a new processing engine trigger.
|
||||
description: |
|
||||
Creates a processing engine trigger with the specified plugin file and trigger specification.
|
||||
|
||||
### Related guides
|
||||
|
||||
- [Processing engine and Python plugins](/influxdb3/core/plugins/)
|
||||
requestBody:
|
||||
required: true
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/ProcessingEngineTriggerRequest'
|
||||
examples:
|
||||
schedule_cron:
|
||||
summary: Schedule trigger using cron
|
||||
description: |
|
||||
In `"cron:CRON_EXPRESSION"`, `CRON_EXPRESSION` uses extended 6-field cron format.
|
||||
The cron expression `0 0 6 * * 1-5` means the trigger will run at 6:00 AM every weekday (Monday to Friday).
|
||||
value:
|
||||
db: mydb
|
||||
plugin_filename: schedule.py
|
||||
trigger_name: schedule_cron_trigger
|
||||
trigger_specification: cron:0 0 6 * * 1-5
|
||||
schedule_every:
|
||||
summary: Schedule trigger using interval
|
||||
description: |
|
||||
In `"every:DURATION"`, `DURATION` specifies the interval between trigger executions.
|
||||
The duration `1h` means the trigger will run every hour.
|
||||
value:
|
||||
db: mydb
|
||||
plugin_filename: schedule.py
|
||||
trigger_name: schedule_every_trigger
|
||||
trigger_specification: every:1h
|
||||
schedule_every_seconds:
|
||||
summary: Schedule trigger using seconds interval
|
||||
description: |
|
||||
Example of scheduling a trigger to run every 30 seconds.
|
||||
value:
|
||||
db: mydb
|
||||
plugin_filename: schedule.py
|
||||
trigger_name: schedule_every_30s_trigger
|
||||
trigger_specification: every:30s
|
||||
schedule_every_minutes:
|
||||
summary: Schedule trigger using minutes interval
|
||||
description: |
|
||||
Example of scheduling a trigger to run every 5 minutes.
|
||||
value:
|
||||
db: mydb
|
||||
plugin_filename: schedule.py
|
||||
trigger_name: schedule_every_5m_trigger
|
||||
trigger_specification: every:5m
|
||||
all_tables:
|
||||
summary: All tables trigger example
|
||||
description: |
|
||||
Trigger that fires on write events to any table in the database.
|
||||
value:
|
||||
db: mydb
|
||||
plugin_filename: all_tables.py
|
||||
trigger_name: all_tables_trigger
|
||||
trigger_specification: all_tables
|
||||
table_specific:
|
||||
summary: Table-specific trigger example
|
||||
description: |
|
||||
Trigger that fires on write events to a specific table.
|
||||
value:
|
||||
db: mydb
|
||||
plugin_filename: table.py
|
||||
trigger_name: table_trigger
|
||||
trigger_specification: table:sensors
|
||||
api_request:
|
||||
summary: On-demand request trigger example
|
||||
description: |
|
||||
Creates an HTTP endpoint `/api/v3/engine/hello-world` for manual invocation.
|
||||
value:
|
||||
db: mydb
|
||||
plugin_filename: request.py
|
||||
trigger_name: hello_world_trigger
|
||||
trigger_specification: request:hello-world
|
||||
cron_friday_afternoon:
|
||||
summary: Cron trigger for Friday afternoons
|
||||
description: |
|
||||
Example of a cron trigger that runs every Friday at 2:30 PM.
|
||||
value:
|
||||
db: reports
|
||||
plugin_filename: weekly_report.py
|
||||
trigger_name: friday_report_trigger
|
||||
trigger_specification: cron:0 30 14 * * 5
|
||||
cron_monthly:
|
||||
summary: Cron trigger for monthly execution
|
||||
description: |
|
||||
Example of a cron trigger that runs on the first day of every month at midnight.
|
||||
value:
|
||||
db: monthly_data
|
||||
plugin_filename: monthly_cleanup.py
|
||||
trigger_name: monthly_cleanup_trigger
|
||||
trigger_specification: cron:0 0 0 1 * *
|
||||
responses:
|
||||
'201':
|
||||
'200':
|
||||
description: Success. Processing engine trigger created.
|
||||
'400':
|
||||
description: Bad request.
|
||||
|
@ -1109,7 +1265,7 @@ paths:
|
|||
$ref: '#/components/schemas/ProcessingEngineTriggerRequest'
|
||||
responses:
|
||||
'200':
|
||||
description: Success. The processing engine trigger has been enabled.
|
||||
description: Success. The processing engine trigger is enabled.
|
||||
'400':
|
||||
description: Bad request.
|
||||
'401':
|
||||
|
@ -1122,7 +1278,14 @@ paths:
|
|||
post:
|
||||
operationId: PostInstallPluginPackages
|
||||
summary: Install plugin packages
|
||||
description: Installs packages for the plugin environment.
|
||||
description: |
|
||||
Installs the specified Python packages into the processing engine plugin environment.
|
||||
|
||||
This endpoint is synchronous and blocks until the packages are installed.
|
||||
|
||||
### Related guides
|
||||
|
||||
- [Processing engine and Python plugins](/influxdb3/core/plugins/)
|
||||
parameters:
|
||||
- $ref: '#/components/parameters/ContentType'
|
||||
requestBody:
|
||||
|
@ -1131,10 +1294,30 @@ paths:
|
|||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
additionalProperties: true
|
||||
properties:
|
||||
packages:
|
||||
type: array
|
||||
items:
|
||||
type: string
|
||||
description: |
|
||||
A list of Python package names to install.
|
||||
Can include version specifiers (e.g., "scipy==1.9.0").
|
||||
example:
|
||||
- influxdb3-python
|
||||
- scipy
|
||||
- pandas==1.5.0
|
||||
- requests
|
||||
required:
|
||||
- packages
|
||||
example:
|
||||
packages:
|
||||
- influxdb3-python
|
||||
- scipy
|
||||
- pandas==1.5.0
|
||||
- requests
|
||||
responses:
|
||||
'200':
|
||||
description: Success. The packages have been installed.
|
||||
description: Success. The packages are installed.
|
||||
'400':
|
||||
description: Bad request.
|
||||
'401':
|
||||
|
@ -1145,7 +1328,15 @@ paths:
|
|||
post:
|
||||
operationId: PostInstallPluginRequirements
|
||||
summary: Install plugin requirements
|
||||
description: Installs requirements for the plugin environment.
|
||||
description: |
|
||||
Installs requirements from a requirements file (also known as a "pip requirements file") into the processing engine plugin environment.
|
||||
|
||||
This endpoint is synchronous and blocks until the requirements are installed.
|
||||
|
||||
### Related
|
||||
|
||||
- [Processing engine and Python plugins](/influxdb3/core/plugins/)
|
||||
- [Python requirements file format](https://pip.pypa.io/en/stable/reference/requirements-file-format/)
|
||||
parameters:
|
||||
- $ref: '#/components/parameters/ContentType'
|
||||
requestBody:
|
||||
|
@ -1154,7 +1345,17 @@ paths:
|
|||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
additionalProperties: true
|
||||
properties:
|
||||
requirements_location:
|
||||
type: string
|
||||
description: |
|
||||
The path to the requirements file containing Python packages to install.
|
||||
Can be a relative path (relative to the plugin directory) or an absolute path.
|
||||
example: requirements.txt
|
||||
required:
|
||||
- requirements_location
|
||||
example:
|
||||
requirements_location: requirements.txt
|
||||
responses:
|
||||
'200':
|
||||
description: Success. The requirements have been installed.
|
||||
|
@ -1196,22 +1397,22 @@ paths:
|
|||
description: Plugin not enabled.
|
||||
tags:
|
||||
- Processing engine
|
||||
/api/v3/engine/{plugin_path}:
|
||||
/api/v3/engine/{request_path}:
|
||||
parameters:
|
||||
- name: plugin_path
|
||||
- name: request_path
|
||||
description: |
|
||||
The path configured in the `trigger-spec` for the plugin.
|
||||
The path configured in the request trigger specification for the plugin.
|
||||
|
||||
For example, if you define a trigger with the following:
|
||||
|
||||
```
|
||||
trigger-spec: "request:hello-world"
|
||||
```json
|
||||
trigger_specification: "request:hello-world"
|
||||
```
|
||||
|
||||
then, the HTTP API exposes the following plugin endpoint:
|
||||
|
||||
```
|
||||
<INFLUXDB_HOST>/api/v3/engine/hello-world
|
||||
<INFLUXDB3_HOST>/api/v3/engine/hello-world
|
||||
```
|
||||
in: path
|
||||
required: true
|
||||
|
@ -1221,7 +1422,7 @@ paths:
|
|||
operationId: GetProcessingEnginePluginRequest
|
||||
summary: On Request processing engine plugin request
|
||||
description: |
|
||||
Sends a request to invoke an _On Request_ processing engine plugin.
|
||||
Executes the On Request processing engine plugin specified in the trigger's `plugin_filename`.
|
||||
The request can include request headers, query string parameters, and a request body, which InfluxDB passes to the plugin.
|
||||
|
||||
An On Request plugin implements the following signature:
|
||||
|
@ -1248,7 +1449,7 @@ paths:
|
|||
operationId: PostProcessingEnginePluginRequest
|
||||
summary: On Request processing engine plugin request
|
||||
description: |
|
||||
Sends a request to invoke an _On Request_ processing engine plugin.
|
||||
Executes the On Request processing engine plugin specified in the trigger's `plugin_filename`.
|
||||
The request can include request headers, query string parameters, and a request body, which InfluxDB passes to the plugin.
|
||||
|
||||
An On Request plugin implements the following signature:
|
||||
|
@ -1280,6 +1481,46 @@ paths:
|
|||
description: Processing failure.
|
||||
tags:
|
||||
- Processing engine
|
||||
/api/v3/configure/token/admin:
|
||||
post:
|
||||
operationId: PostCreateAdminToken
|
||||
summary: Create admin token
|
||||
description: |
|
||||
Creates an admin token.
|
||||
An admin token is a special type of token that has full access to all resources in the system.
|
||||
responses:
|
||||
'201':
|
||||
description: |
|
||||
Success. The admin token has been created.
|
||||
The response body contains the token string and metadata.
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/AdminTokenObject'
|
||||
'401':
|
||||
$ref: '#/components/responses/Unauthorized'
|
||||
tags:
|
||||
- Authentication
|
||||
- Token
|
||||
/api/v3/configure/token/admin/regenerate:
|
||||
post:
|
||||
operationId: PostRegenerateAdminToken
|
||||
summary: Regenerate admin token
|
||||
description: |
|
||||
Regenerates an admin token and revokes the previous token with the same name.
|
||||
parameters: []
|
||||
responses:
|
||||
'201':
|
||||
description: Success. The admin token has been regenerated.
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/AdminTokenObject'
|
||||
'401':
|
||||
$ref: '#/components/responses/Unauthorized'
|
||||
tags:
|
||||
- Authentication
|
||||
- Token
|
||||
components:
|
||||
parameters:
|
||||
AcceptQueryHeader:
|
||||
|
@ -1337,7 +1578,6 @@ components:
|
|||
schema:
|
||||
type: string
|
||||
description: |
|
||||
The name of the database.
|
||||
The name of the database.
|
||||
InfluxDB creates the database if it doesn't already exist, and then
|
||||
writes all points in the batch to the database.
|
||||
|
@ -1416,6 +1656,29 @@ components:
|
|||
schema:
|
||||
$ref: '#/components/schemas/QueryRequestObject'
|
||||
schemas:
|
||||
AdminTokenObject:
|
||||
type: object
|
||||
properties:
|
||||
id:
|
||||
type: integer
|
||||
name:
|
||||
type: string
|
||||
token:
|
||||
type: string
|
||||
hash:
|
||||
type: string
|
||||
created_at:
|
||||
type: string
|
||||
format: date-time
|
||||
expiry:
|
||||
format: date-time
|
||||
example:
|
||||
id: 0
|
||||
name: _admin
|
||||
token: apiv3_00xx0Xx0xx00XX0x0
|
||||
hash: 00xx0Xx0xx00XX0x0
|
||||
created_at: '2025-04-18T14:02:45.331Z'
|
||||
expiry: null
|
||||
ContentEncoding:
|
||||
type: string
|
||||
enum:
|
||||
|
@ -1457,13 +1720,10 @@ components:
|
|||
description: |
|
||||
Acknowledges a successful write without waiting for WAL persistence.
|
||||
|
||||
#### Data flow in InfluxDB 3 Core
|
||||
#### Related
|
||||
|
||||
1. **Incoming writes**: The system validates incoming data and stores it in the write buffer (in memory). If the `no_sync` write option is enabled (`no_sync=true`), the server sends a response to acknowledge the write.
|
||||
2. **WAL flush**: Every second (default), the system flushes the write buffer to the Write-Ahead Log (WAL) for persistence in the Object store. If `no_sync=false` (default), the server sends a response to acknowledge the write.
|
||||
3. **Query availability**: After WAL persistence completes, data moves to the queryable buffer where it becomes available for queries. By default, the server keeps up to 900 WAL files (15 minutes of data) buffered.
|
||||
4. **Long-term storage in Parquet**: Every ten minutes (default), the system persists the oldest data from the queryable buffer to the Object store in Parquet format. InfluxDB keeps the remaining data (the most recent 5 minutes) in memory.
|
||||
5. **In-memory cache**: InfluxDB puts Parquet files into an in-memory cache so that queries against the most recently persisted data don't have to go to object storage.
|
||||
- [Use the HTTP API and client libraries to write data](/influxdb3/core/write-data/api-client-libraries/)
|
||||
- [Data durability](/influxdb3/core/reference/internals/durability/)
|
||||
PrecisionWriteCompatibility:
|
||||
enum:
|
||||
- ms
|
||||
|
@ -1635,15 +1895,69 @@ components:
|
|||
type: string
|
||||
plugin_filename:
|
||||
type: string
|
||||
description: |
|
||||
The path and filename of the plugin to execute--for example,
|
||||
`schedule.py` or `endpoints/report.py`.
|
||||
The path can be absolute or relative to the `--plugins-dir` directory configured when starting InfluxDB 3.
|
||||
|
||||
The plugin file must implement the trigger interface associated with the trigger's specification.
|
||||
trigger_name:
|
||||
type: string
|
||||
trigger_specification:
|
||||
type: string
|
||||
description: |
|
||||
Specifies when and how the processing engine trigger should be invoked.
|
||||
|
||||
## Supported trigger specifications:
|
||||
|
||||
### Cron-based scheduling
|
||||
Format: `cron:CRON_EXPRESSION`
|
||||
|
||||
Uses extended (6-field) cron format (second minute hour day_of_month month day_of_week):
|
||||
```
|
||||
┌───────────── second (0-59)
|
||||
│ ┌───────────── minute (0-59)
|
||||
│ │ ┌───────────── hour (0-23)
|
||||
│ │ │ ┌───────────── day of month (1-31)
|
||||
│ │ │ │ ┌───────────── month (1-12)
|
||||
│ │ │ │ │ ┌───────────── day of week (0-6, Sunday=0)
|
||||
│ │ │ │ │ │
|
||||
* * * * * *
|
||||
```
|
||||
Examples:
|
||||
- `cron:0 0 6 * * 1-5` - Every weekday at 6:00 AM
|
||||
- `cron:0 30 14 * * 5` - Every Friday at 2:30 PM
|
||||
- `cron:0 0 0 1 * *` - First day of every month at midnight
|
||||
|
||||
### Interval-based scheduling
|
||||
Format: `every:DURATION`
|
||||
|
||||
Supported durations: `s` (seconds), `m` (minutes), `h` (hours), `d` (days):
|
||||
- `every:30s` - Every 30 seconds
|
||||
- `every:5m` - Every 5 minutes
|
||||
- `every:1h` - Every hour
|
||||
- `every:1d` - Every day
|
||||
|
||||
### Table-based triggers
|
||||
- `all_tables` - Triggers on write events to any table in the database
|
||||
- `table:TABLE_NAME` - Triggers on write events to a specific table
|
||||
|
||||
### On-demand triggers
|
||||
Format: `request:REQUEST_PATH`
|
||||
|
||||
Creates an HTTP endpoint `/api/v3/engine/REQUEST_PATH` for manual invocation:
|
||||
- `request:hello-world` - Creates endpoint `/api/v3/engine/hello-world`
|
||||
- `request:data-export` - Creates endpoint `/api/v3/engine/data-export`
|
||||
pattern: ^(cron:[0-9 *,/-]+|every:[0-9]+[smhd]|all_tables|table:[a-zA-Z_][a-zA-Z0-9_]*|request:[a-zA-Z0-9_-]+)$
|
||||
example: cron:0 0 6 * * 1-5
|
||||
trigger_arguments:
|
||||
type: object
|
||||
additionalProperties: true
|
||||
description: Optional arguments passed to the plugin.
|
||||
disabled:
|
||||
type: boolean
|
||||
default: false
|
||||
description: Whether the trigger is disabled.
|
||||
required:
|
||||
- db
|
||||
- plugin_filename
|
||||
|
@ -1731,6 +2045,65 @@ components:
|
|||
- m
|
||||
- h
|
||||
type: string
|
||||
UpdateDatabaseRequest:
|
||||
type: object
|
||||
properties:
|
||||
retention_period:
|
||||
type: string
|
||||
description: |
|
||||
The retention period for the database. Specifies how long data should be retained.
|
||||
Use duration format (for example, "1d", "1h", "30m", "7d").
|
||||
example: "7d"
|
||||
description: Request schema for updating database configuration.
|
||||
UpdateTableRequest:
|
||||
type: object
|
||||
properties:
|
||||
db:
|
||||
type: string
|
||||
description: The name of the database containing the table.
|
||||
table:
|
||||
type: string
|
||||
description: The name of the table to update.
|
||||
retention_period:
|
||||
type: string
|
||||
description: |
|
||||
The retention period for the table. Specifies how long data in this table should be retained.
|
||||
Use duration format (for example, "1d", "1h", "30m", "7d").
|
||||
example: "30d"
|
||||
required:
|
||||
- db
|
||||
- table
|
||||
description: Request schema for updating table configuration.
|
||||
LicenseResponse:
|
||||
type: object
|
||||
properties:
|
||||
license_type:
|
||||
type: string
|
||||
description: The type of license (for example, "enterprise", "trial").
|
||||
example: "enterprise"
|
||||
expires_at:
|
||||
type: string
|
||||
format: date-time
|
||||
description: The expiration date of the license in ISO 8601 format.
|
||||
example: "2025-12-31T23:59:59Z"
|
||||
features:
|
||||
type: array
|
||||
items:
|
||||
type: string
|
||||
description: List of features enabled by the license.
|
||||
example:
|
||||
- "clustering"
|
||||
- "processing_engine"
|
||||
- "advanced_auth"
|
||||
status:
|
||||
type: string
|
||||
enum:
|
||||
- "active"
|
||||
- "expired"
|
||||
- "invalid"
|
||||
description: The current status of the license.
|
||||
example: "active"
|
||||
description: Response schema for license information.
|
||||
responses:
|
||||
Unauthorized:
|
||||
description: Unauthorized access.
|
||||
|
@ -1767,8 +2140,6 @@ components:
|
|||
scheme: bearer
|
||||
bearerFormat: JWT
|
||||
description: |
|
||||
_During Alpha release, an API token is not required._
|
||||
|
||||
A Bearer token for authentication.
|
||||
|
||||
Provide the scheme and the API token in the `Authorization` header--for example:
|
||||
|
@ -1782,11 +2153,14 @@ x-tagGroups:
|
|||
tags:
|
||||
- Quick start
|
||||
- Authentication
|
||||
- Cache data
|
||||
- Common parameters
|
||||
- Response codes
|
||||
- Compatibility endpoints
|
||||
- Data I/O
|
||||
- Databases
|
||||
- Database
|
||||
- Processing engine
|
||||
- Server information
|
||||
- Tables
|
||||
- Table
|
||||
- Token
|
||||
- Query data
|
||||
- Write data
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
plugins:
|
||||
- '../../openapi/plugins/docs-plugin.js'
|
||||
- '../../openapi/plugins/docs-plugin.cjs'
|
||||
extends:
|
||||
- recommended
|
||||
- docs/all
|
||||
|
@ -10,3 +10,7 @@ apis:
|
|||
root: v3/ref.yml
|
||||
x-influxdata-docs-aliases:
|
||||
- /influxdb3/enterprise/api/
|
||||
- /influxdb3/enterprise/api/v1/
|
||||
- /influxdb3/enterprise/v2/
|
||||
- /influxdb3/enterprise/v1-compatibility
|
||||
- /influxdb3/enterprise/v2-compatibility
|
|
@ -2,11 +2,14 @@
|
|||
tags:
|
||||
- Quick start
|
||||
- Authentication
|
||||
- Cache data
|
||||
- Common parameters
|
||||
- Response codes
|
||||
- Compatibility endpoints
|
||||
- Data I/O
|
||||
- Databases
|
||||
- Database
|
||||
- Processing engine
|
||||
- Server information
|
||||
- Tables
|
||||
- Table
|
||||
- Token
|
||||
- Query data
|
||||
- Write data
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,6 +1,6 @@
|
|||
module.exports = SetTagGroups;
|
||||
|
||||
const { collect, getName, sortName, isPresent } = require('../../helpers/content-helper.js')
|
||||
const { collect, getName, sortName, isPresent } = require('../../helpers/content-helper.cjs')
|
||||
/**
|
||||
* Returns an object that defines handler functions for:
|
||||
* - Operation nodes
|
|
@ -1,25 +0,0 @@
|
|||
module.exports = SetTags;
|
||||
|
||||
const { tags } = require('../../../content/content')
|
||||
/**
|
||||
* Returns an object that defines handler functions for:
|
||||
* - DefinitionRoot (the root openapi) node
|
||||
* The DefinitionRoot handler, executed when
|
||||
* the parser is leaving the root node,
|
||||
* sets the root `tags` list to the provided `data`.
|
||||
*/
|
||||
/** @type {import('@redocly/openapi-cli').OasDecorator} */
|
||||
function SetTags() {
|
||||
const data = tags();
|
||||
|
||||
return {
|
||||
DefinitionRoot: {
|
||||
/** Set tags from custom tags when visitor enters root. */
|
||||
enter(root) {
|
||||
if(data) {
|
||||
root.tags = data;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
|
@ -1,5 +1,5 @@
|
|||
const path = require('path');
|
||||
const { toJSON } = require('./helpers/content-helper');
|
||||
const { toJSON } = require('./helpers/content-helper.cjs');
|
||||
|
||||
function getVersioned(filename) {
|
||||
const apiDocsRoot=path.resolve(process.env.API_DOCS_ROOT_PATH || process.cwd());
|
|
@ -1,14 +1,14 @@
|
|||
const {info, servers, tagGroups} = require('./docs-content');
|
||||
const ReportTags = require('./rules/report-tags');
|
||||
const ValidateServersUrl = require('./rules/validate-servers-url');
|
||||
const RemovePrivatePaths = require('./decorators/paths/remove-private-paths');
|
||||
const ReplaceShortcodes = require('./decorators/replace-shortcodes');
|
||||
const SetInfo = require('./decorators/set-info');
|
||||
const DeleteServers = require('./decorators/servers/delete-servers');
|
||||
const SetServers = require('./decorators/servers/set-servers');
|
||||
const SetTagGroups = require('./decorators/tags/set-tag-groups');
|
||||
const StripVersionPrefix = require('./decorators/paths/strip-version-prefix');
|
||||
const StripTrailingSlash = require('./decorators/paths/strip-trailing-slash');
|
||||
const {info, servers, tagGroups} = require('./docs-content.cjs');
|
||||
const ReportTags = require('./rules/report-tags.cjs');
|
||||
const ValidateServersUrl = require('./rules/validate-servers-url.cjs');
|
||||
const RemovePrivatePaths = require('./decorators/paths/remove-private-paths.cjs');
|
||||
const ReplaceShortcodes = require('./decorators/replace-shortcodes.cjs');
|
||||
const SetInfo = require('./decorators/set-info.cjs');
|
||||
const DeleteServers = require('./decorators/servers/delete-servers.cjs');
|
||||
const SetServers = require('./decorators/servers/set-servers.cjs');
|
||||
const SetTagGroups = require('./decorators/tags/set-tag-groups.cjs');
|
||||
const StripVersionPrefix = require('./decorators/paths/strip-version-prefix.cjs');
|
||||
const StripTrailingSlash = require('./decorators/paths/strip-trailing-slash.cjs');
|
||||
|
||||
const id = 'docs';
|
||||
|
|
@ -2,7 +2,7 @@
|
|||
///////////////// Preferred Client Library programming language ///////////////
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
import { activateTabs, updateBtnURLs } from './tabbed-content.js';
|
||||
import { getPreference, setPreference } from './local-storage.js';
|
||||
import { getPreference, setPreference } from './services/local-storage.js';
|
||||
|
||||
function getVisitedApiLib() {
|
||||
const path = window.location.pathname.match(
|
||||
|
|
|
@ -8,29 +8,31 @@ function setUser(userid, email) {
|
|||
window[NAMESPACE] = {
|
||||
user: {
|
||||
uniqueClientId: userid,
|
||||
email: email,
|
||||
}
|
||||
}
|
||||
email: email,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
// Initialize the chat widget
|
||||
function initializeChat({onChatLoad, chatAttributes}) {
|
||||
/* See https://docs.kapa.ai/integrations/website-widget/configuration for
|
||||
function initializeChat({ onChatLoad, chatAttributes }) {
|
||||
/* See https://docs.kapa.ai/integrations/website-widget/configuration for
|
||||
* available configuration options.
|
||||
* All values are strings.
|
||||
*/
|
||||
// If you make changes to data attributes here, you also need to port the changes to the api-docs/template.hbs API reference template.
|
||||
// If you make changes to data attributes here, you also need to
|
||||
// port the changes to the api-docs/template.hbs API reference template.
|
||||
const requiredAttributes = {
|
||||
websiteId: 'a02bca75-1dd3-411e-95c0-79ee1139be4d',
|
||||
projectName: 'InfluxDB',
|
||||
projectColor: '#020a47',
|
||||
projectLogo: '/img/influx-logo-cubo-white.png',
|
||||
}
|
||||
};
|
||||
|
||||
const optionalAttributes = {
|
||||
|
||||
modalDisclaimer: 'This AI can access [documentation for InfluxDB, clients, and related tools](https://docs.influxdata.com). Information you submit is used in accordance with our [Privacy Policy](https://www.influxdata.com/legal/privacy-policy/).',
|
||||
modalExampleQuestions: 'Use Python to write data to InfluxDB 3,How do I query using SQL?,How do I use MQTT with Telegraf?',
|
||||
modalDisclaimer:
|
||||
'This AI can access [documentation for InfluxDB, clients, and related tools](https://docs.influxdata.com). Information you submit is used in accordance with our [Privacy Policy](https://www.influxdata.com/legal/privacy-policy/).',
|
||||
modalExampleQuestions:
|
||||
'Use Python to write data to InfluxDB 3,How do I query using SQL?,How do I use MQTT with Telegraf?',
|
||||
buttonHide: 'true',
|
||||
exampleQuestionButtonWidth: 'auto',
|
||||
modalOpenOnCommandK: 'true',
|
||||
|
@ -52,28 +54,32 @@ function initializeChat({onChatLoad, chatAttributes}) {
|
|||
modalHeaderBorderBottom: 'none',
|
||||
modalTitleColor: '#fff',
|
||||
modalTitleFontSize: '1.25rem',
|
||||
}
|
||||
};
|
||||
|
||||
const scriptUrl = 'https://widget.kapa.ai/kapa-widget.bundle.js';
|
||||
const script = document.createElement('script');
|
||||
script.async = true;
|
||||
script.src = scriptUrl;
|
||||
script.onload = function() {
|
||||
script.onload = function () {
|
||||
onChatLoad();
|
||||
window.influxdatadocs.AskAI = AskAI;
|
||||
};
|
||||
script.onerror = function() {
|
||||
script.onerror = function () {
|
||||
console.error('Error loading AI chat widget script');
|
||||
};
|
||||
|
||||
const dataset = {...requiredAttributes, ...optionalAttributes, ...chatAttributes};
|
||||
Object.keys(dataset).forEach(key => {
|
||||
// Assign dataset attributes from the object
|
||||
const dataset = {
|
||||
...requiredAttributes,
|
||||
...optionalAttributes,
|
||||
...chatAttributes,
|
||||
};
|
||||
Object.keys(dataset).forEach((key) => {
|
||||
// Assign dataset attributes from the object
|
||||
script.dataset[key] = dataset[key];
|
||||
});
|
||||
|
||||
// Check for an existing script element to remove
|
||||
const oldScript= document.querySelector(`script[src="${scriptUrl}"]`);
|
||||
const oldScript = document.querySelector(`script[src="${scriptUrl}"]`);
|
||||
if (oldScript) {
|
||||
oldScript.remove();
|
||||
}
|
||||
|
@ -82,22 +88,21 @@ function initializeChat({onChatLoad, chatAttributes}) {
|
|||
|
||||
function getProductExampleQuestions() {
|
||||
const questions = productData?.product?.ai_sample_questions;
|
||||
return questions?.join(',') || '';
|
||||
return questions?.join(',') || '';
|
||||
}
|
||||
|
||||
/**
|
||||
/**
|
||||
* chatParams: specify custom (for example, page-specific) attribute values for the chat, pass the dataset key-values (collected in ...chatParams). See https://docs.kapa.ai/integrations/website-widget/configuration for available configuration options.
|
||||
* onChatLoad: function to call when the chat widget has loaded
|
||||
* userid: optional, a unique user ID for the user (not currently used for public docs)
|
||||
*/
|
||||
*/
|
||||
export default function AskAI({ userid, email, onChatLoad, ...chatParams }) {
|
||||
|
||||
const modalExampleQuestions = getProductExampleQuestions();
|
||||
const chatAttributes = {
|
||||
...(modalExampleQuestions && { modalExampleQuestions }),
|
||||
...chatParams,
|
||||
}
|
||||
initializeChat({onChatLoad, chatAttributes});
|
||||
};
|
||||
initializeChat({ onChatLoad, chatAttributes });
|
||||
|
||||
if (userid) {
|
||||
setUser(userid, email);
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
import $ from 'jquery';
|
||||
import { context } from './page-context.js';
|
||||
|
||||
function initialize() {
|
||||
var codeBlockSelector = '.article--content pre';
|
||||
var codeBlocks = $(codeBlockSelector);
|
||||
var $codeBlocks = $(codeBlockSelector);
|
||||
|
||||
var appendHTML = `
|
||||
<div class="code-controls">
|
||||
|
@ -15,7 +16,7 @@ function initialize() {
|
|||
`;
|
||||
|
||||
// Wrap all codeblocks with a new 'codeblock' div
|
||||
$(codeBlocks).each(function () {
|
||||
$codeBlocks.each(function () {
|
||||
$(this).wrap("<div class='codeblock'></div>");
|
||||
});
|
||||
|
||||
|
@ -68,7 +69,94 @@ function initialize() {
|
|||
// Trigger copy failure state lifecycle
|
||||
|
||||
$('.copy-code').click(function () {
|
||||
let text = $(this).closest('.code-controls').prevAll('pre:has(code)')[0].innerText;
|
||||
let codeElement = $(this)
|
||||
.closest('.code-controls')
|
||||
.prevAll('pre:has(code)')[0];
|
||||
|
||||
let text = codeElement.innerText;
|
||||
|
||||
// Extract additional code block information
|
||||
const codeBlockInfo = extractCodeBlockInfo(codeElement);
|
||||
|
||||
// Add Google Analytics event tracking
|
||||
const currentUrl = new URL(window.location.href);
|
||||
|
||||
// Determine which tracking parameter to add based on product context
|
||||
switch (context) {
|
||||
case 'cloud':
|
||||
currentUrl.searchParams.set('dl', 'cloud');
|
||||
break;
|
||||
case 'core':
|
||||
/** Track using the same value used by www.influxdata.com pages */
|
||||
currentUrl.searchParams.set('dl', 'oss3');
|
||||
break;
|
||||
case 'enterprise':
|
||||
/** Track using the same value used by www.influxdata.com pages */
|
||||
currentUrl.searchParams.set('dl', 'enterprise');
|
||||
break;
|
||||
case 'serverless':
|
||||
currentUrl.searchParams.set('dl', 'serverless');
|
||||
break;
|
||||
case 'dedicated':
|
||||
currentUrl.searchParams.set('dl', 'dedicated');
|
||||
break;
|
||||
case 'clustered':
|
||||
currentUrl.searchParams.set('dl', 'clustered');
|
||||
break;
|
||||
case 'oss/enterprise':
|
||||
currentUrl.searchParams.set('dl', 'oss');
|
||||
break;
|
||||
case 'other':
|
||||
default:
|
||||
// No tracking parameter for other/unknown products
|
||||
break;
|
||||
}
|
||||
|
||||
// Add code block specific tracking parameters
|
||||
if (codeBlockInfo.language) {
|
||||
currentUrl.searchParams.set('code_lang', codeBlockInfo.language);
|
||||
}
|
||||
if (codeBlockInfo.lineCount) {
|
||||
currentUrl.searchParams.set('code_lines', codeBlockInfo.lineCount);
|
||||
}
|
||||
if (codeBlockInfo.hasPlaceholders) {
|
||||
currentUrl.searchParams.set('has_placeholders', 'true');
|
||||
}
|
||||
if (codeBlockInfo.blockType) {
|
||||
currentUrl.searchParams.set('code_type', codeBlockInfo.blockType);
|
||||
}
|
||||
if (codeBlockInfo.sectionTitle) {
|
||||
currentUrl.searchParams.set(
|
||||
'section',
|
||||
encodeURIComponent(codeBlockInfo.sectionTitle)
|
||||
);
|
||||
}
|
||||
if (codeBlockInfo.firstLine) {
|
||||
currentUrl.searchParams.set(
|
||||
'first_line',
|
||||
encodeURIComponent(codeBlockInfo.firstLine.substring(0, 100))
|
||||
);
|
||||
}
|
||||
|
||||
// Update browser history without triggering page reload
|
||||
if (window.history && window.history.replaceState) {
|
||||
window.history.replaceState(null, '', currentUrl.toString());
|
||||
}
|
||||
|
||||
// Send custom Google Analytics event if gtag is available
|
||||
if (typeof window.gtag !== 'undefined') {
|
||||
window.gtag('event', 'code_copy', {
|
||||
language: codeBlockInfo.language,
|
||||
line_count: codeBlockInfo.lineCount,
|
||||
has_placeholders: codeBlockInfo.hasPlaceholders,
|
||||
dl: codeBlockInfo.dl || null,
|
||||
section_title: codeBlockInfo.sectionTitle,
|
||||
first_line: codeBlockInfo.firstLine
|
||||
? codeBlockInfo.firstLine.substring(0, 100)
|
||||
: null,
|
||||
product: context,
|
||||
});
|
||||
}
|
||||
|
||||
const copyContent = async () => {
|
||||
try {
|
||||
|
@ -82,6 +170,71 @@ function initialize() {
|
|||
copyContent();
|
||||
});
|
||||
|
||||
/**
|
||||
* Extract contextual information about a code block
|
||||
* @param {HTMLElement} codeElement - The code block element
|
||||
* @returns {Object} Information about the code block
|
||||
*/
|
||||
function extractCodeBlockInfo(codeElement) {
|
||||
const codeTag = codeElement.querySelector('code');
|
||||
const info = {
|
||||
language: null,
|
||||
lineCount: 0,
|
||||
hasPlaceholders: false,
|
||||
blockType: 'code',
|
||||
dl: null, // Download script type
|
||||
sectionTitle: null,
|
||||
firstLine: null,
|
||||
};
|
||||
|
||||
// Extract language from class attribute
|
||||
if (codeTag && codeTag.className) {
|
||||
const langMatch = codeTag.className.match(
|
||||
/language-(\w+)|hljs-(\w+)|(\w+)/
|
||||
);
|
||||
if (langMatch) {
|
||||
info.language = langMatch[1] || langMatch[2] || langMatch[3];
|
||||
}
|
||||
}
|
||||
|
||||
// Count lines
|
||||
const text = codeElement.innerText || '';
|
||||
const lines = text.split('\n');
|
||||
info.lineCount = lines.length;
|
||||
|
||||
// Get first non-empty line
|
||||
info.firstLine = lines.find((line) => line.trim() !== '') || null;
|
||||
|
||||
// Check for placeholders (common patterns)
|
||||
info.hasPlaceholders =
|
||||
/\b[A-Z_]{2,}\b|\{\{[^}]+\}\}|\$\{[^}]+\}|<[^>]+>/.test(text);
|
||||
|
||||
// Determine if this is a download script
|
||||
if (text.includes('https://www.influxdata.com/d/install_influxdb3.sh')) {
|
||||
if (text.includes('install_influxdb3.sh enterprise')) {
|
||||
info.dl = 'enterprise';
|
||||
} else {
|
||||
info.dl = 'oss3';
|
||||
}
|
||||
} else if (text.includes('docker pull influxdb:3-enterprise')) {
|
||||
info.dl = 'enterprise';
|
||||
} else if (text.includes('docker pull influxdb3-core')) {
|
||||
info.dl = 'oss3';
|
||||
}
|
||||
|
||||
// Find nearest section heading
|
||||
let element = codeElement;
|
||||
while (element && element !== document.body) {
|
||||
element = element.previousElementSibling || element.parentElement;
|
||||
if (element && element.tagName && /^H[1-6]$/.test(element.tagName)) {
|
||||
info.sectionTitle = element.textContent.trim();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return info;
|
||||
}
|
||||
|
||||
/////////////////////////////// FULL WINDOW CODE ///////////////////////////////
|
||||
|
||||
/*
|
||||
|
@ -90,7 +243,10 @@ Disable scrolling on the body.
|
|||
Disable user selection on everything but the fullscreen codeblock.
|
||||
*/
|
||||
$('.fullscreen-toggle').click(function () {
|
||||
var code = $(this).closest('.code-controls').prevAll('pre:has(code)').clone();
|
||||
var code = $(this)
|
||||
.closest('.code-controls')
|
||||
.prevAll('pre:has(code)')
|
||||
.clone();
|
||||
|
||||
$('#fullscreen-code-placeholder').replaceWith(code[0]);
|
||||
$('body').css('overflow', 'hidden');
|
||||
|
|
|
@ -1,30 +1,52 @@
|
|||
const placeholderWrapper = '.code-placeholder-wrapper';
|
||||
import $ from 'jquery';
|
||||
|
||||
const placeholderElement = 'var.code-placeholder';
|
||||
const editIcon = "<span class='code-placeholder-edit-icon cf-icon Pencil'></span>";
|
||||
|
||||
// When clicking a placeholder, append the edit input
|
||||
function handleClick(element) {
|
||||
$(element).on('click', function() {
|
||||
function handleClick($element) {
|
||||
const $placeholder = $($element).find(placeholderElement);
|
||||
$placeholder.on('click', function() {
|
||||
var placeholderData = $(this)[0].dataset;
|
||||
var placeholderID = placeholderData.codeVar;
|
||||
var placeholderID = placeholderData.codeVarEscaped;
|
||||
var placeholderValue = placeholderData.codeVarValue;
|
||||
var placeholderInputWrapper = $('<div class="code-input-wrapper"></div>');
|
||||
var placeholderInput = `<input class="placeholder-edit" id="${placeholderID}" value="${placeholderValue}" spellcheck=false onblur="submitPlaceholder($(this))" oninput="updateInputWidth($(this))" onkeydown="closeOnEnter($(this)[0], event)"></input>`;
|
||||
|
||||
$(this).before(placeholderInputWrapper)
|
||||
$(this).siblings('.code-input-wrapper').append(placeholderInput);
|
||||
$(`input#${placeholderID}`).width(`${placeholderValue.length}ch`);
|
||||
$(`input#${placeholderID}`).focus().select();
|
||||
$(this).css('opacity', 0);
|
||||
const placeholderInput = document.createElement('input');
|
||||
placeholderInput.setAttribute('class', 'placeholder-edit');
|
||||
placeholderInput.setAttribute('data-id', placeholderID);
|
||||
placeholderInput.setAttribute('data-code-var-escaped', placeholderID);
|
||||
placeholderInput.setAttribute('value', placeholderValue);
|
||||
placeholderInput.setAttribute('spellcheck', 'false');
|
||||
|
||||
placeholderInput.addEventListener('blur', function() {
|
||||
submitPlaceholder($(this));
|
||||
}
|
||||
);
|
||||
placeholderInput.addEventListener('input', function() {
|
||||
updateInputWidth($(this));
|
||||
}
|
||||
);
|
||||
placeholderInput.addEventListener('keydown', function(event) {
|
||||
closeOnEnter($(this)[0], event);
|
||||
}
|
||||
);
|
||||
|
||||
const placeholderInputWrapper = $('<div class="code-input-wrapper"></div>');
|
||||
$placeholder.before(placeholderInputWrapper)
|
||||
$placeholder.siblings('.code-input-wrapper').append(placeholderInput);
|
||||
$(`input[data-code-var-escaped="${placeholderID}"]`).width(`${placeholderValue.length}ch`);
|
||||
document.querySelector(`input[data-code-var-escaped="${placeholderID}"]`).focus();
|
||||
document.querySelector(`input[data-code-var-escaped="${placeholderID}"]`).select();
|
||||
$placeholder.css('opacity', 0);
|
||||
});
|
||||
}
|
||||
|
||||
function submitPlaceholder(placeholderInput) {
|
||||
var placeholderID = placeholderInput.attr('id');
|
||||
var placeholderID = placeholderInput.attr('data-code-var-escaped');
|
||||
var placeholderValue = placeholderInput[0].value;
|
||||
var placeholderInput = $(`input.placeholder-edit#${placeholderID}`);
|
||||
placeholderInput = $(`input.placeholder-edit[data-id="${placeholderID}"]`);
|
||||
|
||||
$(`*[data-code-var='${placeholderID}']`).each(function() {
|
||||
$(`*[data-code-var="${placeholderID}"]`).each(function() {
|
||||
$(this).attr('data-code-var-value', placeholderValue);
|
||||
$(this).html(placeholderValue + editIcon);
|
||||
$(this).css('opacity', 1);
|
||||
|
@ -44,13 +66,7 @@ function closeOnEnter(input, event) {
|
|||
}
|
||||
}
|
||||
|
||||
function CodePlaceholder({element}) {
|
||||
handleClick(element);
|
||||
}
|
||||
|
||||
$(function() {
|
||||
const codePlaceholders = $(placeholderElement);
|
||||
codePlaceholders.each(function() {
|
||||
CodePlaceholder({element: this});
|
||||
});
|
||||
});
|
||||
export default function CodePlaceholder({ component }) {
|
||||
const $component = $(component);
|
||||
handleClick($component);
|
||||
}
|
|
@ -0,0 +1,78 @@
|
|||
// Memoize the mermaid module import
|
||||
let mermaidPromise = null;
|
||||
|
||||
export default function Diagram({ component }) {
|
||||
// Import mermaid.js module (memoized)
|
||||
if (!mermaidPromise) {
|
||||
mermaidPromise = import('mermaid');
|
||||
}
|
||||
mermaidPromise
|
||||
.then(({ default: mermaid }) => {
|
||||
// Configure mermaid with InfluxData theming
|
||||
mermaid.initialize({
|
||||
startOnLoad: false, // We'll manually call run()
|
||||
theme: document.body.classList.contains('dark-theme')
|
||||
? 'dark'
|
||||
: 'default',
|
||||
themeVariables: {
|
||||
fontFamily: 'Proxima Nova',
|
||||
fontSize: '16px',
|
||||
lineColor: '#22ADF6',
|
||||
primaryColor: '#22ADF6',
|
||||
primaryTextColor: '#545454',
|
||||
secondaryColor: '#05CE78',
|
||||
tertiaryColor: '#f4f5f5',
|
||||
},
|
||||
securityLevel: 'loose', // Required for interactive diagrams
|
||||
logLevel: 'error',
|
||||
});
|
||||
|
||||
// Process the specific diagram component
|
||||
try {
|
||||
mermaid.run({ nodes: [component] });
|
||||
} catch (error) {
|
||||
console.error('Mermaid diagram rendering error:', error);
|
||||
}
|
||||
|
||||
// Store reference to mermaid for theme switching
|
||||
if (!window.mermaidInstances) {
|
||||
window.mermaidInstances = new Map();
|
||||
}
|
||||
window.mermaidInstances.set(component, mermaid);
|
||||
})
|
||||
.catch((error) => {
|
||||
console.error('Failed to load Mermaid library:', error);
|
||||
});
|
||||
|
||||
// Listen for theme changes to refresh diagrams
|
||||
const observer = new MutationObserver((mutations) => {
|
||||
mutations.forEach((mutation) => {
|
||||
if (
|
||||
mutation.attributeName === 'class' &&
|
||||
document.body.classList.contains('dark-theme') !== window.isDarkTheme
|
||||
) {
|
||||
window.isDarkTheme = document.body.classList.contains('dark-theme');
|
||||
|
||||
// Reload this specific diagram with new theme
|
||||
if (window.mermaidInstances?.has(component)) {
|
||||
const mermaid = window.mermaidInstances.get(component);
|
||||
mermaid.initialize({
|
||||
theme: window.isDarkTheme ? 'dark' : 'default',
|
||||
});
|
||||
mermaid.run({ nodes: [component] });
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// Watch for theme changes on body element
|
||||
observer.observe(document.body, { attributes: true });
|
||||
|
||||
// Return cleanup function to be called when component is destroyed
|
||||
return () => {
|
||||
observer.disconnect();
|
||||
if (window.mermaidInstances?.has(component)) {
|
||||
window.mermaidInstances.delete(component);
|
||||
}
|
||||
};
|
||||
}
|
|
@ -0,0 +1,180 @@
|
|||
/**
|
||||
* DocSearch component for InfluxData documentation
|
||||
* Handles asynchronous loading and initialization of Algolia DocSearch
|
||||
*/
|
||||
const debug = false; // Set to true for debugging output
|
||||
|
||||
export default function DocSearch({ component }) {
|
||||
// Store configuration from component data attributes
|
||||
const config = {
|
||||
apiKey: component.getAttribute('data-api-key'),
|
||||
appId: component.getAttribute('data-app-id'),
|
||||
indexName: component.getAttribute('data-index-name'),
|
||||
inputSelector: component.getAttribute('data-input-selector'),
|
||||
searchTag: component.getAttribute('data-search-tag'),
|
||||
includeFlux: component.getAttribute('data-include-flux') === 'true',
|
||||
includeResources:
|
||||
component.getAttribute('data-include-resources') === 'true',
|
||||
debug: component.getAttribute('data-debug') === 'true',
|
||||
};
|
||||
|
||||
// Initialize global object to track DocSearch state
|
||||
window.InfluxDocs = window.InfluxDocs || {};
|
||||
window.InfluxDocs.search = {
|
||||
initialized: false,
|
||||
options: config,
|
||||
};
|
||||
|
||||
// Load DocSearch asynchronously
|
||||
function loadDocSearch() {
|
||||
if (debug) {
|
||||
console.log('Loading DocSearch script...');
|
||||
}
|
||||
const script = document.createElement('script');
|
||||
script.src =
|
||||
'https://cdn.jsdelivr.net/npm/docsearch.js@2/dist/cdn/docsearch.min.js';
|
||||
script.async = true;
|
||||
script.onload = initializeDocSearch;
|
||||
document.body.appendChild(script);
|
||||
}
|
||||
|
||||
// Initialize DocSearch after script loads
|
||||
function initializeDocSearch() {
|
||||
if (debug) {
|
||||
console.log('Initializing DocSearch...');
|
||||
}
|
||||
const multiVersion = ['influxdb'];
|
||||
|
||||
// Use object-based lookups instead of conditionals for version and product names
|
||||
// These can be replaced with data from productData in the future
|
||||
|
||||
// Version display name mappings
|
||||
const versionDisplayNames = {
|
||||
cloud: 'Cloud (TSM)',
|
||||
core: 'Core',
|
||||
enterprise: 'Enterprise',
|
||||
'cloud-serverless': 'Cloud Serverless',
|
||||
'cloud-dedicated': 'Cloud Dedicated',
|
||||
clustered: 'Clustered',
|
||||
explorer: 'Explorer',
|
||||
};
|
||||
|
||||
// Product display name mappings
|
||||
const productDisplayNames = {
|
||||
influxdb: 'InfluxDB',
|
||||
influxdb3: 'InfluxDB 3',
|
||||
explorer: 'InfluxDB 3 Explorer',
|
||||
enterprise_influxdb: 'InfluxDB Enterprise',
|
||||
flux: 'Flux',
|
||||
telegraf: 'Telegraf',
|
||||
chronograf: 'Chronograf',
|
||||
kapacitor: 'Kapacitor',
|
||||
platform: 'InfluxData Platform',
|
||||
resources: 'Additional Resources',
|
||||
};
|
||||
|
||||
// Initialize DocSearch with configuration
|
||||
window.docsearch({
|
||||
apiKey: config.apiKey,
|
||||
appId: config.appId,
|
||||
indexName: config.indexName,
|
||||
inputSelector: config.inputSelector,
|
||||
debug: config.debug,
|
||||
transformData: function (hits) {
|
||||
// Format version using object lookup instead of if-else chain
|
||||
function fmtVersion(version, productKey) {
|
||||
if (version == null) {
|
||||
return '';
|
||||
} else if (versionDisplayNames[version]) {
|
||||
return versionDisplayNames[version];
|
||||
} else if (multiVersion.includes(productKey)) {
|
||||
return version;
|
||||
} else {
|
||||
return '';
|
||||
}
|
||||
}
|
||||
|
||||
hits.map((hit) => {
|
||||
const pathData = new URL(hit.url).pathname
|
||||
.split('/')
|
||||
.filter((n) => n);
|
||||
const product = productDisplayNames[pathData[0]] || pathData[0];
|
||||
const version = fmtVersion(pathData[1], pathData[0]);
|
||||
|
||||
hit.product = product;
|
||||
hit.version = version;
|
||||
hit.hierarchy.lvl0 =
|
||||
hit.hierarchy.lvl0 +
|
||||
` <span class=\"search-product-version\">${product} ${version}</span>`;
|
||||
hit._highlightResult.hierarchy.lvl0.value =
|
||||
hit._highlightResult.hierarchy.lvl0.value +
|
||||
` <span class=\"search-product-version\">${product} ${version}</span>`;
|
||||
});
|
||||
return hits;
|
||||
},
|
||||
algoliaOptions: {
|
||||
hitsPerPage: 10,
|
||||
facetFilters: buildFacetFilters(config),
|
||||
},
|
||||
autocompleteOptions: {
|
||||
templates: {
|
||||
header:
|
||||
'<div class="search-all-content"><a href="https:\/\/support.influxdata.com" target="_blank">Search all InfluxData content <span class="icon-arrow-up-right"></span></a>',
|
||||
empty:
|
||||
'<div class="search-no-results"><p>Not finding what you\'re looking for?</p> <a href="https:\/\/support.influxdata.com" target="_blank">Search all InfluxData content <span class="icon-arrow-up-right"></span></a></div>',
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
// Mark DocSearch as initialized
|
||||
window.InfluxDocs.search.initialized = true;
|
||||
|
||||
// Dispatch event for other components to know DocSearch is ready
|
||||
window.dispatchEvent(new CustomEvent('docsearch-initialized'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function to build facet filters based on config
|
||||
* - Uses nested arrays for AND conditions
|
||||
* - Includes space after colon in filter expressions
|
||||
*/
|
||||
function buildFacetFilters(config) {
|
||||
if (!config.searchTag) {
|
||||
return ['latest:true'];
|
||||
} else if (config.includeFlux) {
|
||||
// Return a nested array to match original template structure
|
||||
// Note the space after each colon
|
||||
return [
|
||||
[
|
||||
'searchTag: ' + config.searchTag,
|
||||
'flux:true',
|
||||
'resources: ' + config.includeResources,
|
||||
],
|
||||
];
|
||||
} else {
|
||||
// Return a nested array to match original template structure
|
||||
// Note the space after each colon
|
||||
return [
|
||||
[
|
||||
'searchTag: ' + config.searchTag,
|
||||
'resources: ' + config.includeResources,
|
||||
],
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
// Load DocSearch when page is idle or after a slight delay
|
||||
if ('requestIdleCallback' in window) {
|
||||
requestIdleCallback(loadDocSearch);
|
||||
} else {
|
||||
setTimeout(loadDocSearch, 500);
|
||||
}
|
||||
|
||||
// Return cleanup function
|
||||
return function cleanup() {
|
||||
// Clean up any event listeners if needed
|
||||
if (debug) {
|
||||
console.log('DocSearch component cleanup');
|
||||
}
|
||||
};
|
||||
}
|
|
@ -0,0 +1,6 @@
|
|||
import SearchInteractions from '../utils/search-interactions.js';
|
||||
|
||||
export default function SidebarSearch({ component }) {
|
||||
const searchInput = component.querySelector('.sidebar--search-field');
|
||||
SearchInteractions({ searchInput });
|
||||
}
|
|
@ -1,7 +1,7 @@
|
|||
import $ from 'jquery';
|
||||
import { Datepicker } from 'vanillajs-datepicker';
|
||||
import { toggleModal } from './modals.js';
|
||||
import * as localStorage from './local-storage.js';
|
||||
import * as localStorage from './services/local-storage.js';
|
||||
|
||||
// Placeholder start date used in InfluxDB custom timestamps
|
||||
const defaultStartDate = '2022-01-01';
|
||||
|
@ -53,65 +53,65 @@ function timeToUnixSeconds(time) {
|
|||
return unixSeconds;
|
||||
}
|
||||
|
||||
// Default time values in getting started sample data
|
||||
const defaultTimes = [
|
||||
{
|
||||
rfc3339: `${defaultStartDate}T08:00:00Z`,
|
||||
unix: timeToUnixSeconds(`${defaultStartDate}T08:00:00Z`),
|
||||
}, // 1641024000
|
||||
{
|
||||
rfc3339: `${defaultStartDate}T09:00:00Z`,
|
||||
unix: timeToUnixSeconds(`${defaultStartDate}T09:00:00Z`),
|
||||
}, // 1641027600
|
||||
{
|
||||
rfc3339: `${defaultStartDate}T10:00:00Z`,
|
||||
unix: timeToUnixSeconds(`${defaultStartDate}T10:00:00Z`),
|
||||
}, // 1641031200
|
||||
{
|
||||
rfc3339: `${defaultStartDate}T11:00:00Z`,
|
||||
unix: timeToUnixSeconds(`${defaultStartDate}T11:00:00Z`),
|
||||
}, // 1641034800
|
||||
{
|
||||
rfc3339: `${defaultStartDate}T12:00:00Z`,
|
||||
unix: timeToUnixSeconds(`${defaultStartDate}T12:00:00Z`),
|
||||
}, // 1641038400
|
||||
{
|
||||
rfc3339: `${defaultStartDate}T13:00:00Z`,
|
||||
unix: timeToUnixSeconds(`${defaultStartDate}T13:00:00Z`),
|
||||
}, // 1641042000
|
||||
{
|
||||
rfc3339: `${defaultStartDate}T14:00:00Z`,
|
||||
unix: timeToUnixSeconds(`${defaultStartDate}T14:00:00Z`),
|
||||
}, // 1641045600
|
||||
{
|
||||
rfc3339: `${defaultStartDate}T15:00:00Z`,
|
||||
unix: timeToUnixSeconds(`${defaultStartDate}T15:00:00Z`),
|
||||
}, // 1641049200
|
||||
{
|
||||
rfc3339: `${defaultStartDate}T16:00:00Z`,
|
||||
unix: timeToUnixSeconds(`${defaultStartDate}T16:00:00Z`),
|
||||
}, // 1641052800
|
||||
{
|
||||
rfc3339: `${defaultStartDate}T17:00:00Z`,
|
||||
unix: timeToUnixSeconds(`${defaultStartDate}T17:00:00Z`),
|
||||
}, // 1641056400
|
||||
{
|
||||
rfc3339: `${defaultStartDate}T18:00:00Z`,
|
||||
unix: timeToUnixSeconds(`${defaultStartDate}T18:00:00Z`),
|
||||
}, // 1641060000
|
||||
{
|
||||
rfc3339: `${defaultStartDate}T19:00:00Z`,
|
||||
unix: timeToUnixSeconds(`${defaultStartDate}T19:00:00Z`),
|
||||
}, // 1641063600
|
||||
{
|
||||
rfc3339: `${defaultStartDate}T20:00:00Z`,
|
||||
unix: timeToUnixSeconds(`${defaultStartDate}T20:00:00Z`),
|
||||
}, // 1641067200
|
||||
];
|
||||
// Default time values in getting started sample data
|
||||
const defaultTimes = [
|
||||
{
|
||||
rfc3339: `${defaultStartDate}T08:00:00Z`,
|
||||
unix: timeToUnixSeconds(`${defaultStartDate}T08:00:00Z`),
|
||||
}, // 1641024000
|
||||
{
|
||||
rfc3339: `${defaultStartDate}T09:00:00Z`,
|
||||
unix: timeToUnixSeconds(`${defaultStartDate}T09:00:00Z`),
|
||||
}, // 1641027600
|
||||
{
|
||||
rfc3339: `${defaultStartDate}T10:00:00Z`,
|
||||
unix: timeToUnixSeconds(`${defaultStartDate}T10:00:00Z`),
|
||||
}, // 1641031200
|
||||
{
|
||||
rfc3339: `${defaultStartDate}T11:00:00Z`,
|
||||
unix: timeToUnixSeconds(`${defaultStartDate}T11:00:00Z`),
|
||||
}, // 1641034800
|
||||
{
|
||||
rfc3339: `${defaultStartDate}T12:00:00Z`,
|
||||
unix: timeToUnixSeconds(`${defaultStartDate}T12:00:00Z`),
|
||||
}, // 1641038400
|
||||
{
|
||||
rfc3339: `${defaultStartDate}T13:00:00Z`,
|
||||
unix: timeToUnixSeconds(`${defaultStartDate}T13:00:00Z`),
|
||||
}, // 1641042000
|
||||
{
|
||||
rfc3339: `${defaultStartDate}T14:00:00Z`,
|
||||
unix: timeToUnixSeconds(`${defaultStartDate}T14:00:00Z`),
|
||||
}, // 1641045600
|
||||
{
|
||||
rfc3339: `${defaultStartDate}T15:00:00Z`,
|
||||
unix: timeToUnixSeconds(`${defaultStartDate}T15:00:00Z`),
|
||||
}, // 1641049200
|
||||
{
|
||||
rfc3339: `${defaultStartDate}T16:00:00Z`,
|
||||
unix: timeToUnixSeconds(`${defaultStartDate}T16:00:00Z`),
|
||||
}, // 1641052800
|
||||
{
|
||||
rfc3339: `${defaultStartDate}T17:00:00Z`,
|
||||
unix: timeToUnixSeconds(`${defaultStartDate}T17:00:00Z`),
|
||||
}, // 1641056400
|
||||
{
|
||||
rfc3339: `${defaultStartDate}T18:00:00Z`,
|
||||
unix: timeToUnixSeconds(`${defaultStartDate}T18:00:00Z`),
|
||||
}, // 1641060000
|
||||
{
|
||||
rfc3339: `${defaultStartDate}T19:00:00Z`,
|
||||
unix: timeToUnixSeconds(`${defaultStartDate}T19:00:00Z`),
|
||||
}, // 1641063600
|
||||
{
|
||||
rfc3339: `${defaultStartDate}T20:00:00Z`,
|
||||
unix: timeToUnixSeconds(`${defaultStartDate}T20:00:00Z`),
|
||||
}, // 1641067200
|
||||
];
|
||||
|
||||
function updateTimestamps (newStartDate, seedTimes=defaultTimes) {
|
||||
function updateTimestamps(newStartDate, seedTimes = defaultTimes) {
|
||||
// Update the times array with replacement times
|
||||
const times = seedTimes.map(x => {
|
||||
const times = seedTimes.map((x) => {
|
||||
var newStartTimestamp = x.rfc3339.replace(/^.*T/, newStartDate + 'T');
|
||||
|
||||
return {
|
||||
|
@ -178,7 +178,7 @@ function updateTimestamps (newStartDate, seedTimes=defaultTimes) {
|
|||
|
||||
/////////////////////// MODAL INTERACTIONS / DATE PICKER ///////////////////////
|
||||
|
||||
function CustomTimeTrigger({component}) {
|
||||
function CustomTimeTrigger({ component }) {
|
||||
const $component = $(component);
|
||||
$component
|
||||
.find('a[data-action="open"]:first')
|
||||
|
@ -212,7 +212,7 @@ function CustomTimeTrigger({component}) {
|
|||
|
||||
if (newDate != undefined) {
|
||||
newDate = formatDate(newDate);
|
||||
|
||||
|
||||
// Update the last updated timestamps with the new date
|
||||
// and reassign the updated times.
|
||||
updatedTimes = updateTimestamps(newDate, updatedTimes);
|
||||
|
|
|
@ -1,30 +1,54 @@
|
|||
const monthNames = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"];
|
||||
var date = new Date()
|
||||
var currentTimestamp = date.toISOString().replace(/^(.*)(\.\d+)(Z)/, '$1$3') // 2023-01-01T12:34:56Z
|
||||
var currentTime = date.toISOString().replace(/(^.*T)(.*)(Z)/, '$2') + '084216' // 12:34:56.000084216
|
||||
import $ from 'jquery';
|
||||
|
||||
function currentDate(offset=0, trimTime=false) {
|
||||
outputDate = new Date(date)
|
||||
outputDate.setDate(outputDate.getDate() + offset)
|
||||
var date = new Date();
|
||||
var currentTimestamp = date.toISOString().replace(/^(.*)(\.\d+)(Z)/, '$1$3'); // 2023-01-01T12:34:56Z
|
||||
|
||||
// Microsecond offset appended to the current time string for formatting purposes
|
||||
const MICROSECOND_OFFSET = '084216';
|
||||
|
||||
var currentTime =
|
||||
date.toISOString().replace(/(^.*T)(.*)(Z)/, '$2') + MICROSECOND_OFFSET; // 12:34:56.000084216
|
||||
function currentDate(offset = 0, trimTime = false) {
|
||||
let outputDate = new Date(date);
|
||||
outputDate.setDate(outputDate.getDate() + offset);
|
||||
|
||||
if (trimTime) {
|
||||
return outputDate.toISOString().replace(/T.*$/, '') // 2023-01-01
|
||||
return outputDate.toISOString().replace(/T.*$/, ''); // 2023-01-01
|
||||
} else {
|
||||
return outputDate.toISOString().replace(/T.*$/, 'T00:00:00Z') // 2023-01-01T00:00:00Z
|
||||
return outputDate.toISOString().replace(/T.*$/, 'T00:00:00Z'); // 2023-01-01T00:00:00Z
|
||||
}
|
||||
}
|
||||
|
||||
function enterpriseEOLDate() {
|
||||
var inTwoYears = date.setFullYear(date.getFullYear() + 2)
|
||||
earliestEOL = new Date(inTwoYears)
|
||||
return `${monthNames[earliestEOL.getMonth()]} ${earliestEOL.getDate()}, ${earliestEOL.getFullYear()}`
|
||||
const monthNames = [
|
||||
'January',
|
||||
'February',
|
||||
'March',
|
||||
'April',
|
||||
'May',
|
||||
'June',
|
||||
'July',
|
||||
'August',
|
||||
'September',
|
||||
'October',
|
||||
'November',
|
||||
'December',
|
||||
];
|
||||
var inTwoYears = new Date(date);
|
||||
inTwoYears.setFullYear(inTwoYears.getFullYear() + 2);
|
||||
let earliestEOL = new Date(inTwoYears);
|
||||
return `${monthNames[earliestEOL.getMonth()]} ${earliestEOL.getDate()}, ${earliestEOL.getFullYear()}`;
|
||||
}
|
||||
|
||||
$('span.current-timestamp').text(currentTimestamp)
|
||||
$('span.current-time').text(currentTime)
|
||||
$('span.enterprise-eol-date').text(enterpriseEOLDate)
|
||||
$('span.current-date').each(function() {
|
||||
var dayOffset = parseInt($(this).attr("offset"))
|
||||
var trimTime = $(this).attr("trim-time") === "true"
|
||||
$(this).text(currentDate(dayOffset, trimTime))
|
||||
})
|
||||
function initialize() {
|
||||
$('span.current-timestamp').text(currentTimestamp);
|
||||
$('span.current-time').text(currentTime);
|
||||
$('span.enterprise-eol-date').text(enterpriseEOLDate());
|
||||
$('span.current-date').each(function () {
|
||||
var dayOffset = parseInt($(this).attr('offset'));
|
||||
var trimTime = $(this).attr('trim-time') === 'true';
|
||||
$(this).text(currentDate(dayOffset, trimTime));
|
||||
});
|
||||
}
|
||||
|
||||
export { initialize };
|
||||
|
|
|
@ -2,37 +2,24 @@
|
|||
This feature is designed to callout new features added to the documentation
|
||||
CSS is required for the callout bubble to determine look and position, but the
|
||||
element must have the `callout` class and a unique id.
|
||||
Callouts are treated as notifications and use the notification cookie API in
|
||||
assets/js/cookies.js.
|
||||
Callouts are treated as notifications and use the LocalStorage notification API.
|
||||
*/
|
||||
|
||||
import $ from 'jquery';
|
||||
import * as LocalStorageAPI from './services/local-storage.js';
|
||||
|
||||
// Get notification ID
|
||||
function getCalloutID (el) {
|
||||
function getCalloutID(el) {
|
||||
return $(el).attr('id');
|
||||
}
|
||||
|
||||
// Hide a callout and update the cookie with the viewed callout
|
||||
function hideCallout (calloutID) {
|
||||
if (!window.LocalStorageAPI.notificationIsRead(calloutID)) {
|
||||
window.LocalStorageAPI.setNotificationAsRead(calloutID, 'callout');
|
||||
$(`#${calloutID}`).fadeOut(200);
|
||||
// Show the url feature callouts on page load
|
||||
export default function FeatureCallout({ component }) {
|
||||
const calloutID = getCalloutID($(component));
|
||||
|
||||
if (!LocalStorageAPI.notificationIsRead(calloutID, 'callout')) {
|
||||
$(`#${calloutID}.feature-callout`)
|
||||
.fadeIn(300)
|
||||
.removeClass('start-position');
|
||||
}
|
||||
}
|
||||
|
||||
// Show the url feature callouts on page load
|
||||
$(document).ready(function () {
|
||||
$('.feature-callout').each(function () {
|
||||
const calloutID = getCalloutID($(this));
|
||||
|
||||
if (!window.LocalStorageAPI.notificationIsRead(calloutID, 'callout')) {
|
||||
$(`#${calloutID}.feature-callout`)
|
||||
.fadeIn(300)
|
||||
.removeClass('start-position');
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// Hide the InfluxDB URL selector callout
|
||||
// $('button.url-trigger, #influxdb-url-selector .close').click(function () {
|
||||
// hideCallout('influxdb-url-selector');
|
||||
// });
|
||||
|
|
|
@ -1,49 +1,148 @@
|
|||
var tablesElement = $("#flux-group-keys-demo #grouped-tables")
|
||||
import $ from 'jquery';
|
||||
|
||||
// Sample data
|
||||
let data = [
|
||||
[
|
||||
{ _time: "2021-01-01T00:00:00Z", _measurement: "example", loc: "rm1", sensorID: "A123", _field: "temp", _value: 110.3 },
|
||||
{ _time: "2021-01-01T00:01:00Z", _measurement: "example", loc: "rm1", sensorID: "A123", _field: "temp", _value: 112.5 },
|
||||
{ _time: "2021-01-01T00:02:00Z", _measurement: "example", loc: "rm1", sensorID: "A123", _field: "temp", _value: 111.9 }
|
||||
{
|
||||
_time: '2021-01-01T00:00:00Z',
|
||||
_measurement: 'example',
|
||||
loc: 'rm1',
|
||||
sensorID: 'A123',
|
||||
_field: 'temp',
|
||||
_value: 110.3,
|
||||
},
|
||||
{
|
||||
_time: '2021-01-01T00:01:00Z',
|
||||
_measurement: 'example',
|
||||
loc: 'rm1',
|
||||
sensorID: 'A123',
|
||||
_field: 'temp',
|
||||
_value: 112.5,
|
||||
},
|
||||
{
|
||||
_time: '2021-01-01T00:02:00Z',
|
||||
_measurement: 'example',
|
||||
loc: 'rm1',
|
||||
sensorID: 'A123',
|
||||
_field: 'temp',
|
||||
_value: 111.9,
|
||||
},
|
||||
],
|
||||
[
|
||||
{ _time: "2021-01-01T00:00:00Z", _measurement: "example", loc: "rm1", sensorID: "A123", _field: "hum", _value: 73.4 },
|
||||
{ _time: "2021-01-01T00:01:00Z", _measurement: "example", loc: "rm1", sensorID: "A123", _field: "hum", _value: 73.7 },
|
||||
{ _time: "2021-01-01T00:02:00Z", _measurement: "example", loc: "rm1", sensorID: "A123", _field: "hum", _value: 75.1 }
|
||||
{
|
||||
_time: '2021-01-01T00:00:00Z',
|
||||
_measurement: 'example',
|
||||
loc: 'rm1',
|
||||
sensorID: 'A123',
|
||||
_field: 'hum',
|
||||
_value: 73.4,
|
||||
},
|
||||
{
|
||||
_time: '2021-01-01T00:01:00Z',
|
||||
_measurement: 'example',
|
||||
loc: 'rm1',
|
||||
sensorID: 'A123',
|
||||
_field: 'hum',
|
||||
_value: 73.7,
|
||||
},
|
||||
{
|
||||
_time: '2021-01-01T00:02:00Z',
|
||||
_measurement: 'example',
|
||||
loc: 'rm1',
|
||||
sensorID: 'A123',
|
||||
_field: 'hum',
|
||||
_value: 75.1,
|
||||
},
|
||||
],
|
||||
[
|
||||
{ _time: "2021-01-01T00:00:00Z", _measurement: "example", loc: "rm2", sensorID: "B456", _field: "temp", _value: 108.2 },
|
||||
{ _time: "2021-01-01T00:01:00Z", _measurement: "example", loc: "rm2", sensorID: "B456", _field: "temp", _value: 108.5 },
|
||||
{ _time: "2021-01-01T00:02:00Z", _measurement: "example", loc: "rm2", sensorID: "B456", _field: "temp", _value: 109.6 }
|
||||
{
|
||||
_time: '2021-01-01T00:00:00Z',
|
||||
_measurement: 'example',
|
||||
loc: 'rm2',
|
||||
sensorID: 'B456',
|
||||
_field: 'temp',
|
||||
_value: 108.2,
|
||||
},
|
||||
{
|
||||
_time: '2021-01-01T00:01:00Z',
|
||||
_measurement: 'example',
|
||||
loc: 'rm2',
|
||||
sensorID: 'B456',
|
||||
_field: 'temp',
|
||||
_value: 108.5,
|
||||
},
|
||||
{
|
||||
_time: '2021-01-01T00:02:00Z',
|
||||
_measurement: 'example',
|
||||
loc: 'rm2',
|
||||
sensorID: 'B456',
|
||||
_field: 'temp',
|
||||
_value: 109.6,
|
||||
},
|
||||
],
|
||||
[
|
||||
{ _time: "2021-01-01T00:00:00Z", _measurement: "example", loc: "rm2", sensorID: "B456", _field: "hum", _value: 71.8 },
|
||||
{ _time: "2021-01-01T00:01:00Z", _measurement: "example", loc: "rm2", sensorID: "B456", _field: "hum", _value: 72.3 },
|
||||
{ _time: "2021-01-01T00:02:00Z", _measurement: "example", loc: "rm2", sensorID: "B456", _field: "hum", _value: 72.1 }
|
||||
]
|
||||
]
|
||||
{
|
||||
_time: '2021-01-01T00:00:00Z',
|
||||
_measurement: 'example',
|
||||
loc: 'rm2',
|
||||
sensorID: 'B456',
|
||||
_field: 'hum',
|
||||
_value: 71.8,
|
||||
},
|
||||
{
|
||||
_time: '2021-01-01T00:01:00Z',
|
||||
_measurement: 'example',
|
||||
loc: 'rm2',
|
||||
sensorID: 'B456',
|
||||
_field: 'hum',
|
||||
_value: 72.3,
|
||||
},
|
||||
{
|
||||
_time: '2021-01-01T00:02:00Z',
|
||||
_measurement: 'example',
|
||||
loc: 'rm2',
|
||||
sensorID: 'B456',
|
||||
_field: 'hum',
|
||||
_value: 72.1,
|
||||
},
|
||||
],
|
||||
];
|
||||
|
||||
// Default group key
|
||||
let groupKey = ["_measurement", "loc", "sensorID", "_field"]
|
||||
let groupKey = ['_measurement', 'loc', 'sensorID', '_field'];
|
||||
|
||||
export default function FluxGroupKeysDemo({ component }) {
|
||||
$('.column-list label').click(function () {
|
||||
toggleCheckbox($(this));
|
||||
groupKey = getChecked(component);
|
||||
groupData();
|
||||
buildGroupExample(component);
|
||||
});
|
||||
|
||||
// Group and render tables on load
|
||||
groupData();
|
||||
}
|
||||
|
||||
// Build a table group (group key and table) using an array of objects
|
||||
function buildTable(inputData) {
|
||||
|
||||
// Build the group key string
|
||||
function wrapString(column, value) {
|
||||
var stringColumns = ["_measurement", "loc", "sensorID", "_field"]
|
||||
var stringColumns = ['_measurement', 'loc', 'sensorID', '_field'];
|
||||
if (stringColumns.includes(column)) {
|
||||
return '"' + value + '"'
|
||||
return '"' + value + '"';
|
||||
} else {
|
||||
return value
|
||||
return value;
|
||||
}
|
||||
}
|
||||
var groupKeyString = "Group key instance = [" + (groupKey.map(column => column + ": " + wrapString(column, (inputData[0])[column])) ).join(", ") + "]";
|
||||
var groupKeyLabel = document.createElement("p");
|
||||
groupKeyLabel.className = "table-group-key"
|
||||
groupKeyLabel.innerHTML = groupKeyString
|
||||
|
||||
var groupKeyString =
|
||||
'Group key instance = [' +
|
||||
groupKey
|
||||
.map((column) => column + ': ' + wrapString(column, inputData[0][column]))
|
||||
.join(', ') +
|
||||
']';
|
||||
var groupKeyLabel = document.createElement('p');
|
||||
groupKeyLabel.className = 'table-group-key';
|
||||
groupKeyLabel.innerHTML = groupKeyString;
|
||||
|
||||
// Extract column headers
|
||||
var columns = [];
|
||||
|
@ -54,56 +153,57 @@ function buildTable(inputData) {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Create the table element
|
||||
var table = document.createElement("table");
|
||||
|
||||
const table = document.createElement('table');
|
||||
|
||||
// Create the table header
|
||||
for (let i = 0; i < columns.length; i++) {
|
||||
var header = table.createTHead();
|
||||
var th = document.createElement("th");
|
||||
var th = document.createElement('th');
|
||||
th.innerHTML = columns[i];
|
||||
if (groupKey.includes(columns[i])) {
|
||||
th.className = "grouped-by";
|
||||
th.className = 'grouped-by';
|
||||
}
|
||||
header.appendChild(th);
|
||||
}
|
||||
|
||||
// Add inputData to the HTML table
|
||||
for (let i = 0; i < inputData.length; i++) {
|
||||
tr = table.insertRow(-1);
|
||||
let tr = table.insertRow(-1);
|
||||
for (let j = 0; j < columns.length; j++) {
|
||||
var td = tr.insertCell(-1);
|
||||
td.innerHTML = inputData[i][columns[j]];
|
||||
// Highlight the value if column is part of the group key
|
||||
if (groupKey.includes(columns[j])) {
|
||||
td.className = "grouped-by";
|
||||
td.className = 'grouped-by';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Create a table group with group key and table
|
||||
var tableGroup = document.createElement("div");
|
||||
tableGroup.innerHTML += groupKeyLabel.outerHTML + table.outerHTML
|
||||
var tableGroup = document.createElement('div');
|
||||
tableGroup.innerHTML += groupKeyLabel.outerHTML + table.outerHTML;
|
||||
|
||||
return tableGroup
|
||||
return tableGroup;
|
||||
}
|
||||
|
||||
// Clear and rebuild all HTML tables
|
||||
function buildTables(data) {
|
||||
existingTables = tablesElement[0]
|
||||
let tablesElement = $('#flux-group-keys-demo #grouped-tables');
|
||||
let existingTables = tablesElement[0];
|
||||
while (existingTables.firstChild) {
|
||||
existingTables.removeChild(existingTables.firstChild);
|
||||
}
|
||||
for (let i = 0; i < data.length; i++) {
|
||||
var table = buildTable(data[i])
|
||||
var table = buildTable(data[i]);
|
||||
tablesElement.append(table);
|
||||
}
|
||||
}
|
||||
|
||||
// Group data based on the group key and output new tables
|
||||
function groupData() {
|
||||
let groupedData = data.flat()
|
||||
let groupedData = data.flat();
|
||||
|
||||
function groupBy(array, f) {
|
||||
var groups = {};
|
||||
|
@ -114,20 +214,19 @@ function groupData() {
|
|||
});
|
||||
return Object.keys(groups).map(function (group) {
|
||||
return groups[group];
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
groupedData = groupBy(groupedData, function (r) {
|
||||
return groupKey.map(v => r[v]);
|
||||
return groupKey.map((v) => r[v]);
|
||||
});
|
||||
|
||||
buildTables(groupedData);
|
||||
}
|
||||
|
||||
// Get selected column names
|
||||
var checkboxes = $("input[type=checkbox]");
|
||||
|
||||
function getChecked() {
|
||||
function getChecked(component) {
|
||||
// Get selected column names
|
||||
var checkboxes = $(component).find('input[type=checkbox]');
|
||||
var checked = [];
|
||||
for (var i = 0; i < checkboxes.length; i++) {
|
||||
var checkbox = checkboxes[i];
|
||||
|
@ -141,17 +240,12 @@ function toggleCheckbox(element) {
|
|||
}
|
||||
|
||||
// Build example group function
|
||||
function buildGroupExample() {
|
||||
var columnCollection = getChecked().map(i => '<span class=\"s2\">"' + i + '"</span>').join(", ")
|
||||
$("pre#group-by-example")[0].innerHTML = "data\n <span class='nx'>|></span> group(columns<span class='nx'>:</span> [" + columnCollection + "])";
|
||||
function buildGroupExample(component) {
|
||||
var columnCollection = getChecked(component)
|
||||
.map((i) => '<span class=\"s2\">"' + i + '"</span>')
|
||||
.join(', ');
|
||||
$('pre#group-by-example')[0].innerHTML =
|
||||
"data\n <span class='nx'>|></span> group(columns<span class='nx'>:</span> [" +
|
||||
columnCollection +
|
||||
'])';
|
||||
}
|
||||
|
||||
$(".column-list label").click(function () {
|
||||
toggleCheckbox($(this))
|
||||
groupKey = getChecked();
|
||||
groupData();
|
||||
buildGroupExample();
|
||||
});
|
||||
|
||||
// Group and render tables on load
|
||||
groupData()
|
||||
|
|
|
@ -1,22 +0,0 @@
|
|||
$('.exp-btn').click(function() {
|
||||
var targetBtnElement = $(this).parent()
|
||||
$('.exp-btn > p', targetBtnElement).fadeOut(100);
|
||||
setTimeout(function() {
|
||||
$('.exp-btn-links', targetBtnElement).fadeIn(200)
|
||||
$('.exp-btn', targetBtnElement).addClass('open');
|
||||
$('.close-btn', targetBtnElement).fadeIn(200);
|
||||
}, 100);
|
||||
})
|
||||
|
||||
$('.close-btn').click(function() {
|
||||
var targetBtnElement = $(this).parent().parent()
|
||||
$('.exp-btn-links', targetBtnElement).fadeOut(100)
|
||||
$('.exp-btn', targetBtnElement).removeClass('open');
|
||||
$(this).fadeOut(100);
|
||||
setTimeout(function() {
|
||||
$('p', targetBtnElement).fadeIn(100);
|
||||
}, 100);
|
||||
})
|
||||
|
||||
/////////////////////////////// EXPANDING BUTTONS //////////////////////////////
|
||||
|
|
@ -3,7 +3,6 @@
|
|||
///////////////////////// INFLUXDB URL PREFERENCE /////////////////////////////
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
*/
|
||||
import * as pageParams from '@params';
|
||||
import {
|
||||
DEFAULT_STORAGE_URLS,
|
||||
getPreference,
|
||||
|
@ -12,15 +11,18 @@ import {
|
|||
removeInfluxDBUrl,
|
||||
getInfluxDBUrl,
|
||||
getInfluxDBUrls,
|
||||
} from './local-storage.js';
|
||||
} from './services/local-storage.js';
|
||||
import $ from 'jquery';
|
||||
import { context as PRODUCT_CONTEXT, referrerHost } from './page-context.js';
|
||||
import { influxdbUrls } from './services/influxdb-urls.js';
|
||||
import { delay } from './helpers.js';
|
||||
import { toggleModal } from './modals.js';
|
||||
|
||||
let CLOUD_URLS = [];
|
||||
if (pageParams && pageParams.influxdb_urls) {
|
||||
CLOUD_URLS = Object.values(pageParams.influxdb_urls.cloud.providers).flatMap((provider) => provider.regions?.map((region) => region.url));
|
||||
if (influxdbUrls?.cloud) {
|
||||
CLOUD_URLS = Object.values(influxdbUrls.cloud.providers).flatMap((provider) =>
|
||||
provider.regions?.map((region) => region.url)
|
||||
);
|
||||
}
|
||||
export { CLOUD_URLS };
|
||||
|
||||
|
@ -28,7 +30,7 @@ export function InfluxDBUrl() {
|
|||
const UNIQUE_URL_PRODUCTS = ['dedicated', 'clustered'];
|
||||
const IS_UNIQUE_URL_PRODUCT = UNIQUE_URL_PRODUCTS.includes(PRODUCT_CONTEXT);
|
||||
|
||||
// Add actual cloud URLs as needed
|
||||
// Add actual cloud URLs as needed
|
||||
const elementSelector = '.article--content pre:not(.preserve)';
|
||||
|
||||
///////////////////// Stored preference management ///////////////////////
|
||||
|
@ -118,11 +120,12 @@ export function InfluxDBUrl() {
|
|||
});
|
||||
}
|
||||
|
||||
// Retrieve the currently selected URLs from the urls local storage object.
|
||||
function getUrls() {
|
||||
const { cloud, oss, core, enterprise, serverless, dedicated, clustered } = getInfluxDBUrls();
|
||||
return { oss, cloud, core, enterprise, serverless, dedicated, clustered };
|
||||
}
|
||||
// Retrieve the currently selected URLs from the urls local storage object.
|
||||
function getUrls() {
|
||||
const { cloud, oss, core, enterprise, serverless, dedicated, clustered } =
|
||||
getInfluxDBUrls();
|
||||
return { oss, cloud, core, enterprise, serverless, dedicated, clustered };
|
||||
}
|
||||
|
||||
// Retrieve the previously selected URLs from the from the urls local storage object.
|
||||
// This is used to update URLs whenever you switch between browser tabs.
|
||||
|
@ -289,15 +292,17 @@ export function InfluxDBUrl() {
|
|||
}
|
||||
|
||||
// Append the URL selector button to each codeblock containing a placeholder URL
|
||||
function appendUrlSelector(urls={
|
||||
cloud: '',
|
||||
oss: '',
|
||||
core: '',
|
||||
enterprise: '',
|
||||
serverless: '',
|
||||
dedicated: '',
|
||||
clustered: '',
|
||||
}) {
|
||||
function appendUrlSelector(
|
||||
urls = {
|
||||
cloud: '',
|
||||
oss: '',
|
||||
core: '',
|
||||
enterprise: '',
|
||||
serverless: '',
|
||||
dedicated: '',
|
||||
clustered: '',
|
||||
}
|
||||
) {
|
||||
const appendToUrls = Object.values(urls);
|
||||
|
||||
const getBtnText = (context) => {
|
||||
|
@ -315,7 +320,7 @@ export function InfluxDBUrl() {
|
|||
return contextText[context];
|
||||
};
|
||||
|
||||
appendToUrls.forEach(function (url) {
|
||||
appendToUrls.forEach(function (url) {
|
||||
$(elementSelector).each(function () {
|
||||
var code = $(this).html();
|
||||
if (code.includes(url)) {
|
||||
|
@ -330,20 +335,32 @@ export function InfluxDBUrl() {
|
|||
});
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
////////////////// Initialize InfluxDB URL interactions ////////////////////
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
////////////////// Initialize InfluxDB URL interactions ////////////////////
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// Add the preserve tag to code blocks that shouldn't be updated
|
||||
addPreserve();
|
||||
const { cloud, oss, core, enterprise, serverless, dedicated, clustered } = DEFAULT_STORAGE_URLS;
|
||||
const { cloud, oss, core, enterprise, serverless, dedicated, clustered } =
|
||||
DEFAULT_STORAGE_URLS;
|
||||
|
||||
// Append URL selector buttons to code blocks
|
||||
appendUrlSelector({ cloud, oss, core, enterprise, serverless, dedicated, clustered });
|
||||
appendUrlSelector({
|
||||
cloud,
|
||||
oss,
|
||||
core,
|
||||
enterprise,
|
||||
serverless,
|
||||
dedicated,
|
||||
clustered,
|
||||
});
|
||||
|
||||
// Update URLs on load
|
||||
|
||||
updateUrls({ cloud, oss, core, enterprise, serverless, dedicated, clustered }, getUrls());
|
||||
updateUrls(
|
||||
{ cloud, oss, core, enterprise, serverless, dedicated, clustered },
|
||||
getUrls()
|
||||
);
|
||||
|
||||
// Set active radio button on page load
|
||||
setRadioButtons(getUrls());
|
||||
|
|
|
@ -1,41 +1,58 @@
|
|||
// Dynamically update keybindings or hotkeys
|
||||
function getPlatform() {
|
||||
if (/Mac/.test(navigator.platform)) {
|
||||
return "osx"
|
||||
} else if (/Win/.test(navigator.platform)) {
|
||||
return "win"
|
||||
} else if (/Linux/.test(navigator.platform)) {
|
||||
return "linux"
|
||||
} else {
|
||||
return "other"
|
||||
}
|
||||
import { getPlatform } from './utils/user-agent-platform.js';
|
||||
import $ from 'jquery';
|
||||
|
||||
/**
|
||||
* Adds OS-specific class to component
|
||||
* @param {string} osClass - OS-specific class to add
|
||||
* @param {Object} options - Component options
|
||||
* @param {jQuery} options.$component - jQuery element reference
|
||||
*/
|
||||
function addOSClass(osClass, { $component }) {
|
||||
$component.addClass(osClass);
|
||||
}
|
||||
|
||||
const platform = getPlatform()
|
||||
/**
|
||||
* Updates keybinding display based on detected platform
|
||||
* @param {Object} options - Component options
|
||||
* @param {jQuery} options.$component - jQuery element reference
|
||||
* @param {string} options.platform - Detected platform
|
||||
*/
|
||||
function updateKeyBindings({ $component, platform }) {
|
||||
const osx = $component.data('osx');
|
||||
const linux = $component.data('linux');
|
||||
const win = $component.data('win');
|
||||
|
||||
function addOSClass(osClass) {
|
||||
$('.keybinding').addClass(osClass)
|
||||
}
|
||||
let keybind;
|
||||
|
||||
function updateKeyBindings() {
|
||||
$('.keybinding').each(function() {
|
||||
var osx = $(this).data("osx")
|
||||
var linux = $(this).data("linux")
|
||||
var win = $(this).data("win")
|
||||
|
||||
if (platform === "other") {
|
||||
if (win != linux) {
|
||||
var keybind = '<code class="osx">' + osx + '</code> for macOS, <code>' + linux + '</code> for Linux, and <code>' + win + '</code> for Windows';
|
||||
} else {
|
||||
var keybind = '<code>' + linux + '</code> for Linux and Windows and <code class="osx">' + osx + '</code> for macOS';
|
||||
}
|
||||
if (platform === 'other') {
|
||||
if (win !== linux) {
|
||||
keybind =
|
||||
`<code class="osx">${osx}</code> for macOS, ` +
|
||||
`<code>${linux}</code> for Linux, ` +
|
||||
`and <code>${win}</code> for Windows`;
|
||||
} else {
|
||||
var keybind = '<code>' + $(this).data(platform) + '</code>'
|
||||
keybind =
|
||||
`<code>${linux}</code> for Linux and Windows and ` +
|
||||
`<code class="osx">${osx}</code> for macOS`;
|
||||
}
|
||||
} else {
|
||||
keybind = `<code>${$component.data(platform)}</code>`;
|
||||
}
|
||||
|
||||
$(this).html(keybind)
|
||||
})
|
||||
$component.html(keybind);
|
||||
}
|
||||
|
||||
addOSClass(platform)
|
||||
updateKeyBindings()
|
||||
/**
|
||||
* Initialize and render platform-specific keybindings
|
||||
* @param {Object} options - Component options
|
||||
* @param {HTMLElement} options.component - DOM element
|
||||
* @returns {void}
|
||||
*/
|
||||
export default function KeyBinding({ component }) {
|
||||
// Initialize keybindings
|
||||
const platform = getPlatform();
|
||||
const $component = $(component);
|
||||
|
||||
addOSClass(platform, { $component });
|
||||
updateKeyBindings({ $component, platform });
|
||||
}
|
||||
|
|
|
@ -1,11 +1,15 @@
|
|||
import $ from 'jquery';
|
||||
|
||||
// Count tag elements
|
||||
function countTag(tag) {
|
||||
return $(".visible[data-tags*='" + tag + "']").length
|
||||
return $(".visible[data-tags*='" + tag + "']").length;
|
||||
}
|
||||
|
||||
function getFilterCounts() {
|
||||
$('#list-filters label').each(function() {
|
||||
var tagName = $('input', this).attr('name').replace(/[\W/]+/, "-");
|
||||
function getFilterCounts($labels) {
|
||||
$labels.each(function () {
|
||||
var tagName = $('input', this)
|
||||
.attr('name')
|
||||
.replace(/[\W/]+/, '-');
|
||||
var tagCount = countTag(tagName);
|
||||
$(this).attr('data-count', '(' + tagCount + ')');
|
||||
if (tagCount <= 0) {
|
||||
|
@ -13,38 +17,58 @@ function getFilterCounts() {
|
|||
} else {
|
||||
$(this).fadeTo(400, 1.0);
|
||||
}
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
// Get initial filter count on page load
|
||||
getFilterCounts()
|
||||
/** TODO: Include the data source value in the as an additional attribute
|
||||
* in the HTML and pass it into the component, which would let us use selectors
|
||||
* for only the source items and let us have more than one
|
||||
* list filter component per page without conflicts */
|
||||
export default function ListFilters({ component }) {
|
||||
const $component = $(component);
|
||||
const $labels = $component.find('label');
|
||||
const $inputs = $component.find('input');
|
||||
|
||||
$("#list-filters input").click(function() {
|
||||
getFilterCounts($labels);
|
||||
|
||||
// List of tags to hide
|
||||
var tagArray = $("#list-filters input:checkbox:checked").map(function(){
|
||||
return $(this).attr('name').replace(/[\W]+/, "-");
|
||||
}).get();
|
||||
$inputs.click(function () {
|
||||
// List of tags to hide
|
||||
var tagArray = $component
|
||||
.find('input:checkbox:checked')
|
||||
.map(function () {
|
||||
return $(this).attr('name').replace(/[\W]+/, '-');
|
||||
})
|
||||
.get();
|
||||
|
||||
// List of tags to restore
|
||||
var restoreArray = $("#list-filters input:checkbox:not(:checked)").map(function(){
|
||||
return $(this).attr('name').replace(/[\W]+/, "-");
|
||||
}).get();
|
||||
// List of tags to restore
|
||||
var restoreArray = $component
|
||||
.find('input:checkbox:not(:checked)')
|
||||
.map(function () {
|
||||
return $(this).attr('name').replace(/[\W]+/, '-');
|
||||
})
|
||||
.get();
|
||||
|
||||
// Actions for filter select
|
||||
if ( $(this).is(':checked') ) {
|
||||
$.each( tagArray, function( index, value ) {
|
||||
$(".filter-item.visible:not([data-tags~='" + value + "'])").removeClass('visible').fadeOut()
|
||||
})
|
||||
} else {
|
||||
$.each( restoreArray, function( index, value ) {
|
||||
$(".filter-item:not(.visible)[data-tags~='" + value + "']").addClass('visible').fadeIn()
|
||||
})
|
||||
$.each( tagArray, function( index, value ) {
|
||||
$(".filter-item.visible:not([data-tags~='" + value + "'])").removeClass('visible').hide()
|
||||
})
|
||||
}
|
||||
// Actions for filter select
|
||||
if ($(this).is(':checked')) {
|
||||
$.each(tagArray, function (index, value) {
|
||||
$(".filter-item.visible:not([data-tags~='" + value + "'])")
|
||||
.removeClass('visible')
|
||||
.fadeOut();
|
||||
});
|
||||
} else {
|
||||
$.each(restoreArray, function (index, value) {
|
||||
$(".filter-item:not(.visible)[data-tags~='" + value + "']")
|
||||
.addClass('visible')
|
||||
.fadeIn();
|
||||
});
|
||||
$.each(tagArray, function (index, value) {
|
||||
$(".filter-item.visible:not([data-tags~='" + value + "'])")
|
||||
.removeClass('visible')
|
||||
.hide();
|
||||
});
|
||||
}
|
||||
|
||||
// Refresh filter count
|
||||
getFilterCounts()
|
||||
});
|
||||
// Refresh filter count
|
||||
getFilterCounts($labels);
|
||||
});
|
||||
}
|
||||
|
|
|
@ -1,35 +1,24 @@
|
|||
// assets/js/main.js
|
||||
|
||||
// If you need to pass parameters from the calling Hugo page, you can import them here like so:
|
||||
// import * as pageParams from '@params';
|
||||
// Import dependencies that we still need to load in the global scope
|
||||
import $ from 'jquery';
|
||||
|
||||
/** Import modules that are not components.
|
||||
* TODO: Refactor these into single-purpose component modules.
|
||||
*/
|
||||
// import * as codeblocksPreferences from './api-libs.js';
|
||||
// import * as datetime from './datetime.js';
|
||||
// import * as featureCallouts from './feature-callouts.js';
|
||||
import * as apiLibs from './api-libs.js';
|
||||
import * as codeControls from './code-controls.js';
|
||||
import * as contentInteractions from './content-interactions.js';
|
||||
import * as datetime from './datetime.js';
|
||||
import { delay } from './helpers.js';
|
||||
import { InfluxDBUrl } from './influxdb-url.js';
|
||||
import * as localStorage from './local-storage.js';
|
||||
import * as localStorage from './services/local-storage.js';
|
||||
import * as modals from './modals.js';
|
||||
import * as notifications from './notifications.js';
|
||||
import * as pageContext from './page-context.js';
|
||||
import * as pageFeedback from './page-feedback.js';
|
||||
import * as tabbedContent from './tabbed-content.js';
|
||||
import * as v3Wayfinding from './v3-wayfinding.js';
|
||||
// import * as homeInteractions from './home-interactions.js';
|
||||
// import { getUrls, getReferrerHost, InfluxDBUrl } from './influxdb-url.js';
|
||||
// import * as keybindings from './keybindings.js';
|
||||
// import * as listFilters from './list-filters.js';
|
||||
// import { Modal } from './modal.js';
|
||||
// import { showNotifications } from './notifications.js';
|
||||
// import ReleaseTOC from './release-toc.js';
|
||||
// import * as scroll from './scroll.js';
|
||||
// import { TabbedContent } from './tabbed-content.js';
|
||||
|
||||
/** Import component modules
|
||||
* The component pattern organizes JavaScript, CSS, and HTML for a specific UI element or interaction:
|
||||
|
@ -39,107 +28,151 @@ import * as v3Wayfinding from './v3-wayfinding.js';
|
|||
* The JavaScript is ideally a single-purpose module that exports a single default function to initialize the component and handle any component interactions.
|
||||
*/
|
||||
import AskAITrigger from './ask-ai-trigger.js';
|
||||
import CodePlaceholder from './code-placeholders.js';
|
||||
import { CustomTimeTrigger } from './custom-timestamps.js';
|
||||
import Diagram from './components/diagram.js';
|
||||
import DocSearch from './components/doc-search.js';
|
||||
import FeatureCallout from './feature-callouts.js';
|
||||
import FluxGroupKeysDemo from './flux-group-keys.js';
|
||||
import FluxInfluxDBVersionsTrigger from './flux-influxdb-versions.js';
|
||||
import KeyBinding from './keybindings.js';
|
||||
import ListFilters from './list-filters.js';
|
||||
import ProductSelector from './version-selector.js';
|
||||
import ReleaseToc from './release-toc.js';
|
||||
import { SearchButton } from './search-button.js';
|
||||
import SidebarSearch from './components/sidebar-search.js';
|
||||
import { SidebarToggle } from './sidebar-toggle.js';
|
||||
import Theme from './theme.js';
|
||||
import ThemeSwitch from './theme-switch.js';
|
||||
// import CodeControls from './code-controls.js';
|
||||
// import ContentInteractions from './content-interactions.js';
|
||||
// import CustomTimestamps from './custom-timestamps.js';
|
||||
// import Diagram from './Diagram.js';
|
||||
// import FluxGroupKeysExample from './FluxGroupKeysExample.js';
|
||||
import FluxInfluxDBVersionsTrigger from './flux-influxdb-versions.js';
|
||||
// import PageFeedback from './page-feedback.js';
|
||||
// import SearchInput from './SearchInput.js';
|
||||
// import Sidebar from './Sidebar.js';
|
||||
// import V3Wayfinding from './v3-wayfinding.js';
|
||||
// import VersionSelector from './VersionSelector.js';
|
||||
|
||||
// Expose libraries and components within a namespaced object (for backwards compatibility or testing)
|
||||
// Expose libraries and components within a namespaced object (for backwards compatibility or testing)
|
||||
/**
|
||||
* Component Registry
|
||||
* A central registry that maps component names to their constructor functions.
|
||||
* Add new components to this registry as they are created or migrated from non-component modules.
|
||||
* This allows for:
|
||||
* 1. Automatic component initialization based on data-component attributes
|
||||
* 2. Centralized component management
|
||||
* 3. Easy addition/removal of components
|
||||
* 4. Simplified testing and debugging
|
||||
*/
|
||||
const componentRegistry = {
|
||||
'ask-ai-trigger': AskAITrigger,
|
||||
'code-placeholder': CodePlaceholder,
|
||||
'custom-time-trigger': CustomTimeTrigger,
|
||||
diagram: Diagram,
|
||||
'doc-search': DocSearch,
|
||||
'feature-callout': FeatureCallout,
|
||||
'flux-group-keys-demo': FluxGroupKeysDemo,
|
||||
'flux-influxdb-versions-trigger': FluxInfluxDBVersionsTrigger,
|
||||
keybinding: KeyBinding,
|
||||
'list-filters': ListFilters,
|
||||
'product-selector': ProductSelector,
|
||||
'release-toc': ReleaseToc,
|
||||
'search-button': SearchButton,
|
||||
'sidebar-search': SidebarSearch,
|
||||
'sidebar-toggle': SidebarToggle,
|
||||
theme: Theme,
|
||||
'theme-switch': ThemeSwitch,
|
||||
};
|
||||
|
||||
|
||||
|
||||
document.addEventListener('DOMContentLoaded', function () {
|
||||
/**
|
||||
* Initialize global namespace for documentation JavaScript
|
||||
* Exposes core modules for debugging, testing, and backwards compatibility
|
||||
*/
|
||||
function initGlobals() {
|
||||
if (typeof window.influxdatadocs === 'undefined') {
|
||||
window.influxdatadocs = {};
|
||||
}
|
||||
|
||||
// Expose modules to the global object for debugging, testing, and backwards compatibility for non-ES6 modules.
|
||||
// Expose modules to the global object for debugging, testing, and backwards compatibility
|
||||
window.influxdatadocs.delay = delay;
|
||||
window.influxdatadocs.localStorage = window.LocalStorageAPI = localStorage;
|
||||
window.influxdatadocs.pageContext = pageContext;
|
||||
window.influxdatadocs.toggleModal = modals.toggleModal;
|
||||
window.influxdatadocs.componentRegistry = componentRegistry;
|
||||
|
||||
// On content loaded, initialize (not-component-ready) UI interaction modules
|
||||
// To differentiate these from component-ready modules, these modules typically export an initialize function that wraps UI interactions and event listeners.
|
||||
// Re-export jQuery to global namespace for legacy scripts
|
||||
if (typeof window.jQuery === 'undefined') {
|
||||
window.jQuery = window.$ = $;
|
||||
}
|
||||
|
||||
return window.influxdatadocs;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize components based on data-component attributes
|
||||
* @param {Object} globals - The global influxdatadocs namespace
|
||||
*/
|
||||
function initComponents(globals) {
|
||||
const components = document.querySelectorAll('[data-component]');
|
||||
|
||||
components.forEach((component) => {
|
||||
const componentName = component.getAttribute('data-component');
|
||||
const ComponentConstructor = componentRegistry[componentName];
|
||||
|
||||
if (ComponentConstructor) {
|
||||
// Initialize the component and store its instance in the global namespace
|
||||
try {
|
||||
const instance = ComponentConstructor({ component });
|
||||
globals[componentName] = ComponentConstructor;
|
||||
|
||||
// Optionally store component instances for future reference
|
||||
if (!globals.instances) {
|
||||
globals.instances = {};
|
||||
}
|
||||
|
||||
if (!globals.instances[componentName]) {
|
||||
globals.instances[componentName] = [];
|
||||
}
|
||||
|
||||
globals.instances[componentName].push({
|
||||
element: component,
|
||||
instance,
|
||||
});
|
||||
} catch (error) {
|
||||
console.error(
|
||||
`Error initializing component "${componentName}":`,
|
||||
error
|
||||
);
|
||||
}
|
||||
} else {
|
||||
console.warn(`Unknown component: "${componentName}"`);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize all non-component modules
|
||||
*/
|
||||
function initModules() {
|
||||
modals.initialize();
|
||||
apiLibs.initialize();
|
||||
codeControls.initialize();
|
||||
contentInteractions.initialize();
|
||||
datetime.initialize();
|
||||
InfluxDBUrl();
|
||||
notifications.initialize();
|
||||
pageFeedback.initialize();
|
||||
tabbedContent.initialize();
|
||||
v3Wayfinding.initialize();
|
||||
}
|
||||
|
||||
/** Initialize components
|
||||
Component Structure: Each component is structured as a jQuery anonymous function that listens for the document ready state.
|
||||
Initialization in main.js: Each component is called in main.js inside a jQuery document ready function to ensure they are initialized when the document is ready.
|
||||
Note: These components should *not* be called directly in the HTML.
|
||||
*/
|
||||
const components = document.querySelectorAll('[data-component]');
|
||||
components.forEach((component) => {
|
||||
const componentName = component.getAttribute('data-component');
|
||||
switch (componentName) {
|
||||
case 'ask-ai-trigger':
|
||||
AskAITrigger({ component });
|
||||
window.influxdatadocs[componentName] = AskAITrigger;
|
||||
break;
|
||||
case 'custom-time-trigger':
|
||||
CustomTimeTrigger({ component });
|
||||
window.influxdatadocs[componentName] = CustomTimeTrigger;
|
||||
break;
|
||||
case 'flux-influxdb-versions-trigger':
|
||||
FluxInfluxDBVersionsTrigger({ component });
|
||||
window.influxdatadocs[componentName] = FluxInfluxDBVersionsTrigger;
|
||||
break;
|
||||
case 'search-button':
|
||||
SearchButton({ component });
|
||||
window.influxdatadocs[componentName] = SearchButton;
|
||||
break;
|
||||
case 'sidebar-toggle':
|
||||
SidebarToggle({ component });
|
||||
window.influxdatadocs[componentName] = SidebarToggle;
|
||||
break;
|
||||
case 'theme':
|
||||
Theme({ component });
|
||||
window.influxdatadocs[componentName] = Theme;
|
||||
break;
|
||||
// CodeControls();
|
||||
// ContentInteractions();
|
||||
// CustomTimestamps();
|
||||
// Diagram();
|
||||
// FluxGroupKeysExample();
|
||||
// FluxInfluxDBVersionsModal();
|
||||
// InfluxDBUrl();
|
||||
// Modal();
|
||||
// PageFeedback();
|
||||
// ReleaseTOC();
|
||||
// SearchInput();
|
||||
// showNotifications();
|
||||
// Sidebar();
|
||||
// TabbedContent();
|
||||
// ThemeSwitch({});
|
||||
// V3Wayfinding();
|
||||
// VersionSelector();
|
||||
case 'theme-switch':
|
||||
ThemeSwitch({ component });
|
||||
window.influxdatadocs[componentName] = ThemeSwitch;
|
||||
break;
|
||||
default:
|
||||
console.warn(`Unknown component: ${componentName}`);
|
||||
}
|
||||
});
|
||||
});
|
||||
/**
|
||||
* Main initialization function
|
||||
*/
|
||||
function init() {
|
||||
// Initialize global namespace and expose core modules
|
||||
const globals = initGlobals();
|
||||
|
||||
// Initialize non-component UI modules
|
||||
initModules();
|
||||
|
||||
// Initialize components from registry
|
||||
initComponents(globals);
|
||||
}
|
||||
|
||||
// Initialize everything when the DOM is ready
|
||||
document.addEventListener('DOMContentLoaded', init);
|
||||
|
||||
// Export public API
|
||||
export { initGlobals, componentRegistry };
|
||||
|
|
|
@ -1,34 +1,80 @@
|
|||
/** This module retrieves browser context information and site data for the
|
||||
* current page, version, and product.
|
||||
*/
|
||||
import { products, influxdb_urls } from '@params';
|
||||
|
||||
const safeProducts = products || {};
|
||||
const safeUrls = influxdb_urls || {};
|
||||
import { products } from './services/influxdata-products.js';
|
||||
import { influxdbUrls } from './services/influxdb-urls.js';
|
||||
|
||||
function getCurrentProductData() {
|
||||
const path = window.location.pathname;
|
||||
const mappings = [
|
||||
{ pattern: /\/influxdb\/cloud\//, product: safeProducts.cloud, urls: safeUrls.influxdb_cloud },
|
||||
{ pattern: /\/influxdb3\/core/, product: safeProducts.influxdb3_core, urls: safeUrls.core },
|
||||
{ pattern: /\/influxdb3\/enterprise/, product: safeProducts.influxdb3_enterprise, urls: safeUrls.enterprise },
|
||||
{ pattern: /\/influxdb3\/cloud-serverless/, product: safeProducts.influxdb3_cloud_serverless, urls: safeUrls.cloud },
|
||||
{ pattern: /\/influxdb3\/cloud-dedicated/, product: safeProducts.influxdb3_cloud_dedicated, urls: safeUrls.dedicated },
|
||||
{ pattern: /\/influxdb3\/clustered/, product: safeProducts.influxdb3_clustered, urls: safeUrls.clustered },
|
||||
{ pattern: /\/enterprise_v1\//, product: safeProducts.enterprise_influxdb, urls: safeUrls.oss },
|
||||
{ pattern: /\/influxdb.*v1\//, product: safeProducts.influxdb, urls: safeUrls.oss },
|
||||
{ pattern: /\/influxdb.*v2\//, product: safeProducts.influxdb, urls: safeUrls.oss },
|
||||
{ pattern: /\/kapacitor\//, product: safeProducts.kapacitor, urls: safeUrls.oss },
|
||||
{ pattern: /\/telegraf\//, product: safeProducts.telegraf, urls: safeUrls.oss },
|
||||
{ pattern: /\/chronograf\//, product: safeProducts.chronograf, urls: safeUrls.oss },
|
||||
{ pattern: /\/flux\//, product: safeProducts.flux, urls: safeUrls.oss },
|
||||
{
|
||||
pattern: /\/influxdb\/cloud\//,
|
||||
product: products.cloud,
|
||||
urls: influxdbUrls.influxdb_cloud,
|
||||
},
|
||||
{
|
||||
pattern: /\/influxdb3\/core/,
|
||||
product: products.influxdb3_core,
|
||||
urls: influxdbUrls.core,
|
||||
},
|
||||
{
|
||||
pattern: /\/influxdb3\/enterprise/,
|
||||
product: products.influxdb3_enterprise,
|
||||
urls: influxdbUrls.enterprise,
|
||||
},
|
||||
{
|
||||
pattern: /\/influxdb3\/cloud-serverless/,
|
||||
product: products.influxdb3_cloud_serverless,
|
||||
urls: influxdbUrls.cloud,
|
||||
},
|
||||
{
|
||||
pattern: /\/influxdb3\/cloud-dedicated/,
|
||||
product: products.influxdb3_cloud_dedicated,
|
||||
urls: influxdbUrls.dedicated,
|
||||
},
|
||||
{
|
||||
pattern: /\/influxdb3\/clustered/,
|
||||
product: products.influxdb3_clustered,
|
||||
urls: influxdbUrls.clustered,
|
||||
},
|
||||
{
|
||||
pattern: /\/enterprise_v1\//,
|
||||
product: products.enterprise_influxdb,
|
||||
urls: influxdbUrls.oss,
|
||||
},
|
||||
{
|
||||
pattern: /\/influxdb.*v1\//,
|
||||
product: products.influxdb,
|
||||
urls: influxdbUrls.oss,
|
||||
},
|
||||
{
|
||||
pattern: /\/influxdb.*v2\//,
|
||||
product: products.influxdb,
|
||||
urls: influxdbUrls.oss,
|
||||
},
|
||||
{
|
||||
pattern: /\/kapacitor\//,
|
||||
product: products.kapacitor,
|
||||
urls: influxdbUrls.oss,
|
||||
},
|
||||
{
|
||||
pattern: /\/telegraf\//,
|
||||
product: products.telegraf,
|
||||
urls: influxdbUrls.oss,
|
||||
},
|
||||
{
|
||||
pattern: /\/chronograf\//,
|
||||
product: products.chronograf,
|
||||
urls: influxdbUrls.oss,
|
||||
},
|
||||
{ pattern: /\/flux\//, product: products.flux, urls: influxdbUrls.oss },
|
||||
];
|
||||
|
||||
for (const { pattern, product, urls } of mappings) {
|
||||
if (pattern.test(path)) {
|
||||
return {
|
||||
product: product || 'unknown',
|
||||
urls: urls || {}
|
||||
return {
|
||||
product: product || 'unknown',
|
||||
urls: urls || {},
|
||||
};
|
||||
}
|
||||
}
|
||||
|
@ -36,7 +82,8 @@ function getCurrentProductData() {
|
|||
return { product: 'other', urls: {} };
|
||||
}
|
||||
|
||||
// Return the page context (cloud, serverless, oss/enterprise, dedicated, clustered, other)
|
||||
// Return the page context
|
||||
// (cloud, serverless, oss/enterprise, dedicated, clustered, other)
|
||||
function getContext() {
|
||||
if (/\/influxdb\/cloud\//.test(window.location.pathname)) {
|
||||
return 'cloud';
|
||||
|
@ -78,8 +125,12 @@ const context = getContext(),
|
|||
protocol = location.protocol,
|
||||
referrer = document.referrer === '' ? 'direct' : document.referrer,
|
||||
referrerHost = getReferrerHost(),
|
||||
// TODO: Verify this still does what we want since the addition of InfluxDB 3 naming and the Core and Enterprise versions.
|
||||
version = (/^v\d/.test(pathArr[1]) || pathArr[1]?.includes('cloud') ? pathArr[1].replace(/^v/, '') : "n/a")
|
||||
// TODO: Verify this works since the addition of InfluxDB 3 naming
|
||||
// and the Core and Enterprise versions.
|
||||
version =
|
||||
/^v\d/.test(pathArr[1]) || pathArr[1]?.includes('cloud')
|
||||
? pathArr[1].replace(/^v/, '')
|
||||
: 'n/a';
|
||||
|
||||
export {
|
||||
context,
|
||||
|
@ -92,4 +143,4 @@ export {
|
|||
referrer,
|
||||
referrerHost,
|
||||
version,
|
||||
};
|
||||
};
|
||||
|
|
|
@ -1,26 +1,67 @@
|
|||
/////////////////////////// Table of Contents Script ///////////////////////////
|
||||
|
||||
/*
|
||||
* This script is used to generate a table of contents for the
|
||||
* release notes pages.
|
||||
*/
|
||||
* This script is used to generate a table of contents for the
|
||||
* release notes pages.
|
||||
*/
|
||||
export default function ReleaseToc({ component }) {
|
||||
// Get all h2 elements that are not checkpoint-releases
|
||||
const releases = Array.from(document.querySelectorAll('h2')).filter(
|
||||
(el) => !el.id.match(/checkpoint-releases/)
|
||||
);
|
||||
|
||||
// Use jQuery filter to get an array of all the *release* h2 elements
|
||||
const releases = $('h2').filter(
|
||||
(_i, el) => !el.id.match(/checkpoint-releases/)
|
||||
);
|
||||
// Extract data about each release from the array of releases
|
||||
const releaseData = releases.map((el) => ({
|
||||
name: el.textContent,
|
||||
id: el.id,
|
||||
class: el.getAttribute('class'),
|
||||
date: el.getAttribute('date'),
|
||||
}));
|
||||
|
||||
// Extract data about each release from the array of releases
|
||||
releaseData = releases.map((_i, el) => ({
|
||||
name: el.textContent,
|
||||
id: el.id,
|
||||
class: el.getAttribute('class'),
|
||||
date: el.getAttribute('date')
|
||||
}));
|
||||
// Build the release table of contents
|
||||
const releaseTocUl = component.querySelector('#release-toc ul');
|
||||
releaseData.forEach((release) => {
|
||||
releaseTocUl.appendChild(getReleaseItem(release));
|
||||
});
|
||||
|
||||
/*
|
||||
* This script is used to expand the release notes table of contents by the
|
||||
* number specified in the `show` attribute of `ul.release-list`.
|
||||
* Once all the release items are visible, the "Show More" button is hidden.
|
||||
*/
|
||||
const showMoreBtn = component.querySelector('.show-more');
|
||||
if (showMoreBtn) {
|
||||
showMoreBtn.addEventListener('click', function () {
|
||||
const itemHeight = 1.885; // Item height in rem
|
||||
const releaseNum = releaseData.length;
|
||||
const maxHeight = releaseNum * itemHeight;
|
||||
const releaseList = document.getElementById('release-list');
|
||||
const releaseIncrement = Number(releaseList.getAttribute('show'));
|
||||
const currentHeightMatch = releaseList.style.height.match(/\d+\.?\d+/);
|
||||
const currentHeight = currentHeightMatch
|
||||
? Number(currentHeightMatch[0])
|
||||
: 0;
|
||||
const potentialHeight = currentHeight + releaseIncrement * itemHeight;
|
||||
const newHeight =
|
||||
potentialHeight > maxHeight ? maxHeight : potentialHeight;
|
||||
|
||||
releaseList.style.height = `${newHeight}rem`;
|
||||
|
||||
if (newHeight >= maxHeight) {
|
||||
// Simple fade out
|
||||
showMoreBtn.style.transition = 'opacity 0.1s';
|
||||
showMoreBtn.style.opacity = 0;
|
||||
setTimeout(() => {
|
||||
showMoreBtn.style.display = 'none';
|
||||
}, 100);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Use release data to generate a list item for each release
|
||||
getReleaseItem = (releaseData) => {
|
||||
var li = document.createElement("li");
|
||||
function getReleaseItem(releaseData) {
|
||||
const li = document.createElement('li');
|
||||
if (releaseData.class !== null) {
|
||||
li.className = releaseData.class;
|
||||
}
|
||||
|
@ -28,31 +69,3 @@ getReleaseItem = (releaseData) => {
|
|||
li.setAttribute('date', releaseData.date);
|
||||
return li;
|
||||
}
|
||||
|
||||
// Use jQuery each to build the release table of contents
|
||||
releaseData.each((_i, release) => {
|
||||
$('#release-toc ul')[0].appendChild(getReleaseItem(release));
|
||||
});
|
||||
|
||||
/*
|
||||
* This script is used to expand the release notes table of contents by the
|
||||
* number specified in the `show` attribute of `ul.release-list`.
|
||||
* Once all the release items are visible, the "Show More" button is hidden.
|
||||
*/
|
||||
$('#release-toc .show-more').click(function () {
|
||||
const itemHeight = 1.885; // Item height in rem
|
||||
const releaseNum = releaseData.length;
|
||||
const maxHeight = releaseNum * itemHeight;
|
||||
const releaseIncrement = Number($('#release-list')[0].getAttribute('show'));
|
||||
const currentHeight = Number(
|
||||
$('#release-list')[0].style.height.match(/\d+\.?\d+/)[0]
|
||||
);
|
||||
const potentialHeight = currentHeight + releaseIncrement * itemHeight;
|
||||
const newHeight = potentialHeight > maxHeight ? maxHeight : potentialHeight;
|
||||
|
||||
$('#release-list')[0].style.height = `${newHeight}rem`;
|
||||
|
||||
if (newHeight >= maxHeight) {
|
||||
$('#release-toc .show-more').fadeOut(100);
|
||||
}
|
||||
});
|
||||
|
|
|
@ -1,10 +0,0 @@
|
|||
// Fade content wrapper when focusing on search input
|
||||
$('#algolia-search-input').focus(function() {
|
||||
$('.content-wrapper').fadeTo(300, .35);
|
||||
})
|
||||
|
||||
// Hide search dropdown when leaving search input
|
||||
$('#algolia-search-input').blur(function() {
|
||||
$('.content-wrapper').fadeTo(200, 1);
|
||||
$('.ds-dropdown-menu').hide();
|
||||
})
|
|
@ -0,0 +1,3 @@
|
|||
import { products as productsParam } from '@params';
|
||||
|
||||
export const products = productsParam || {};
|
|
@ -0,0 +1,3 @@
|
|||
import { influxdb_urls as influxdbUrlsParam } from '@params';
|
||||
|
||||
export const influxdbUrls = influxdbUrlsParam || {};
|
|
@ -10,7 +10,8 @@
|
|||
- messages: Messages (data/notifications.yaml) that have been seen (array)
|
||||
- callouts: Feature callouts that have been seen (array)
|
||||
*/
|
||||
import * as pageParams from '@params';
|
||||
|
||||
import { influxdbUrls } from './influxdb-urls.js';
|
||||
|
||||
// Prefix for all InfluxData docs local storage
|
||||
const storagePrefix = 'influxdata_docs_';
|
||||
|
@ -82,14 +83,12 @@ function getPreferences() {
|
|||
//////////// MANAGE INFLUXDATA DOCS URLS IN LOCAL STORAGE //////////////////////
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
const defaultUrls = {};
|
||||
// Guard against pageParams being null/undefined and safely access nested properties
|
||||
if (pageParams && pageParams.influxdb_urls) {
|
||||
Object.entries(pageParams.influxdb_urls).forEach(([product, {providers}]) => {
|
||||
defaultUrls[product] = providers.filter(provider => provider.name === 'Default')[0]?.regions[0]?.url;
|
||||
});
|
||||
}
|
||||
Object.entries(influxdbUrls).forEach(([product, { providers }]) => {
|
||||
defaultUrls[product] =
|
||||
providers.filter((provider) => provider.name === 'Default')[0]?.regions[0]
|
||||
?.url || 'https://cloud2.influxdata.com';
|
||||
});
|
||||
|
||||
export const DEFAULT_STORAGE_URLS = {
|
||||
oss: defaultUrls.oss,
|
||||
|
@ -177,7 +176,10 @@ const defaultNotificationsObj = {
|
|||
function getNotifications() {
|
||||
// Initialize notifications data if it doesn't already exist
|
||||
if (localStorage.getItem(notificationStorageKey) === null) {
|
||||
initializeStorageItem('notifications', JSON.stringify(defaultNotificationsObj));
|
||||
initializeStorageItem(
|
||||
'notifications',
|
||||
JSON.stringify(defaultNotificationsObj)
|
||||
);
|
||||
}
|
||||
|
||||
// Retrieve and parse the notifications data as JSON
|
||||
|
@ -221,7 +223,10 @@ function setNotificationAsRead(notificationID, notificationType) {
|
|||
readNotifications.push(notificationID);
|
||||
notificationsObj[notificationType + 's'] = readNotifications;
|
||||
|
||||
localStorage.setItem(notificationStorageKey, JSON.stringify(notificationsObj));
|
||||
localStorage.setItem(
|
||||
notificationStorageKey,
|
||||
JSON.stringify(notificationsObj)
|
||||
);
|
||||
}
|
||||
|
||||
// Export functions as a module and make the file backwards compatible for non-module environments until all remaining dependent scripts are ported to modules
|
|
@ -3,7 +3,7 @@
|
|||
http://www.thesitewizard.com/javascripts/change-style-sheets.shtml
|
||||
*/
|
||||
|
||||
import * as localStorage from './local-storage.js';
|
||||
import * as localStorage from './services/local-storage.js';
|
||||
|
||||
// *** TO BE CUSTOMISED ***
|
||||
var sidebar_state_preference_name = 'sidebar_state';
|
||||
|
|
|
@ -1,20 +1,21 @@
|
|||
import Theme from './theme.js';
|
||||
|
||||
export default function ThemeSwitch({ component }) {
|
||||
if ( component == undefined) {
|
||||
if (component === undefined) {
|
||||
component = document;
|
||||
}
|
||||
component.querySelectorAll(`.theme-switch-light`).forEach((button) => {
|
||||
button.addEventListener('click', function(event) {
|
||||
|
||||
component.querySelectorAll('.theme-switch-light').forEach((button) => {
|
||||
button.addEventListener('click', function (event) {
|
||||
event.preventDefault();
|
||||
Theme({ style: 'light-theme' });
|
||||
Theme({ component, style: 'light-theme' });
|
||||
});
|
||||
});
|
||||
|
||||
component.querySelectorAll(`.theme-switch-dark`).forEach((button) => {
|
||||
button.addEventListener('click', function(event) {
|
||||
component.querySelectorAll('.theme-switch-dark').forEach((button) => {
|
||||
button.addEventListener('click', function (event) {
|
||||
event.preventDefault();
|
||||
Theme({ style: 'dark-theme' });
|
||||
Theme({ component, style: 'dark-theme' });
|
||||
});
|
||||
});
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { getPreference, setPreference } from './local-storage.js';
|
||||
import { getPreference, setPreference } from './services/local-storage.js';
|
||||
|
||||
const PROPS = {
|
||||
style_preference_name: 'theme',
|
||||
|
@ -6,19 +6,22 @@ const PROPS = {
|
|||
style_domain: 'docs.influxdata.com',
|
||||
};
|
||||
|
||||
function getPreferredTheme () {
|
||||
function getPreferredTheme() {
|
||||
return `${getPreference(PROPS.style_preference_name)}-theme`;
|
||||
}
|
||||
|
||||
function switchStyle({ styles_element, css_title }) {
|
||||
// Disable all other theme stylesheets
|
||||
styles_element.querySelectorAll('link[rel*="stylesheet"][title*="theme"]')
|
||||
.forEach(function (link) {
|
||||
link.disabled = true;
|
||||
});
|
||||
styles_element
|
||||
.querySelectorAll('link[rel*="stylesheet"][title*="theme"]')
|
||||
.forEach(function (link) {
|
||||
link.disabled = true;
|
||||
});
|
||||
|
||||
// Enable the stylesheet with the specified title
|
||||
const link = styles_element.querySelector(`link[rel*="stylesheet"][title="${css_title}"]`);
|
||||
const link = styles_element.querySelector(
|
||||
`link[rel*="stylesheet"][title="${css_title}"]`
|
||||
);
|
||||
link && (link.disabled = false);
|
||||
|
||||
setPreference(PROPS.style_preference_name, css_title.replace(/-theme/, ''));
|
||||
|
@ -38,5 +41,4 @@ export default function Theme({ component, style }) {
|
|||
if (component.dataset?.themeCallback === 'setVisibility') {
|
||||
setVisibility(component);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,38 @@
|
|||
/**
|
||||
* Helper functions for debugging without source maps
|
||||
* Example usage:
|
||||
* In your code, you can use these functions like this:
|
||||
* ```javascript
|
||||
* import { debugLog, debugBreak, debugInspect } from './debug-helpers.js';
|
||||
*
|
||||
* const data = debugInspect(someData, 'Data');
|
||||
* debugLog('Processing data', 'myFunction');
|
||||
*
|
||||
* function processData() {
|
||||
* // Add a breakpoint that works with DevTools
|
||||
* debugBreak();
|
||||
*
|
||||
* // Your existing code...
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* @fileoverview DEVELOPMENT USE ONLY - Functions should not be committed to production
|
||||
*/
|
||||
|
||||
/* eslint-disable no-debugger */
|
||||
/* eslint-disable-next-line */
|
||||
// NOTE: These functions are detected by ESLint rules to prevent committing debug code
|
||||
|
||||
export function debugLog(message, context = '') {
|
||||
const contextStr = context ? `[${context}]` : '';
|
||||
console.log(`DEBUG${contextStr}: ${message}`);
|
||||
}
|
||||
|
||||
export function debugBreak() {
|
||||
debugger;
|
||||
}
|
||||
|
||||
export function debugInspect(value, label = 'Inspect') {
|
||||
console.log(`DEBUG[${label}]:`, value);
|
||||
return value;
|
||||
}
|
|
@ -0,0 +1,107 @@
|
|||
/**
|
||||
* Manages search interactions for DocSearch integration
|
||||
* Uses MutationObserver to watch for dropdown creation
|
||||
*/
|
||||
export default function SearchInteractions({ searchInput }) {
|
||||
const contentWrapper = document.querySelector('.content-wrapper');
|
||||
let observer = null;
|
||||
let dropdownObserver = null;
|
||||
let dropdownMenu = null;
|
||||
const debug = false; // Set to true for debugging logs
|
||||
|
||||
// Fade content wrapper when focusing on search input
|
||||
function handleFocus() {
|
||||
contentWrapper.style.opacity = '0.35';
|
||||
contentWrapper.style.transition = 'opacity 300ms';
|
||||
}
|
||||
|
||||
// Hide search dropdown when leaving search input
|
||||
function handleBlur(event) {
|
||||
// Only process blur if not clicking within dropdown
|
||||
const relatedTarget = event.relatedTarget;
|
||||
if (
|
||||
relatedTarget &&
|
||||
(relatedTarget.closest('.algolia-autocomplete') ||
|
||||
relatedTarget.closest('.ds-dropdown-menu'))
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
contentWrapper.style.opacity = '1';
|
||||
contentWrapper.style.transition = 'opacity 200ms';
|
||||
|
||||
// Hide dropdown if it exists
|
||||
if (dropdownMenu) {
|
||||
dropdownMenu.style.display = 'none';
|
||||
}
|
||||
}
|
||||
|
||||
// Add event listeners
|
||||
searchInput.addEventListener('focus', handleFocus);
|
||||
searchInput.addEventListener('blur', handleBlur);
|
||||
|
||||
// Use MutationObserver to detect when dropdown is added to the DOM
|
||||
observer = new MutationObserver((mutations) => {
|
||||
for (const mutation of mutations) {
|
||||
if (mutation.type === 'childList') {
|
||||
const newDropdown = document.querySelector(
|
||||
'.ds-dropdown-menu:not([data-monitored])'
|
||||
);
|
||||
if (newDropdown) {
|
||||
// Save reference to dropdown
|
||||
dropdownMenu = newDropdown;
|
||||
newDropdown.setAttribute('data-monitored', 'true');
|
||||
|
||||
// Monitor dropdown removal/display changes
|
||||
dropdownObserver = new MutationObserver((dropdownMutations) => {
|
||||
for (const dropdownMutation of dropdownMutations) {
|
||||
if (debug) {
|
||||
if (
|
||||
dropdownMutation.type === 'attributes' &&
|
||||
dropdownMutation.attributeName === 'style'
|
||||
) {
|
||||
console.log(
|
||||
'Dropdown style changed:',
|
||||
dropdownMenu.style.display
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Observe changes to dropdown attributes (like style)
|
||||
dropdownObserver.observe(dropdownMenu, {
|
||||
attributes: true,
|
||||
attributeFilter: ['style'],
|
||||
});
|
||||
|
||||
// Add event listeners to keep dropdown open when interacted with
|
||||
dropdownMenu.addEventListener('mousedown', (e) => {
|
||||
// Prevent blur on searchInput when clicking in dropdown
|
||||
e.preventDefault();
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Start observing the document body for dropdown creation
|
||||
observer.observe(document.body, {
|
||||
childList: true,
|
||||
subtree: true,
|
||||
});
|
||||
|
||||
// Return cleanup function
|
||||
return function cleanup() {
|
||||
searchInput.removeEventListener('focus', handleFocus);
|
||||
searchInput.removeEventListener('blur', handleBlur);
|
||||
|
||||
if (observer) {
|
||||
observer.disconnect();
|
||||
}
|
||||
|
||||
if (dropdownObserver) {
|
||||
dropdownObserver.disconnect();
|
||||
}
|
||||
};
|
||||
}
|
|
@ -0,0 +1,35 @@
|
|||
/**
|
||||
* Platform detection utility functions
|
||||
* Provides methods for detecting user's operating system
|
||||
*/
|
||||
|
||||
/**
|
||||
* Detects user's operating system using modern techniques
|
||||
* Falls back to userAgent parsing when newer APIs aren't available
|
||||
* @returns {string} Operating system identifier ("osx", "win", "linux", or "other")
|
||||
*/
|
||||
export function getPlatform() {
|
||||
// Try to use modern User-Agent Client Hints API first (Chrome 89+, Edge 89+)
|
||||
if (navigator.userAgentData && navigator.userAgentData.platform) {
|
||||
const platform = navigator.userAgentData.platform.toLowerCase();
|
||||
|
||||
if (platform.includes('mac')) return 'osx';
|
||||
if (platform.includes('win')) return 'win';
|
||||
if (platform.includes('linux')) return 'linux';
|
||||
}
|
||||
|
||||
// Fall back to userAgent string parsing
|
||||
const userAgent = navigator.userAgent.toLowerCase();
|
||||
|
||||
if (
|
||||
userAgent.includes('mac') ||
|
||||
userAgent.includes('iphone') ||
|
||||
userAgent.includes('ipad')
|
||||
)
|
||||
return 'osx';
|
||||
if (userAgent.includes('win')) return 'win';
|
||||
if (userAgent.includes('linux') || userAgent.includes('android'))
|
||||
return 'linux';
|
||||
|
||||
return 'other';
|
||||
}
|
|
@ -1,6 +1,14 @@
|
|||
import { CLOUD_URLS } from './influxdb-url.js';
|
||||
import * as localStorage from './local-storage.js';
|
||||
import { context, host, hostname, path, protocol, referrer, referrerHost } from './page-context.js';
|
||||
import * as localStorage from './services/local-storage.js';
|
||||
import {
|
||||
context,
|
||||
host,
|
||||
hostname,
|
||||
path,
|
||||
protocol,
|
||||
referrer,
|
||||
referrerHost,
|
||||
} from './page-context.js';
|
||||
|
||||
/**
|
||||
* Builds a referrer whitelist array that includes the current page host and all
|
||||
|
@ -69,8 +77,6 @@ function setWayfindingInputState() {
|
|||
}
|
||||
|
||||
function submitWayfindingData(engine, action) {
|
||||
|
||||
|
||||
// Build lp using page data and engine data
|
||||
const lp = `ioxwayfinding,host=${hostname},path=${path},referrer=${referrer},engine=${engine} action="${action}"`;
|
||||
|
||||
|
@ -81,10 +87,7 @@ function submitWayfindingData(engine, action) {
|
|||
'https://j32dswat7l.execute-api.us-east-1.amazonaws.com/prod/wayfinding'
|
||||
);
|
||||
xhr.setRequestHeader('X-Requested-With', 'XMLHttpRequest');
|
||||
xhr.setRequestHeader(
|
||||
'Access-Control-Allow-Origin',
|
||||
`${protocol}//${host}`
|
||||
);
|
||||
xhr.setRequestHeader('Access-Control-Allow-Origin', `${protocol}//${host}`);
|
||||
xhr.setRequestHeader('Content-Type', 'text/plain; charset=utf-8');
|
||||
xhr.setRequestHeader('Accept', 'application/json');
|
||||
xhr.send(lp);
|
||||
|
|
|
@ -1,19 +1,21 @@
|
|||
// Select the product dropdown and dropdown items
|
||||
const productDropdown = document.querySelector("#product-dropdown");
|
||||
const dropdownItems = document.querySelector("#dropdown-items");
|
||||
export default function ProductSelector({ component }) {
|
||||
// Select the product dropdown and dropdown items
|
||||
const productDropdown = component.querySelector('#product-dropdown');
|
||||
const dropdownItems = component.querySelector('#dropdown-items');
|
||||
|
||||
// Expand the menu on click
|
||||
if (productDropdown) {
|
||||
productDropdown.addEventListener("click", function() {
|
||||
productDropdown.classList.toggle("open");
|
||||
dropdownItems.classList.toggle("open");
|
||||
// Expand the menu on click
|
||||
if (productDropdown) {
|
||||
productDropdown.addEventListener('click', function () {
|
||||
productDropdown.classList.toggle('open');
|
||||
dropdownItems.classList.toggle('open');
|
||||
});
|
||||
}
|
||||
|
||||
// Close the dropdown by clicking anywhere else
|
||||
document.addEventListener('click', function (e) {
|
||||
// Check if the click was outside of the '.product-list' container
|
||||
if (!e.target.closest('.product-list')) {
|
||||
dropdownItems.classList.remove('open');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Close the dropdown by clicking anywhere else
|
||||
document.addEventListener("click", function(e) {
|
||||
// Check if the click was outside of the '.product-list' container
|
||||
if (!e.target.closest('.product-list')) {
|
||||
dropdownItems.classList.remove("open");
|
||||
}
|
||||
});
|
||||
|
|
|
@ -3,7 +3,8 @@
|
|||
"baseUrl": ".",
|
||||
"paths": {
|
||||
"*": [
|
||||
"*"
|
||||
"*",
|
||||
"../node_modules/*"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,18 @@
|
|||
/*
|
||||
Datetime Components
|
||||
----------------------------------------------
|
||||
*/
|
||||
|
||||
.current-timestamp,
|
||||
.current-date,
|
||||
.current-time,
|
||||
.enterprise-eol-date {
|
||||
color: $current-timestamp-color;
|
||||
display: inline-block;
|
||||
font-family: $proxima;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.nowrap {
|
||||
white-space: nowrap;
|
||||
}
|
|
@ -105,7 +105,7 @@
|
|||
.product {
|
||||
padding: 0 1rem;
|
||||
display: flex;
|
||||
flex: 1 1 50%;
|
||||
flex: 1 1 33%;
|
||||
flex-direction: column;
|
||||
justify-content: space-between;
|
||||
max-width: 33%;
|
||||
|
@ -118,11 +118,10 @@
|
|||
line-height: 1.5rem;
|
||||
color: rgba($article-text, .7);
|
||||
}
|
||||
}
|
||||
|
||||
&.new {
|
||||
.product-info h3::after {
|
||||
content: "New";
|
||||
h3[state] {
|
||||
&::after {
|
||||
content: attr(state);
|
||||
margin-left: .5rem;
|
||||
font-size: 1rem;
|
||||
padding: .25em .5em .25em .4em;
|
||||
|
@ -132,6 +131,8 @@
|
|||
font-style: italic;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
ul.product-links {
|
||||
|
@ -227,6 +228,30 @@
|
|||
background: $article-bg;
|
||||
}
|
||||
|
||||
.categories {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
flex-wrap: wrap;
|
||||
// margin: 0 -1rem;
|
||||
width: calc(100% + 2rem);
|
||||
|
||||
.category {
|
||||
&.full-width {
|
||||
width: 100%;
|
||||
}
|
||||
&.two-thirds {
|
||||
width: 66.66%;
|
||||
.product { max-width: 50%; }
|
||||
}
|
||||
&.one-third {
|
||||
width: 33.33%;
|
||||
.product {
|
||||
max-width: 100%;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.category-head{
|
||||
margin: 1rem 0 2rem;
|
||||
&::after {
|
||||
|
@ -234,6 +259,7 @@
|
|||
display: block;
|
||||
border-top: 1px solid $article-hr;
|
||||
margin-top: -1.15rem;
|
||||
width: calc(100% - 2rem);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -441,6 +467,16 @@
|
|||
ul {margin-bottom: 0;}
|
||||
}
|
||||
}
|
||||
.categories .category {
|
||||
&.two-thirds {
|
||||
width: 100%;
|
||||
.product { max-width: 100%; }
|
||||
}
|
||||
&.one-third {
|
||||
width: 100%;
|
||||
.product { max-width: 100%; }
|
||||
}
|
||||
}
|
||||
}
|
||||
#telegraf {
|
||||
flex-direction: column;
|
||||
|
|
|
@ -96,4 +96,5 @@ blockquote {
|
|||
"blocks/tip",
|
||||
"blocks/important",
|
||||
"blocks/warning",
|
||||
"blocks/caution";
|
||||
"blocks/caution",
|
||||
"blocks/special-state";
|
||||
|
|
|
@ -16,6 +16,10 @@
|
|||
background: $article-code-bg !important;
|
||||
font-size: .85em;
|
||||
font-weight: $medium;
|
||||
|
||||
p {
|
||||
background: $article-bg !important;
|
||||
}
|
||||
}
|
||||
|
||||
.node {
|
||||
|
|
|
@ -34,5 +34,10 @@
|
|||
vertical-align: middle;
|
||||
}
|
||||
}
|
||||
|
||||
// Remove max-width when only one button is present
|
||||
&:only-child {
|
||||
max-width: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,105 @@
|
|||
.block.special-state {
|
||||
@include gradient($grad-burningDusk);
|
||||
padding: 4px;
|
||||
border: none;
|
||||
border-radius: 25px !important;
|
||||
|
||||
.state-content {
|
||||
background: $article-bg;
|
||||
border-radius: 21px;
|
||||
padding: calc(1.65rem - 4px) calc(2rem - 4px) calc(.1rem + 4px) calc(2rem - 4px);
|
||||
|
||||
h4 {
|
||||
color: $article-heading;
|
||||
}
|
||||
|
||||
p {margin-bottom: 1rem;}
|
||||
|
||||
.expand-wrapper {
|
||||
border: none;
|
||||
margin: .5rem 0 1.5rem;
|
||||
}
|
||||
.expand {
|
||||
border: none;
|
||||
padding: 0;
|
||||
|
||||
.expand-content p {
|
||||
margin-left: 2rem;
|
||||
}
|
||||
|
||||
ul {
|
||||
|
||||
margin-top: -1rem;
|
||||
|
||||
&.feedback-channels {
|
||||
|
||||
padding: 0;
|
||||
margin: -1rem 0 1.5rem 2rem;
|
||||
list-style: none;
|
||||
|
||||
a {
|
||||
color: $article-heading;
|
||||
font-weight: $medium;
|
||||
position: relative;
|
||||
|
||||
&.discord:before {
|
||||
content: url('/svgs/discord.svg');
|
||||
display: inline-block;
|
||||
height: 1.1rem;
|
||||
width: 1.25rem;
|
||||
vertical-align: top;
|
||||
margin: 2px .65rem 0 0;
|
||||
}
|
||||
|
||||
&.community:before {
|
||||
content: "\e900";
|
||||
color: $article-heading;
|
||||
margin: 0 .65rem 0 0;
|
||||
font-size: 1.2rem;
|
||||
font-family: 'icomoon-v2';
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
&.slack:before {
|
||||
content: url('/svgs/slack.svg');
|
||||
display: inline-block;
|
||||
height: 1.1rem;
|
||||
width: 1.1rem;
|
||||
vertical-align: text-top;
|
||||
margin-right: .65rem;
|
||||
}
|
||||
|
||||
&.reddit:before {
|
||||
content: url('/svgs/reddit.svg');
|
||||
display: inline-block;
|
||||
height: 1.1rem;
|
||||
width: 1.2rem;
|
||||
vertical-align: top;
|
||||
margin: 2px .65rem 0 0;
|
||||
}
|
||||
|
||||
&::after {
|
||||
content: "\e90a";
|
||||
font-family: 'icomoon-v4';
|
||||
font-weight: bold;
|
||||
font-size: 1.3rem;
|
||||
display: inline-block;
|
||||
position: absolute;
|
||||
@include gradient($grad-burningDusk);
|
||||
background-clip: text;
|
||||
-webkit-text-fill-color: transparent;
|
||||
right: 0;
|
||||
transform: translateX(.25rem);
|
||||
opacity: 0;
|
||||
transition: transform .2s, opacity .2s;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
&::after {transform: translateX(1.5rem); opacity: 1;}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -23,6 +23,7 @@
|
|||
"layouts/syntax-highlighting",
|
||||
"layouts/algolia-search-overrides",
|
||||
"layouts/landing",
|
||||
"layouts/datetime",
|
||||
"layouts/error-page",
|
||||
"layouts/footer-widgets",
|
||||
"layouts/modals",
|
||||
|
|
|
@ -203,6 +203,12 @@ $article-btn-text-hover: $g20-white;
|
|||
$article-nav-icon-bg: $g5-pepper;
|
||||
$article-nav-acct-bg: $g3-castle;
|
||||
|
||||
// Datetime shortcode colors
|
||||
$current-timestamp-color: $g15-platinum;
|
||||
$current-date-color: $g15-platinum;
|
||||
$current-time-color: $g15-platinum;
|
||||
$enterprise-eol-date-color: $g15-platinum;
|
||||
|
||||
// Error Page Colors
|
||||
$error-page-btn: $b-pool;
|
||||
$error-page-btn-text: $g20-white;
|
||||
|
|
|
@ -203,6 +203,12 @@ $article-btn-text-hover: $g20-white !default;
|
|||
$article-nav-icon-bg: $g6-smoke !default;
|
||||
$article-nav-acct-bg: $g5-pepper !default;
|
||||
|
||||
// Datetime Colors
|
||||
$current-timestamp-color: $article-text !default;
|
||||
$current-date-color: $article-text !default;
|
||||
$current-time-color: $article-text !default;
|
||||
$enterprise-eol-date-color: $article-text !default;
|
||||
|
||||
// Error Page Colors
|
||||
$error-page-btn: $b-pool !default;
|
||||
$error-page-btn-text: $g20-white !default;
|
||||
|
|
|
@ -0,0 +1,145 @@
|
|||
#!/usr/bin/env node
|
||||
|
||||
/**
|
||||
* Script to generate GitHub Copilot instructions
|
||||
* for InfluxData documentation.
|
||||
*/
|
||||
import fs from 'fs';
|
||||
import path from 'path';
|
||||
import process from 'process';
|
||||
import { execSync } from 'child_process';
|
||||
|
||||
// Get the current file path and directory
|
||||
export { buildContributingInstructions };
|
||||
|
||||
(async () => {
|
||||
try {
|
||||
await buildContributingInstructions();
|
||||
} catch (error) {
|
||||
console.error('Error generating Copilot instructions:', error);
|
||||
}
|
||||
})();
|
||||
|
||||
/** Build instructions from CONTRIBUTING.md
|
||||
* This script reads CONTRIBUTING.md, formats it appropriately,
|
||||
* and saves it to .github/instructions/contributing.instructions.md
|
||||
* Includes optimization to reduce file size for better performance
|
||||
*/
|
||||
function buildContributingInstructions() {
|
||||
// Paths
|
||||
const contributingPath = path.join(process.cwd(), 'CONTRIBUTING.md');
|
||||
const instructionsDir = path.join(process.cwd(), '.github', 'instructions');
|
||||
const instructionsPath = path.join(
|
||||
instructionsDir,
|
||||
'contributing.instructions.md'
|
||||
);
|
||||
|
||||
// Ensure the instructions directory exists
|
||||
if (!fs.existsSync(instructionsDir)) {
|
||||
fs.mkdirSync(instructionsDir, { recursive: true });
|
||||
}
|
||||
|
||||
// Read the CONTRIBUTING.md file
|
||||
let content = fs.readFileSync(contributingPath, 'utf8');
|
||||
|
||||
// Optimize content by removing less critical sections for Copilot
|
||||
content = optimizeContentForContext(content);
|
||||
|
||||
// Format the content for Copilot instructions with applyTo attribute
|
||||
content = `---
|
||||
applyTo: "content/**/*.md, layouts/**/*.html"
|
||||
---
|
||||
|
||||
# Contributing instructions for InfluxData Documentation
|
||||
|
||||
## Purpose and scope
|
||||
|
||||
Help document InfluxData products
|
||||
by creating clear, accurate technical content with proper
|
||||
code examples, frontmatter, shortcodes, and formatting.
|
||||
|
||||
${content}`;
|
||||
|
||||
// Write the formatted content to the instructions file
|
||||
fs.writeFileSync(instructionsPath, content);
|
||||
|
||||
const fileSize = fs.statSync(instructionsPath).size;
|
||||
const sizeInKB = (fileSize / 1024).toFixed(1);
|
||||
console.log(
|
||||
`✅ Generated instructions at ${instructionsPath} (${sizeInKB}KB)`
|
||||
);
|
||||
|
||||
if (fileSize > 40000) {
|
||||
console.warn(
|
||||
`⚠️ Instructions file is large (${sizeInKB}KB > 40KB) and may impact performance`
|
||||
);
|
||||
}
|
||||
|
||||
// Add the file to git if it has changed
|
||||
try {
|
||||
const gitStatus = execSync(
|
||||
`git status --porcelain "${instructionsPath}"`
|
||||
).toString();
|
||||
if (gitStatus.trim()) {
|
||||
execSync(`git add "${instructionsPath}"`);
|
||||
console.log('✅ Added instructions file to git staging');
|
||||
}
|
||||
} catch (error) {
|
||||
console.warn('⚠️ Could not add instructions file to git:', error.message);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Optimize content for Copilot by removing or condensing less critical sections
|
||||
* while preserving essential documentation guidance
|
||||
*/
|
||||
function optimizeContentForContext(content) {
|
||||
// Remove or condense sections that are less relevant for context assistance
|
||||
const sectionsToRemove = [
|
||||
// Installation and setup sections (less relevant for writing docs)
|
||||
/### Install project dependencies[\s\S]*?(?=\n##|\n###|$)/g,
|
||||
/### Install Node\.js dependencies[\s\S]*?(?=\n##|\n###|$)/g,
|
||||
/### Install Docker[\s\S]*?(?=\n##|\n###|$)/g,
|
||||
/#### Build the test dependency image[\s\S]*?(?=\n##|\n###|$)/g,
|
||||
/### Install Visual Studio Code extensions[\s\S]*?(?=\n##|\n###|$)/g,
|
||||
/### Run the documentation locally[\s\S]*?(?=\n##|\n###|$)/g,
|
||||
|
||||
// Testing and CI/CD sections (important but can be condensed)
|
||||
/### Set up test scripts and credentials[\s\S]*?(?=\n##|\n###|$)/g,
|
||||
/#### Test shell and python code blocks[\s\S]*?(?=\n##|\n###|$)/g,
|
||||
/#### Troubleshoot tests[\s\S]*?(?=\n##|\n###|$)/g,
|
||||
/### Pytest collected 0 items[\s\S]*?(?=\n##|\n###|$)/g,
|
||||
|
||||
// Long code examples that can be referenced elsewhere
|
||||
/```[\s\S]{500,}?```/g,
|
||||
|
||||
// Repetitive examples
|
||||
/#### Example[\s\S]*?(?=\n####|\n###|\n##|$)/g,
|
||||
];
|
||||
|
||||
// Remove identified sections
|
||||
sectionsToRemove.forEach((regex) => {
|
||||
content = content.replace(regex, '');
|
||||
});
|
||||
|
||||
// Condense whitespace
|
||||
content = content.replace(/\n{3,}/g, '\n\n');
|
||||
|
||||
// Remove HTML comments
|
||||
content = content.replace(/<!--[\s\S]*?-->/g, '');
|
||||
|
||||
// Shorten repetitive content
|
||||
content = content.replace(/(\{%[^%]+%\})[\s\S]*?\1/g, (match) => {
|
||||
// If it's a long repeated pattern, show it once with a note
|
||||
if (match.length > 200) {
|
||||
const firstOccurrence = match.split('\n\n')[0];
|
||||
return (
|
||||
firstOccurrence +
|
||||
'\n\n[Similar patterns apply - see full CONTRIBUTING.md for complete examples]'
|
||||
);
|
||||
}
|
||||
return match;
|
||||
});
|
||||
|
||||
return content;
|
||||
}
|
45
compose.yaml
45
compose.yaml
|
@ -301,15 +301,49 @@ services:
|
|||
working_dir: /app
|
||||
influxdb3-core:
|
||||
container_name: influxdb3-core
|
||||
image: quay.io/influxdb/influxdb3-core:latest
|
||||
image: influxdb:3-core
|
||||
ports:
|
||||
- 8181:8181
|
||||
- 8282:8181
|
||||
command:
|
||||
- influxdb3
|
||||
- serve
|
||||
- --node-id=sensors_node0
|
||||
- --node-id=node0
|
||||
- --log-filter=debug
|
||||
- --object-store=file
|
||||
- --data-dir=/var/lib/influxdb3
|
||||
- --data-dir=/var/lib/influxdb3/data
|
||||
- --plugin-dir=/var/lib/influxdb3/plugins
|
||||
volumes:
|
||||
- type: bind
|
||||
source: test/.influxdb3/core/data
|
||||
target: /var/lib/influxdb3/data
|
||||
- type: bind
|
||||
source: test/.influxdb3/core/plugins
|
||||
target: /var/lib/influxdb3/plugins
|
||||
influxdb3-enterprise:
|
||||
container_name: influxdb3-enterprise
|
||||
image: influxdb:3-enterprise
|
||||
ports:
|
||||
- 8181:8181
|
||||
# Change the INFLUXDB3_LICENSE_EMAIL environment variable to your email address. You can also set it in a `.env` file in the same directory as this compose file. Docker Compose automatically loads the .env file.
|
||||
# The license email option is only used the first time you run the container; you can't change the license email after the first run.
|
||||
# The server stores the license in the data directory in the object store and the license is associated with the cluster ID and email.
|
||||
command:
|
||||
- influxdb3
|
||||
- serve
|
||||
- --node-id=node0
|
||||
- --cluster-id=cluster0
|
||||
- --log-filter=debug
|
||||
- --object-store=file
|
||||
- --data-dir=/var/lib/influxdb3/data
|
||||
- --plugin-dir=/var/lib/influxdb3/plugins
|
||||
- --license-email=${INFLUXDB3_LICENSE_EMAIL}
|
||||
volumes:
|
||||
- type: bind
|
||||
source: test/.influxdb3/enterprise/data
|
||||
target: /var/lib/influxdb3/data
|
||||
- type: bind
|
||||
source: test/.influxdb3/enterprise/plugins
|
||||
target: /var/lib/influxdb3/plugins
|
||||
telegraf-pytest:
|
||||
container_name: telegraf-pytest
|
||||
image: influxdata/docs-pytest
|
||||
|
@ -448,6 +482,9 @@ services:
|
|||
- type: bind
|
||||
source: ./content
|
||||
target: /app/content
|
||||
- type: bind
|
||||
source: ./CONTRIBUTING.md
|
||||
target: /app/CONTRIBUTING.md
|
||||
volumes:
|
||||
test-content:
|
||||
cloud-tmp:
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
baseURL: 'https://docs.influxdata.com/'
|
||||
baseURL: https://docs.influxdata.com/
|
||||
languageCode: en-us
|
||||
title: InfluxDB Documentation
|
||||
|
||||
|
@ -49,8 +49,52 @@ privacy:
|
|||
youtube:
|
||||
disable: false
|
||||
privacyEnhanced: true
|
||||
|
||||
outputFormats:
|
||||
json:
|
||||
mediaType: application/json
|
||||
baseName: pages
|
||||
isPlainText: true
|
||||
|
||||
# Asset processing configuration for development
|
||||
build:
|
||||
# Ensure Hugo correctly processes JavaScript modules
|
||||
jsConfig:
|
||||
nodeEnv: "development"
|
||||
# Development asset processing
|
||||
writeStats: false
|
||||
useResourceCacheWhen: "fallback"
|
||||
noJSConfigInAssets: false
|
||||
|
||||
# Asset processing configuration
|
||||
assetDir: "assets"
|
||||
|
||||
module:
|
||||
mounts:
|
||||
- source: assets
|
||||
target: assets
|
||||
- source: node_modules
|
||||
target: assets/node_modules
|
||||
|
||||
# Environment parameters
|
||||
params:
|
||||
env: development
|
||||
environment: development
|
||||
|
||||
# Configure the server for development
|
||||
server:
|
||||
port: 1313
|
||||
baseURL: 'http://localhost:1313/'
|
||||
watchChanges: true
|
||||
disableLiveReload: false
|
||||
|
||||
# Ignore specific warning logs
|
||||
ignoreLogs:
|
||||
- warning-goldmark-raw-html
|
||||
|
||||
# Disable minification for development
|
||||
minify:
|
||||
disableJS: true
|
||||
disableCSS: true
|
||||
disableHTML: true
|
||||
minifyOutput: false
|
|
@ -0,0 +1,40 @@
|
|||
# Production overrides for CI/CD builds
|
||||
baseURL: 'https://docs.influxdata.com/'
|
||||
|
||||
# Production environment parameters
|
||||
params:
|
||||
env: production
|
||||
environment: production
|
||||
|
||||
# Enable minification for production
|
||||
minify:
|
||||
disableJS: false
|
||||
disableCSS: false
|
||||
disableHTML: false
|
||||
minifyOutput: true
|
||||
|
||||
# Production asset processing
|
||||
build:
|
||||
writeStats: false
|
||||
useResourceCacheWhen: "fallback"
|
||||
buildOptions:
|
||||
sourcemap: false
|
||||
target: "es2015"
|
||||
|
||||
# Asset processing configuration
|
||||
assetDir: "assets"
|
||||
|
||||
# Mount assets for production
|
||||
module:
|
||||
mounts:
|
||||
- source: assets
|
||||
target: assets
|
||||
- source: node_modules
|
||||
target: assets/node_modules
|
||||
|
||||
# Disable development server settings
|
||||
server: {}
|
||||
|
||||
# Suppress the warning mentioned in the error
|
||||
ignoreLogs:
|
||||
- 'warning-goldmark-raw-html'
|
|
@ -0,0 +1,17 @@
|
|||
build:
|
||||
writeStats: false
|
||||
useResourceCacheWhen: "fallback"
|
||||
buildOptions:
|
||||
sourcemap: false
|
||||
target: "es2015"
|
||||
minify:
|
||||
disableJS: false
|
||||
disableCSS: false
|
||||
disableHTML: false
|
||||
minifyOutput: true
|
||||
params:
|
||||
env: production
|
||||
environment: production
|
||||
server: {
|
||||
disableLiveReload: true
|
||||
}
|
|
@ -0,0 +1,19 @@
|
|||
baseURL: https://test2.docs.influxdata.com/
|
||||
build:
|
||||
writeStats: false
|
||||
useResourceCacheWhen: "fallback"
|
||||
buildOptions:
|
||||
sourcemap: false
|
||||
target: "es2015"
|
||||
minify:
|
||||
disableJS: false
|
||||
disableCSS: false
|
||||
disableHTML: false
|
||||
minifyOutput: true
|
||||
params:
|
||||
env: staging
|
||||
environment: staging
|
||||
server: {
|
||||
disableLiveReload: true
|
||||
}
|
||||
|
|
@ -22,7 +22,7 @@ We recommend the following design guidelines for most use cases:
|
|||
|
||||
Your queries should guide what data you store in [tags](/enterprise_influxdb/v1/concepts/glossary/#tag) and what you store in [fields](/enterprise_influxdb/v1/concepts/glossary/#field) :
|
||||
|
||||
- Store commonly queried and grouping ([`group()`](/flux/v0.x/stdlib/universe/group) or [`GROUP BY`](/enterprise_influxdb/v1/query_language/explore-data/#group-by-tags)) metadata in tags.
|
||||
- Store commonly queried and grouping ([`group()`](/flux/v0/stdlib/universe/group) or [`GROUP BY`](/enterprise_influxdb/v1/query_language/explore-data/#group-by-tags)) metadata in tags.
|
||||
- Store data in fields if each data point contains a different value.
|
||||
- Store numeric values as fields ([tag values](/enterprise_influxdb/v1/concepts/glossary/#tag-value) only support string values).
|
||||
|
||||
|
|
|
@ -6,6 +6,15 @@ menu:
|
|||
enterprise_influxdb_v1:
|
||||
name: Tools
|
||||
weight: 72
|
||||
aliases:
|
||||
- /enterprise_influxdb/v1/tools/flux-vscode/
|
||||
prepend: |
|
||||
> [!Important]
|
||||
> #### Flux VS Code extension no longer available
|
||||
>
|
||||
> The `vsflux` extension is no longer available in the Visual Studio Marketplace.
|
||||
> `vsflux` and the `flux-lsp` Flux Language Server Protocol plugin are no longer maintained.
|
||||
> Their repositories have been archived and are no longer receiving updates.
|
||||
---
|
||||
|
||||
Use the following tools to work with InfluxDB Enterprise:
|
||||
|
|
|
@ -10,6 +10,14 @@ menu:
|
|||
enterprise_influxdb_v1:
|
||||
name: Flux VS Code extension
|
||||
parent: Tools
|
||||
draft: true
|
||||
prepend: |
|
||||
> [!Important]
|
||||
> #### Flux VS Code extension no longer available
|
||||
>
|
||||
> The `vsflux` extension is no longer available in the Visual Studio Marketplace.
|
||||
> `vsflux` and the `flux-lsp` Flux Language Server Protocol plugin are no longer maintained.
|
||||
> Their repositories have been archived and are no longer receiving updates.
|
||||
---
|
||||
|
||||
The [Flux Visual Studio Code (VS Code) extension](https://marketplace.visualstudio.com/items?itemName=influxdata.flux)
|
||||
|
|
|
@ -6,14 +6,14 @@ related:
|
|||
- /influxdb/v2/write-data/
|
||||
- /influxdb/v2/write-data/quick-start
|
||||
- https://influxdata.com, This is an external link
|
||||
draft: true
|
||||
test_only: true # Custom parameter to indicate test-only content
|
||||
---
|
||||
|
||||
This is a paragraph. Lorem ipsum dolor ({{< icon "trash" "v2" >}}) sit amet, consectetur adipiscing elit. Nunc rutrum, metus id scelerisque euismod, erat ante suscipit nibh, ac congue enim risus id est. Etiam tristique nisi et tristique auctor. Morbi eu bibendum erat. Sed ullamcorper, dui id lobortis efficitur, mauris odio pharetra neque, vel tempor odio dolor blandit justo.
|
||||
|
||||
[Ref link][foo]
|
||||
|
||||
[foo]: https://docs.influxadata.com
|
||||
[foo]: https://docs.influxdata.com
|
||||
|
||||
This is **bold** text. This is _italic_ text. This is _**bold and italic**_.
|
||||
|
||||
|
@ -1267,3 +1267,106 @@ This is small tab 2.4 content.
|
|||
{{% /tab-content %}}
|
||||
|
||||
{{< /tabs-wrapper >}}
|
||||
|
||||
## Group key demo
|
||||
|
||||
Used to demonstrate Flux group keys
|
||||
|
||||
{{< tabs-wrapper >}}
|
||||
{{% tabs "small" %}}
|
||||
[Input](#)
|
||||
[Output](#)
|
||||
<span class="tab-view-output">Click to view output</span>
|
||||
{{% /tabs %}}
|
||||
{{% tab-content %}}
|
||||
|
||||
The following data is output from the last `filter()` and piped forward into `group()`:
|
||||
|
||||
> [!Note]
|
||||
> `_start` and `_stop` columns have been omitted.
|
||||
|
||||
{{% flux/group-key "[_measurement=home, room=Kitchen, _field=hum]" true %}}
|
||||
|
||||
| _time | _measurement | room | _field | _value |
|
||||
| :------------------- | :----------- | :---------- | :----- | :----- |
|
||||
| 2022-01-01T08:00:00Z | home | Kitchen | hum | 35.9 |
|
||||
| 2022-01-01T09:00:00Z | home | Kitchen | hum | 36.2 |
|
||||
| 2022-01-01T10:00:00Z | home | Kitchen | hum | 36.1 |
|
||||
|
||||
{{% flux/group-key "[_measurement=home, room=Living Room, _field=hum]" true %}}
|
||||
|
||||
| _time | _measurement | room | _field | _value |
|
||||
| :------------------- | :----------- | :---------- | :----- | :----- |
|
||||
| 2022-01-01T08:00:00Z | home | Living Room | hum | 35.9 |
|
||||
| 2022-01-01T09:00:00Z | home | Living Room | hum | 35.9 |
|
||||
| 2022-01-01T10:00:00Z | home | Living Room | hum | 36 |
|
||||
|
||||
{{% flux/group-key "[_measurement=home, room=Kitchen, _field=temp]" true %}}
|
||||
|
||||
| _time | _measurement | room | _field | _value |
|
||||
| :------------------- | :----------- | :---------- | :----- | :----- |
|
||||
| 2022-01-01T08:00:00Z | home | Kitchen | temp | 21 |
|
||||
| 2022-01-01T09:00:00Z | home | Kitchen | temp | 23 |
|
||||
| 2022-01-01T10:00:00Z | home | Kitchen | temp | 22.7 |
|
||||
|
||||
{{% flux/group-key "[_measurement=home, room=Living Room, _field=temp]" true %}}
|
||||
|
||||
| _time | _measurement | room | _field | _value |
|
||||
| :------------------- | :----------- | :---------- | :----- | :----- |
|
||||
| 2022-01-01T08:00:00Z | home | Living Room | temp | 21.1 |
|
||||
| 2022-01-01T09:00:00Z | home | Living Room | temp | 21.4 |
|
||||
| 2022-01-01T10:00:00Z | home | Living Room | temp | 21.8 |
|
||||
|
||||
{{% /tab-content %}}
|
||||
{{% tab-content %}}
|
||||
|
||||
When grouped by `_field`, all rows with the `temp` field will be in one table
|
||||
and all the rows with the `hum` field will be in another.
|
||||
`_measurement` and `room` columns no longer affect how rows are grouped.
|
||||
|
||||
{{% note %}}
|
||||
`_start` and `_stop` columns have been omitted.
|
||||
{{% /note %}}
|
||||
|
||||
{{% flux/group-key "[_field=hum]" true %}}
|
||||
|
||||
| _time | _measurement | room | _field | _value |
|
||||
| :------------------- | :----------- | :---------- | :----- | :----- |
|
||||
| 2022-01-01T08:00:00Z | home | Kitchen | hum | 35.9 |
|
||||
| 2022-01-01T09:00:00Z | home | Kitchen | hum | 36.2 |
|
||||
| 2022-01-01T10:00:00Z | home | Kitchen | hum | 36.1 |
|
||||
| 2022-01-01T08:00:00Z | home | Living Room | hum | 35.9 |
|
||||
| 2022-01-01T09:00:00Z | home | Living Room | hum | 35.9 |
|
||||
| 2022-01-01T10:00:00Z | home | Living Room | hum | 36 |
|
||||
|
||||
{{% flux/group-key "[_field=temp]" true %}}
|
||||
|
||||
| _time | _measurement | room | _field | _value |
|
||||
| :------------------- | :----------- | :---------- | :----- | :----- |
|
||||
| 2022-01-01T08:00:00Z | home | Kitchen | temp | 21 |
|
||||
| 2022-01-01T09:00:00Z | home | Kitchen | temp | 23 |
|
||||
| 2022-01-01T10:00:00Z | home | Kitchen | temp | 22.7 |
|
||||
| 2022-01-01T08:00:00Z | home | Living Room | temp | 21.1 |
|
||||
| 2022-01-01T09:00:00Z | home | Living Room | temp | 21.4 |
|
||||
| 2022-01-01T10:00:00Z | home | Living Room | temp | 21.8 |
|
||||
|
||||
{{% /tab-content %}}
|
||||
{{< /tabs-wrapper >}}
|
||||
|
||||
## datetime/current-timestamp shortcode
|
||||
|
||||
### Default usage
|
||||
|
||||
{{< datetime/current-timestamp >}}
|
||||
|
||||
### Format YYYY-MM-DD HH:mm:ss
|
||||
|
||||
{{< datetime/current-timestamp format="YYYY-MM-DD HH:mm:ss" >}}
|
||||
|
||||
### Format with UTC timezone
|
||||
|
||||
{{< datetime/current-timestamp format="YYYY-MM-DD HH:mm:ss" timezone="UTC" >}}
|
||||
|
||||
### Format with America/New_York timezone
|
||||
|
||||
{{< datetime/current-timestamp format="YYYY-MM-DD HH:mm:ss" timezone="America/New_York" >}}
|
||||
|
|
|
@ -433,7 +433,7 @@ representative of the Flux SPEC.
|
|||
details.
|
||||
- Add tagging support to Flux tests.
|
||||
- Add new function [`experimental.catch()`](/flux/v0/stdlib/experimental/catch/).
|
||||
- Add new function [`testing.shouldError()`](/flux/v0.x/stdlib/testing/shoulderror/).
|
||||
- Add new function [`testing.shouldError()`](/flux/v0/stdlib/testing/shoulderror/).
|
||||
|
||||
### Bug fixes
|
||||
|
||||
|
|
|
@ -12,8 +12,8 @@ menu:
|
|||
parent: Account management
|
||||
name: View data usage
|
||||
related:
|
||||
- /flux/v0.x/stdlib/experimental/usage/from/
|
||||
- /flux/v0.x/stdlib/experimental/usage/limits/
|
||||
- /flux/v0/stdlib/experimental/usage/from/
|
||||
- /flux/v0/stdlib/experimental/usage/limits/
|
||||
alt_links:
|
||||
cloud-serverless: /influxdb3/cloud-serverless/admin/billing/data-usage/
|
||||
---
|
||||
|
|
|
@ -9,8 +9,8 @@ menu:
|
|||
parent: Account management
|
||||
name: Adjustable quotas and limits
|
||||
related:
|
||||
- /flux/v0.x/stdlib/experimental/usage/from/
|
||||
- /flux/v0.x/stdlib/experimental/usage/limits/
|
||||
- /flux/v0/stdlib/experimental/usage/from/
|
||||
- /flux/v0/stdlib/experimental/usage/limits/
|
||||
- /influxdb/cloud/write-data/best-practices/resolve-high-cardinality/
|
||||
alt_links:
|
||||
cloud-serverless: /influxdb3/cloud-serverless/admin/billing/limits/
|
||||
|
@ -97,7 +97,7 @@ Combine delete predicate expressions (if possible) into a single request. Influx
|
|||
|
||||
The {{< product-name >}} UI displays a notification message when service quotas or limits are exceeded. The error messages correspond with the relevant [API error responses](#api-error-responses).
|
||||
|
||||
Errors can also be viewed in the [Usage page](/influxdb/cloud/account-management/data-usage/) under **Limit Events**, e.g. `event_type_limited_query`, `event_type_limited_write`,`event_type_limited_cardinality`, or `event_type_limited_delete_rate`.
|
||||
Errors can also be viewed in the [Usage page](/influxdb/cloud/account-management/data-usage/) under **Limit Events**, for example: `event_type_limited_query`, `event_type_limited_write`,`event_type_limited_cardinality`, or `event_type_limited_delete_rate`.
|
||||
|
||||
## API error responses
|
||||
|
||||
|
|
|
@ -40,7 +40,7 @@ To replicate the state of an organization:
|
|||
### Write data with Flux
|
||||
Perform a query to return all specified data.
|
||||
Write results directly to a bucket in the new organization with the Flux
|
||||
[`to()` function](/flux/v0.x/stdlib/influxdata/influxdb/to/).
|
||||
[`to()` function](/flux/v0/stdlib/influxdata/influxdb/to/).
|
||||
|
||||
{{% note %}}
|
||||
If writes are prevented by rate limiting,
|
||||
|
|
|
@ -25,7 +25,7 @@ types of demo data that let you explore and familiarize yourself with InfluxDB C
|
|||
{{% note %}}
|
||||
#### Free to use and read-only
|
||||
- InfluxDB Cloud demo data buckets are **free to use** and are **_not_ subject to
|
||||
[Free Plan rate limits](influxdb/cloud/account-management/limits/#free-plan-rate-limits) rate limits**.
|
||||
[Free Plan rate limits](/influxdb/cloud/account-management/limits/#free-plan-rate-limits) rate limits**.
|
||||
- Demo data buckets are **read-only**. You cannot write data into demo data buckets.
|
||||
{{% /note %}}
|
||||
|
||||
|
|
|
@ -13,7 +13,7 @@ prepend: |
|
|||
> [Use InfluxQL to query InfluxDB](/influxdb/cloud/query-data/influxql/).
|
||||
> For information about manually converting InfluxQL queries to Flux, see:
|
||||
>
|
||||
> - [Get started with Flux](/flux/v0.x/get-started/)
|
||||
> - [Get started with Flux](/flux/v0/get-started/)
|
||||
> - [Query data with Flux](/influxdb/cloud/query-data/flux/)
|
||||
> - [Migrate continuous queries to Flux tasks](/influxdb/cloud/upgrade/v1-to-cloud/migrate-cqs/)
|
||||
source: /shared/influxdb-v2/reference/cli/influx/transpile/_index.md
|
||||
|
|
|
@ -14,6 +14,14 @@ aliases:
|
|||
InfluxDB Cloud updates occur frequently. Find a compilation of recent updates below.
|
||||
To find information about the latest Flux updates in InfluxDB Cloud, see [Flux release notes](/influxdb/cloud/reference/release-notes/flux/).
|
||||
|
||||
## April 2025
|
||||
|
||||
### Flux VS Code extension no longer maintained
|
||||
|
||||
`vsflux` is no longer available in the Visual Studio Marketplace.
|
||||
The `vsflux` Visual Studio Code extension and the `flux-lsp` Flux Language Server Protocol plugin are no longer maintained.
|
||||
Their repositories have been archived and are no longer receiving updates.
|
||||
|
||||
## October 2022
|
||||
|
||||
### Custom data retention periods
|
||||
|
@ -180,7 +188,7 @@ Now, you can add the following buckets with sample data to your notebooks:
|
|||
|
||||
### Add ability to share notebooks
|
||||
|
||||
Add ability to [share a notebook](/influxdb/cloud/tools/notebooks/manage-notebooks/#share-a-notebook) in the the InfluxDB Cloud notebook UI.
|
||||
Add ability to [share a notebook](/influxdb/cloud/tools/notebooks/manage-notebooks/#share-a-notebook) in the InfluxDB Cloud notebook UI.
|
||||
|
||||
## October 2021
|
||||
|
||||
|
@ -201,7 +209,7 @@ Refresh the look and feel of InfluxDB Cloud UI. The updated icons, fonts, and la
|
|||
|
||||
### Flux update
|
||||
|
||||
Upgrade to [Flux v0.139](/flux/v0.x/release-notes/).
|
||||
Upgrade to [Flux v0.139](/flux/v0/release-notes/).
|
||||
|
||||
### Telegraf configuration UI
|
||||
|
||||
|
@ -339,7 +347,7 @@ Install and customize any [InfluxDB community template](https://github.com/influ
|
|||
|
||||
## Features
|
||||
- **InfluxDB OSS 2.0 alpha-17** –
|
||||
_See the [alpha-17 release notes](/influxdb/v2%2E0/reference/release-notes/influxdb/#v200-alpha17) for details._
|
||||
_See the [alpha-17 release notes](/influxdb/v2/reference/release-notes/influxdb/#v200-alpha17) for details._
|
||||
- Alerts and Notifications to Slack (Free Plan), PagerDuty and HTTP (Usage-based Plan).
|
||||
- Rate limiting on cardinality for Free Plan.
|
||||
- Billing notifications.
|
||||
|
@ -351,7 +359,7 @@ Install and customize any [InfluxDB community template](https://github.com/influ
|
|||
### Features
|
||||
|
||||
- **InfluxDB OSS 2.0 alpha-15** –
|
||||
_See the [alpha-9 release notes](/influxdb/v2%2E0/reference/release-notes/influxdb/#v200-alpha15) for details._
|
||||
_See the [alpha-9 release notes](/influxdb/v2/reference/release-notes/influxdb/#v200-alpha15) for details._
|
||||
- Usage-based Plan.
|
||||
- Adjusted Free Plan rate limits.
|
||||
- Timezone selection in the user interface.
|
||||
|
@ -378,7 +386,7 @@ Install and customize any [InfluxDB community template](https://github.com/influ
|
|||
### Features
|
||||
|
||||
- **InfluxDB OSS 2.0 alpha-9** –
|
||||
_See the [alpha-9 release notes](/influxdb/v2%2E0/reference/release-notes/influxdb/#v200-alpha9) for details._
|
||||
_See the [alpha-9 release notes](/influxdb/v2/reference/release-notes/influxdb/#v200-alpha9) for details._
|
||||
|
||||
### Bug fixes
|
||||
|
||||
|
@ -395,7 +403,7 @@ Install and customize any [InfluxDB community template](https://github.com/influ
|
|||
### Features
|
||||
|
||||
- **InfluxDB OSS 2.0 alpha-7** –
|
||||
_See the [alpha-7 release notes](/influxdb/v2%2E0/reference/release-notes/influxdb/#v200-alpha7) for details._
|
||||
_See the [alpha-7 release notes](/influxdb/v2/reference/release-notes/influxdb/#v200-alpha7) for details._
|
||||
|
||||
### Bug fixes
|
||||
|
||||
|
|
|
@ -136,8 +136,8 @@ To see all available `influx` commands, type `influx -h` or check out [influx -
|
|||
|
||||
Click one of the following buttons to download and install the `influx` CLI appropriate for your chipset.
|
||||
|
||||
<a class="btn download" href="https://dl.influxdata.com/influxdb/releases/influxdb2-client-{{< latest-cli >}}-linux-amd64.tar.gz" download >influx CLI (amd64)</a>
|
||||
<a class="btn download" href="https://dl.influxdata.com/influxdb/releases/influxdb2-client-{{< latest-cli >}}-linux-arm64.tar.gz" download >influx CLI (arm)</a>
|
||||
<a class="btn download" href="https://dl.influxdata.com/influxdb/releases/influxdb2-client-{{< latest-patch cli=true >}}-linux-amd64.tar.gz" download >influx CLI (amd64)</a>
|
||||
<a class="btn download" href="https://dl.influxdata.com/influxdb/releases/influxdb2-client-{{< latest-patch cli=true >}}-linux-arm64.tar.gz" download >influx CLI (arm)</a>
|
||||
|
||||
#### Step 2: Unpackage the influx binary
|
||||
|
||||
|
@ -145,7 +145,7 @@ Click one of the following buttons to download and install the `influx` CLI appr
|
|||
|
||||
```sh
|
||||
# Unpackage contents to the current working directory
|
||||
tar xvfz influxdb2-client-{{< latest-cli >}}-linux-amd64.tar.gz
|
||||
tar xvfz influxdb2-client-{{< latest-patch cli=true >}}-linux-amd64.tar.gz
|
||||
```
|
||||
|
||||
#### Step 3: (Optional) Place the binary in your $PATH
|
||||
|
@ -157,7 +157,7 @@ prefix the executable with `./` to run in place. If the binary is on your $PATH,
|
|||
|
||||
```sh
|
||||
# Copy the influx and influxd binary to your $PATH
|
||||
sudo cp influxdb2-client-{{< latest-cli >}}-linux-amd64/influx /usr/local/bin/
|
||||
sudo cp influxdb2-client-{{< latest-patch cli=true >}}-linux-amd64/influx /usr/local/bin/
|
||||
```
|
||||
|
||||
{{% note %}}
|
||||
|
|
|
@ -6,6 +6,15 @@ weight: 13
|
|||
menu:
|
||||
influxdb_cloud:
|
||||
name: Tools & integrations
|
||||
aliases:
|
||||
- /influxdb/cloud/tools/flux-vscode/
|
||||
prepend: |
|
||||
> [!Important]
|
||||
> #### Flux VS Code extension no longer available
|
||||
>
|
||||
> The `vsflux` extension is no longer available in the Visual Studio Marketplace.
|
||||
> `vsflux` and the `flux-lsp` Flux Language Server Protocol plugin are no longer maintained.
|
||||
> Their repositories have been archived and are no longer receiving updates.
|
||||
---
|
||||
|
||||
{{< children >}}
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue