Compare commits
64 Commits
@nhost/das
...
storage@0.
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
32fe5bec57 | ||
|
|
afffb887d0 | ||
|
|
f542e3a57b | ||
|
|
3644a77b2d | ||
|
|
855b5fc081 | ||
|
|
9dab347348 | ||
|
|
279d952c4c | ||
|
|
6c044458ca | ||
|
|
a7fd13e384 | ||
|
|
30f9c7498b | ||
|
|
d015790556 | ||
|
|
ab6e72ffed | ||
|
|
03b6fd2d93 | ||
|
|
fa6d2e6ae1 | ||
|
|
96c377357e | ||
|
|
561b108900 | ||
|
|
7fa7ef2715 | ||
|
|
5b98f4ece2 | ||
|
|
dc7d3fb4cc | ||
|
|
84ebe77b27 | ||
|
|
effb2ae17f | ||
|
|
d15717b67a | ||
|
|
a3c7f89eda | ||
|
|
6692e0dfc0 | ||
|
|
8541165781 | ||
|
|
5cd5ebbc65 | ||
|
|
5066ef708a | ||
|
|
a6a378c5a6 | ||
|
|
a3a3cf205d | ||
|
|
3fd2e63db3 | ||
|
|
f5956f1b2e | ||
|
|
f3b397b0d8 | ||
|
|
b7940087ee | ||
|
|
3dae655858 | ||
|
|
2aa269734b | ||
|
|
bc91836f83 | ||
|
|
6d8b243571 | ||
|
|
c9967b1a6d | ||
|
|
7f72aadff9 | ||
|
|
8faf9565bb | ||
|
|
7ac3f12852 | ||
|
|
184a3ed190 | ||
|
|
372c4e32d4 | ||
|
|
a68d261d8e | ||
|
|
55bda3f56b | ||
|
|
2311e1dd77 | ||
|
|
824ee142c4 | ||
|
|
c662d063a7 | ||
|
|
b518132349 | ||
|
|
b677d3768f | ||
|
|
51ec151752 | ||
|
|
223322d654 | ||
|
|
add2c20c95 | ||
|
|
961bc5feea | ||
|
|
0ca89974b9 | ||
|
|
e8d52859a3 | ||
|
|
67740ebe3d | ||
|
|
d6f7b01aee | ||
|
|
0fc65df78d | ||
|
|
52e3db7f61 | ||
|
|
235449d68c | ||
|
|
323834d212 | ||
|
|
f7bd250f73 | ||
|
|
579f9dbf31 |
2
.github/ISSUE_TEMPLATE/bug_report.md
vendored
2
.github/ISSUE_TEMPLATE/bug_report.md
vendored
@@ -7,6 +7,8 @@ assignees: ''
|
||||
|
||||
---
|
||||
|
||||
> **Note:** Bug reports that are clearly AI-generated will not be accepted and will be closed immediately. Please write your bug report in your own words.
|
||||
|
||||
**Describe the bug**
|
||||
A clear and concise description of what the bug is.
|
||||
|
||||
|
||||
2
.github/ISSUE_TEMPLATE/feature_request.md
vendored
2
.github/ISSUE_TEMPLATE/feature_request.md
vendored
@@ -7,6 +7,8 @@ assignees: ''
|
||||
|
||||
---
|
||||
|
||||
> **Note:** Feature requests that are clearly AI-generated will not be accepted and will be closed immediately. Please write your feature request in your own words.
|
||||
|
||||
**Is your feature request related to a problem? Please describe.**
|
||||
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
|
||||
|
||||
|
||||
3
.github/PULL_REQUEST_TEMPLATE.md
vendored
3
.github/PULL_REQUEST_TEMPLATE.md
vendored
@@ -8,6 +8,8 @@
|
||||
|
||||
--- Delete everything below this line before submitting your PR ---
|
||||
|
||||
> **Note on AI-assisted contributions:** Contributions with the help of AI are permitted, but you are ultimately responsible for the quality of your submission and for ensuring it follows our contributing guidelines. **The PR description must be written in your own words and be clear and concise**. Please ensure you remove any superfluous code comments introduced by AI tools before submitting. PRs that clearly violate this rule will be closed without further review.
|
||||
|
||||
### PR title format
|
||||
|
||||
The PR title must follow the following pattern:
|
||||
@@ -30,6 +32,7 @@ Where `PKG` is:
|
||||
- `deps`: For changes to dependencies
|
||||
- `docs`: For changes to the documentation
|
||||
- `examples`: For changes to the examples
|
||||
- `internal/lib`: For changes to Nhost's common libraries (internal)
|
||||
- `mintlify-openapi`: For changes to the Mintlify OpenAPI tool
|
||||
- `nhost-js`: For changes to the Nhost JavaScript SDK
|
||||
- `nixops`: For changes to the NixOps
|
||||
|
||||
@@ -17,7 +17,7 @@ runs:
|
||||
|
||||
# Define valid types and packages
|
||||
VALID_TYPES="feat|fix|chore"
|
||||
VALID_PKGS="auth|ci|cli|codegen|dashboard|deps|docs|examples|mintlify-openapi|nhost-js|nixops|storage"
|
||||
VALID_PKGS="auth|ci|cli|codegen|dashboard|deps|docs|examples|internal\/lib|mintlify-openapi|nhost-js|nixops|storage"
|
||||
|
||||
# Check if title matches the pattern TYPE(PKG): SUMMARY
|
||||
if [[ ! "$PR_TITLE" =~ ^(${VALID_TYPES})\((${VALID_PKGS})\):\ .+ ]]; then
|
||||
|
||||
8
.github/workflows/auth_checks.yaml
vendored
8
.github/workflows/auth_checks.yaml
vendored
@@ -1,8 +1,7 @@
|
||||
---
|
||||
name: "auth: check and build"
|
||||
on:
|
||||
# pull_request_target:
|
||||
pull_request:
|
||||
pull_request_target:
|
||||
paths:
|
||||
- '.github/workflows/auth_checks.yaml'
|
||||
- '.github/workflows/wf_check.yaml'
|
||||
@@ -18,6 +17,7 @@ on:
|
||||
- '.golangci.yaml'
|
||||
- 'go.mod'
|
||||
- 'go.sum'
|
||||
- 'internal/lib/**'
|
||||
- 'vendor/**'
|
||||
|
||||
# auth
|
||||
@@ -49,7 +49,7 @@ jobs:
|
||||
with:
|
||||
NAME: auth
|
||||
PATH: services/auth
|
||||
GIT_REF: ${{ github.sha }}
|
||||
GIT_REF: ${{ github.event_name == 'pull_request_target' && github.event.pull_request.head.sha || github.sha }}
|
||||
|
||||
secrets:
|
||||
AWS_ACCOUNT_ID: ${{ secrets.AWS_PRODUCTION_CORE_ACCOUNT_ID }}
|
||||
@@ -64,7 +64,7 @@ jobs:
|
||||
with:
|
||||
NAME: auth
|
||||
PATH: services/auth
|
||||
GIT_REF: ${{ github.sha }}
|
||||
GIT_REF: ${{ github.event_name == 'pull_request_target' && github.event.pull_request.head.sha || github.sha }}
|
||||
VERSION: 0.0.0-dev # we use a fixed version here to avoid unnecessary rebuilds
|
||||
DOCKER: true
|
||||
secrets:
|
||||
|
||||
2
.github/workflows/ci_update_changelog.yaml
vendored
2
.github/workflows/ci_update_changelog.yaml
vendored
@@ -40,7 +40,7 @@ jobs:
|
||||
cd ${{ matrix.project }}
|
||||
TAG_NAME=$(make release-tag-name)
|
||||
VERSION=$(nix develop .\#cliff -c make changelog-next-version)
|
||||
if git tag | grep -q "$TAG_NAME@$VERSION"; then
|
||||
if git tag | grep -qx "$TAG_NAME@$VERSION"; then
|
||||
echo "Tag $TAG_NAME@$VERSION already exists, skipping release preparation"
|
||||
else
|
||||
echo "Tag $TAG_NAME@$VERSION does not exist, proceeding with release preparation"
|
||||
|
||||
9
.github/workflows/cli_checks.yaml
vendored
9
.github/workflows/cli_checks.yaml
vendored
@@ -1,8 +1,7 @@
|
||||
---
|
||||
name: "cli: check and build"
|
||||
on:
|
||||
# pull_request_target:
|
||||
pull_request:
|
||||
pull_request_target:
|
||||
paths:
|
||||
- '.github/workflows/cli_checks.yaml'
|
||||
- '.github/workflows/wf_check.yaml'
|
||||
@@ -50,7 +49,7 @@ jobs:
|
||||
with:
|
||||
NAME: cli
|
||||
PATH: cli
|
||||
GIT_REF: ${{ github.sha }}
|
||||
GIT_REF: ${{ github.event_name == 'pull_request_target' && github.event.pull_request.head.sha || github.sha }}
|
||||
|
||||
secrets:
|
||||
AWS_ACCOUNT_ID: ${{ secrets.AWS_PRODUCTION_CORE_ACCOUNT_ID }}
|
||||
@@ -65,7 +64,7 @@ jobs:
|
||||
with:
|
||||
NAME: cli
|
||||
PATH: cli
|
||||
GIT_REF: ${{ github.sha }}
|
||||
GIT_REF: ${{ github.event_name == 'pull_request_target' && github.event.pull_request.head.sha || github.sha }}
|
||||
VERSION: 0.0.0-dev # we use a fixed version here to avoid unnecessary rebuilds
|
||||
DOCKER: true
|
||||
secrets:
|
||||
@@ -81,7 +80,7 @@ jobs:
|
||||
with:
|
||||
NAME: cli
|
||||
PATH: cli
|
||||
GIT_REF: ${{ github.sha }}
|
||||
GIT_REF: ${{ github.event_name == 'pull_request_target' && github.event.pull_request.head.sha || github.sha }}
|
||||
|
||||
secrets:
|
||||
AWS_ACCOUNT_ID: ${{ secrets.AWS_PRODUCTION_CORE_ACCOUNT_ID }}
|
||||
|
||||
@@ -63,7 +63,7 @@ jobs:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: "Get artifacts"
|
||||
uses: actions/download-artifact@v5
|
||||
uses: actions/download-artifact@v6
|
||||
with:
|
||||
path: ~/artifacts
|
||||
|
||||
|
||||
7
.github/workflows/codegen_checks.yaml
vendored
7
.github/workflows/codegen_checks.yaml
vendored
@@ -1,8 +1,7 @@
|
||||
---
|
||||
name: "codegen: check and build"
|
||||
on:
|
||||
# pull_request_target:
|
||||
pull_request:
|
||||
pull_request_target:
|
||||
paths:
|
||||
- '.github/workflows/wf_check.yaml'
|
||||
- '.github/workflows/codegen_checks.yaml'
|
||||
@@ -48,7 +47,7 @@ jobs:
|
||||
with:
|
||||
NAME: codegen
|
||||
PATH: tools/codegen
|
||||
GIT_REF: ${{ github.sha }}
|
||||
GIT_REF: ${{ github.event_name == 'pull_request_target' && github.event.pull_request.head.sha || github.sha }}
|
||||
|
||||
secrets:
|
||||
AWS_ACCOUNT_ID: ${{ secrets.AWS_PRODUCTION_CORE_ACCOUNT_ID }}
|
||||
@@ -62,7 +61,7 @@ jobs:
|
||||
with:
|
||||
NAME: codegen
|
||||
PATH: tools/codegen
|
||||
GIT_REF: ${{ github.sha }}
|
||||
GIT_REF: ${{ github.event_name == 'pull_request_target' && github.event.pull_request.head.sha || github.sha }}
|
||||
VERSION: 0.0.0-dev # we use a fixed version here to avoid unnecessary rebuilds
|
||||
DOCKER: false
|
||||
secrets:
|
||||
|
||||
10
.github/workflows/dashboard_checks.yaml
vendored
10
.github/workflows/dashboard_checks.yaml
vendored
@@ -1,7 +1,7 @@
|
||||
---
|
||||
name: "dashboard: check and build"
|
||||
on:
|
||||
pull_request:
|
||||
pull_request_target:
|
||||
paths:
|
||||
- '.github/workflows/wf_build_artifacts.yaml'
|
||||
- '.github/workflows/wf_check.yaml'
|
||||
@@ -54,7 +54,7 @@ jobs:
|
||||
- check-permissions
|
||||
with:
|
||||
NAME: dashboard
|
||||
GIT_REF: ${{ github.sha }}
|
||||
GIT_REF: ${{ github.event_name == 'pull_request_target' && github.event.pull_request.head.sha || github.sha }}
|
||||
ENVIRONMENT: preview
|
||||
secrets:
|
||||
AWS_ACCOUNT_ID: ${{ secrets.AWS_PRODUCTION_CORE_ACCOUNT_ID }}
|
||||
@@ -73,7 +73,7 @@ jobs:
|
||||
with:
|
||||
NAME: dashboard
|
||||
PATH: dashboard
|
||||
GIT_REF: ${{ github.sha }}
|
||||
GIT_REF: ${{ github.event_name == 'pull_request_target' && github.event.pull_request.head.sha || github.sha }}
|
||||
VERSION: 0.0.0-dev # we use a fixed version here to avoid unnecessary rebuilds
|
||||
DOCKER: true
|
||||
OS_MATRIX: '["blacksmith-2vcpu-ubuntu-2404"]'
|
||||
@@ -91,7 +91,7 @@ jobs:
|
||||
with:
|
||||
NAME: dashboard
|
||||
PATH: dashboard
|
||||
GIT_REF: ${{ github.sha }}
|
||||
GIT_REF: ${{ github.event_name == 'pull_request_target' && github.event.pull_request.head.sha || github.sha }}
|
||||
secrets:
|
||||
AWS_ACCOUNT_ID: ${{ secrets.AWS_PRODUCTION_CORE_ACCOUNT_ID }}
|
||||
NIX_CACHE_PUB_KEY: ${{ secrets.NIX_CACHE_PUB_KEY }}
|
||||
@@ -107,7 +107,7 @@ jobs:
|
||||
with:
|
||||
NAME: dashboard
|
||||
PATH: dashboard
|
||||
GIT_REF: ${{ github.sha }}
|
||||
GIT_REF: ${{ github.event_name == 'pull_request_target' && github.event.pull_request.head.sha || github.sha }}
|
||||
NHOST_TEST_DASHBOARD_URL: ${{ needs.deploy-vercel.outputs.preview-url }}
|
||||
NHOST_TEST_PROJECT_NAME: ${{ vars.NHOST_TEST_PROJECT_NAME }}
|
||||
NHOST_TEST_ORGANIZATION_NAME: ${{ vars.NHOST_TEST_ORGANIZATION_NAME }}
|
||||
|
||||
@@ -148,7 +148,7 @@ jobs:
|
||||
rm playwright-report.tar.gz
|
||||
|
||||
- name: Upload encrypted Playwright report
|
||||
uses: actions/upload-artifact@v4
|
||||
uses: actions/upload-artifact@v5
|
||||
if: failure()
|
||||
with:
|
||||
name: encrypted-playwright-report-${{ github.run_id }}
|
||||
|
||||
2
.github/workflows/dashboard_wf_release.yaml
vendored
2
.github/workflows/dashboard_wf_release.yaml
vendored
@@ -88,7 +88,7 @@ jobs:
|
||||
- name: Bump version in source code
|
||||
run: |
|
||||
find cli -type f -exec sed -i 's/"nhost\/dashboard:[^"]*"/"nhost\/dashboard:${{ inputs.VERSION }}"/g' {} +
|
||||
sed -i 's/"nhost\/dashboard:[^"]*"/"nhost\/dashboard:${{ inputs.VERSION }}"/g' docs/reference/cli/commands.mdx
|
||||
sed -i 's/nhost\/dashboard:[^)]*/nhost\/dashboard:${{ inputs.VERSION }}/g' docs/reference/cli/commands.mdx
|
||||
|
||||
- name: "Create Pull Request"
|
||||
uses: peter-evans/create-pull-request@v7
|
||||
|
||||
4
.github/workflows/docs_checks.yaml
vendored
4
.github/workflows/docs_checks.yaml
vendored
@@ -1,7 +1,7 @@
|
||||
---
|
||||
name: "docs: check and build"
|
||||
on:
|
||||
pull_request:
|
||||
pull_request_target:
|
||||
paths:
|
||||
- '.github/workflows/wf_check.yaml'
|
||||
- '.github/workflows/dashboard_checks.yaml'
|
||||
@@ -62,7 +62,7 @@ jobs:
|
||||
with:
|
||||
NAME: docs
|
||||
PATH: docs
|
||||
GIT_REF: ${{ github.sha }}
|
||||
GIT_REF: ${{ github.event_name == 'pull_request_target' && github.event.pull_request.head.sha || github.sha }}
|
||||
secrets:
|
||||
AWS_ACCOUNT_ID: ${{ secrets.AWS_PRODUCTION_CORE_ACCOUNT_ID }}
|
||||
NIX_CACHE_PUB_KEY: ${{ secrets.NIX_CACHE_PUB_KEY }}
|
||||
|
||||
7
.github/workflows/examples_demos_checks.yaml
vendored
7
.github/workflows/examples_demos_checks.yaml
vendored
@@ -1,8 +1,7 @@
|
||||
---
|
||||
name: "examples/demos: check and build"
|
||||
on:
|
||||
# pull_request_target:
|
||||
pull_request:
|
||||
pull_request_target:
|
||||
paths:
|
||||
- '.github/workflows/wf_check.yaml'
|
||||
- '.github/workflows/examples_demos_checks.yaml'
|
||||
@@ -64,7 +63,7 @@ jobs:
|
||||
with:
|
||||
NAME: demos
|
||||
PATH: examples/demos
|
||||
GIT_REF: ${{ github.sha }}
|
||||
GIT_REF: ${{ github.event_name == 'pull_request_target' && github.event.pull_request.head.sha || github.sha }}
|
||||
|
||||
secrets:
|
||||
AWS_ACCOUNT_ID: ${{ secrets.AWS_PRODUCTION_CORE_ACCOUNT_ID }}
|
||||
@@ -78,7 +77,7 @@ jobs:
|
||||
with:
|
||||
NAME: demos
|
||||
PATH: examples/demos
|
||||
GIT_REF: ${{ github.sha }}
|
||||
GIT_REF: ${{ github.event_name == 'pull_request_target' && github.event.pull_request.head.sha || github.sha }}
|
||||
VERSION: 0.0.0-dev # we use a fixed version here to avoid unnecessary rebuilds
|
||||
DOCKER: false
|
||||
OS_MATRIX: '["blacksmith-2vcpu-ubuntu-2404"]'
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
---
|
||||
name: "examples/guides: check and build"
|
||||
on:
|
||||
# pull_request_target:
|
||||
pull_request:
|
||||
pull_request_target:
|
||||
paths:
|
||||
- '.github/workflows/wf_check.yaml'
|
||||
- '.github/workflows/examples_guides_checks.yaml'
|
||||
@@ -64,7 +63,7 @@ jobs:
|
||||
with:
|
||||
NAME: guides
|
||||
PATH: examples/guides
|
||||
GIT_REF: ${{ github.sha }}
|
||||
GIT_REF: ${{ github.event_name == 'pull_request_target' && github.event.pull_request.head.sha || github.sha }}
|
||||
|
||||
secrets:
|
||||
AWS_ACCOUNT_ID: ${{ secrets.AWS_PRODUCTION_CORE_ACCOUNT_ID }}
|
||||
@@ -78,7 +77,7 @@ jobs:
|
||||
with:
|
||||
NAME: guides
|
||||
PATH: examples/guides
|
||||
GIT_REF: ${{ github.sha }}
|
||||
GIT_REF: ${{ github.event_name == 'pull_request_target' && github.event.pull_request.head.sha || github.sha }}
|
||||
VERSION: 0.0.0-dev # we use a fixed version here to avoid unnecessary rebuilds
|
||||
DOCKER: false
|
||||
OS_MATRIX: '["blacksmith-2vcpu-ubuntu-2404"]'
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
---
|
||||
name: "examples/tutorials: check and build"
|
||||
on:
|
||||
# pull_request_target:
|
||||
pull_request:
|
||||
pull_request_target:
|
||||
paths:
|
||||
- '.github/workflows/wf_check.yaml'
|
||||
- '.github/workflows/examples_tutorials_checks.yaml'
|
||||
@@ -64,7 +63,7 @@ jobs:
|
||||
with:
|
||||
NAME: tutorials
|
||||
PATH: examples/tutorials
|
||||
GIT_REF: ${{ github.sha }}
|
||||
GIT_REF: ${{ github.event_name == 'pull_request_target' && github.event.pull_request.head.sha || github.sha }}
|
||||
|
||||
secrets:
|
||||
AWS_ACCOUNT_ID: ${{ secrets.AWS_PRODUCTION_CORE_ACCOUNT_ID }}
|
||||
@@ -78,7 +77,7 @@ jobs:
|
||||
with:
|
||||
NAME: tutorials
|
||||
PATH: examples/tutorials
|
||||
GIT_REF: ${{ github.sha }}
|
||||
GIT_REF: ${{ github.event_name == 'pull_request_target' && github.event.pull_request.head.sha || github.sha }}
|
||||
VERSION: 0.0.0-dev # we use a fixed version here to avoid unnecessary rebuilds
|
||||
DOCKER: false
|
||||
OS_MATRIX: '["blacksmith-2vcpu-ubuntu-2404"]'
|
||||
|
||||
4
.github/workflows/gen_ai_review.yaml
vendored
4
.github/workflows/gen_ai_review.yaml
vendored
@@ -1,7 +1,7 @@
|
||||
---
|
||||
name: "gen: AI review"
|
||||
on:
|
||||
pull_request:
|
||||
pull_request_target:
|
||||
types: [opened, reopened, ready_for_review]
|
||||
issue_comment:
|
||||
jobs:
|
||||
@@ -16,7 +16,7 @@ jobs:
|
||||
steps:
|
||||
- name: PR Agent action step
|
||||
id: pragent
|
||||
uses: Codium-ai/pr-agent@v0.30
|
||||
uses: Codium-ai/pr-agent@v0.31
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
OPENAI_KEY: ${{ secrets.OPENAI_API_KEY }}
|
||||
|
||||
7
.github/workflows/nhost-js_checks.yaml
vendored
7
.github/workflows/nhost-js_checks.yaml
vendored
@@ -1,8 +1,7 @@
|
||||
---
|
||||
name: "nhost-js: check and build"
|
||||
on:
|
||||
# pull_request_target:
|
||||
pull_request:
|
||||
pull_request_target:
|
||||
paths:
|
||||
- '.github/workflows/wf_check.yaml'
|
||||
- '.github/workflows/nhost-js_checks.yaml'
|
||||
@@ -65,7 +64,7 @@ jobs:
|
||||
with:
|
||||
NAME: nhost-js
|
||||
PATH: packages/nhost-js
|
||||
GIT_REF: ${{ github.sha }}
|
||||
GIT_REF: ${{ github.event_name == 'pull_request_target' && github.event.pull_request.head.sha || github.sha }}
|
||||
|
||||
secrets:
|
||||
AWS_ACCOUNT_ID: ${{ secrets.AWS_PRODUCTION_CORE_ACCOUNT_ID }}
|
||||
@@ -79,7 +78,7 @@ jobs:
|
||||
with:
|
||||
NAME: nhost-js
|
||||
PATH: packages/nhost-js
|
||||
GIT_REF: ${{ github.sha }}
|
||||
GIT_REF: ${{ github.event_name == 'pull_request_target' && github.event.pull_request.head.sha || github.sha }}
|
||||
VERSION: 0.0.0-dev # we use a fixed version here to avoid unnecessary rebuilds
|
||||
DOCKER: false
|
||||
secrets:
|
||||
|
||||
7
.github/workflows/nixops_checks.yaml
vendored
7
.github/workflows/nixops_checks.yaml
vendored
@@ -1,8 +1,7 @@
|
||||
---
|
||||
name: "nixops: check and build"
|
||||
on:
|
||||
# pull_request_target:
|
||||
pull_request:
|
||||
pull_request_target:
|
||||
paths:
|
||||
- '.github/workflows/wf_check.yaml'
|
||||
- '.github/workflows/nixops_checks.yaml'
|
||||
@@ -40,7 +39,7 @@ jobs:
|
||||
with:
|
||||
NAME: nixops
|
||||
PATH: nixops
|
||||
GIT_REF: ${{ github.sha }}
|
||||
GIT_REF: ${{ github.event_name == 'pull_request_target' && github.event.pull_request.head.sha || github.sha }}
|
||||
|
||||
secrets:
|
||||
AWS_ACCOUNT_ID: ${{ secrets.AWS_PRODUCTION_CORE_ACCOUNT_ID }}
|
||||
@@ -54,7 +53,7 @@ jobs:
|
||||
with:
|
||||
NAME: nixops
|
||||
PATH: nixops
|
||||
GIT_REF: ${{ github.sha }}
|
||||
GIT_REF: ${{ github.event_name == 'pull_request_target' && github.event.pull_request.head.sha || github.sha }}
|
||||
VERSION: 0.0.0-dev # we use a fixed version here to avoid unnecessary rebuilds
|
||||
DOCKER: true
|
||||
secrets:
|
||||
|
||||
8
.github/workflows/storage_checks.yaml
vendored
8
.github/workflows/storage_checks.yaml
vendored
@@ -1,8 +1,7 @@
|
||||
---
|
||||
name: "storage: check and build"
|
||||
on:
|
||||
# pull_request_target:
|
||||
pull_request:
|
||||
pull_request_target:
|
||||
paths:
|
||||
- '.github/workflows/storage_checks.yaml'
|
||||
- '.github/workflows/wf_check.yaml'
|
||||
@@ -18,6 +17,7 @@ on:
|
||||
- '.golangci.yaml'
|
||||
- 'go.mod'
|
||||
- 'go.sum'
|
||||
- 'internal/lib/**'
|
||||
- 'vendor/**'
|
||||
|
||||
# storage
|
||||
@@ -49,7 +49,7 @@ jobs:
|
||||
with:
|
||||
NAME: storage
|
||||
PATH: services/storage
|
||||
GIT_REF: ${{ github.sha }}
|
||||
GIT_REF: ${{ github.event_name == 'pull_request_target' && github.event.pull_request.head.sha || github.sha }}
|
||||
|
||||
secrets:
|
||||
AWS_ACCOUNT_ID: ${{ secrets.AWS_PRODUCTION_CORE_ACCOUNT_ID }}
|
||||
@@ -64,7 +64,7 @@ jobs:
|
||||
with:
|
||||
NAME: storage
|
||||
PATH: services/storage
|
||||
GIT_REF: ${{ github.sha }}
|
||||
GIT_REF: ${{ github.event_name == 'pull_request_target' && github.event.pull_request.head.sha || github.sha }}
|
||||
VERSION: 0.0.0-dev # we use a fixed version here to avoid unnecessary rebuilds
|
||||
DOCKER: true
|
||||
secrets:
|
||||
|
||||
4
.github/workflows/wf_build_artifacts.yaml
vendored
4
.github/workflows/wf_build_artifacts.yaml
vendored
@@ -85,7 +85,7 @@ jobs:
|
||||
zip -r result.zip result
|
||||
|
||||
- name: "Push artifact to artifact repository"
|
||||
uses: actions/upload-artifact@v4
|
||||
uses: actions/upload-artifact@v5
|
||||
with:
|
||||
name: ${{ inputs.NAME }}-artifact-${{ steps.vars.outputs.ARCH }}-${{ steps.vars.outputs.VERSION }}
|
||||
path: ${{ inputs.PATH }}/result.zip
|
||||
@@ -100,7 +100,7 @@ jobs:
|
||||
if: ${{ ( inputs.DOCKER ) }}
|
||||
|
||||
- name: "Push docker image to artifact repository"
|
||||
uses: actions/upload-artifact@v4
|
||||
uses: actions/upload-artifact@v5
|
||||
with:
|
||||
name: ${{ inputs.NAME }}-docker-image-${{ steps.vars.outputs.ARCH }}-${{ steps.vars.outputs.VERSION }}
|
||||
path: ${{ inputs.PATH }}/result
|
||||
|
||||
2
.github/workflows/wf_docker_push_image.yaml
vendored
2
.github/workflows/wf_docker_push_image.yaml
vendored
@@ -44,7 +44,7 @@ jobs:
|
||||
echo "VERSION=$(make get-version VER=${{ inputs.VERSION }})" >> $GITHUB_OUTPUT
|
||||
|
||||
- name: "Get artifacts"
|
||||
uses: actions/download-artifact@v5
|
||||
uses: actions/download-artifact@v6
|
||||
with:
|
||||
path: ~/artifacts
|
||||
|
||||
|
||||
@@ -55,7 +55,7 @@ jobs:
|
||||
echo "VERSION=$(make get-version VER=${{ inputs.VERSION }})" >> $GITHUB_OUTPUT
|
||||
|
||||
- name: "Get artifacts"
|
||||
uses: actions/download-artifact@v5
|
||||
uses: actions/download-artifact@v6
|
||||
with:
|
||||
path: ~/artifacts
|
||||
|
||||
|
||||
@@ -16,6 +16,15 @@ Contributions are made to Nhost repos via Issues and Pull Requests (PRs). A few
|
||||
- We work hard to make sure issues are handled on time, but it could take a while to investigate the root cause depending on the impact. A friendly ping in the comment thread to the submitter or a contributor can help draw attention if your issue is blocking.
|
||||
- If you've never contributed before, see [the first-timer's guide](https://github.com/firstcontributions/first-contributions) for resources and tips on getting started.
|
||||
|
||||
### AI-Assisted Contributions
|
||||
|
||||
We have specific policies regarding AI-assisted contributions:
|
||||
|
||||
- **Issues**: Bug reports and feature requests that are clearly AI-generated will not be accepted and will be closed immediately. Please write your issues in your own words to ensure they are clear, specific, and contain the necessary context.
|
||||
- **Pull Requests**: Contributions with the help of AI are permitted, but you are ultimately responsible for the quality of your submission and for ensuring it follows our contributing guidelines. The PR description must be written in your own words. Additionally, please remove any superfluous code comments introduced by AI tools before submitting. PRs that clearly violate this rule will be closed without further review.
|
||||
|
||||
In all cases, contributors must ensure their submissions are thoughtful, well-tested, and meet the project's quality standards.
|
||||
|
||||
### Issues
|
||||
|
||||
Issues should be used to report problems with Nhost, request a new feature, or discuss potential changes before a PR is created.
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
"$schema": "https://github.com/IBM/audit-ci/raw/main/docs/schema.json",
|
||||
"moderate": true,
|
||||
"allowlist": [
|
||||
"GHSA-9965-vmph-33xx", // https://github.com/advisories/GHSA-9965-vmph-33xx Update package once have a fix
|
||||
"GHSA-7mvr-c777-76hp" // https://github.com/advisories/GHSA-7mvr-c777-76hp Update package once Nix side is also updated
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,45 @@
|
||||
## [cli@1.34.7] - 2025-11-13
|
||||
|
||||
### ⚙️ Miscellaneous Tasks
|
||||
|
||||
- *(cli)* Bump nhost/dashboard to 2.42.0 (#3693)
|
||||
|
||||
## [cli@1.34.6] - 2025-11-13
|
||||
|
||||
### 🐛 Bug Fixes
|
||||
|
||||
- *(cli)* Mcp: specify items type for arrays in tools (#3687)
|
||||
|
||||
|
||||
### ⚙️ Miscellaneous Tasks
|
||||
|
||||
- *(cli)* Update bindings (#3689)
|
||||
|
||||
## [cli@1.34.5] - 2025-11-06
|
||||
|
||||
### ⚙️ Miscellaneous Tasks
|
||||
|
||||
- *(nixops)* Bump go to 1.25.3 and nixpkgs due to CVEs (#3652)
|
||||
- *(cli)* Udpate certs and schema (#3675)
|
||||
- *(cli)* Bump nhost/dashboard to 2.41.0 (#3669)
|
||||
|
||||
# Changelog
|
||||
|
||||
All notable changes to this project will be documented in this file.
|
||||
|
||||
## [cli@1.34.4] - 2025-10-28
|
||||
|
||||
### 🐛 Bug Fixes
|
||||
|
||||
- *(cli)* Update NEXT_PUBLIC_NHOST_HASURA_MIGRATIONS_API_URL correctly (#3643)
|
||||
|
||||
## [cli@1.34.3] - 2025-10-27
|
||||
|
||||
### ⚙️ Miscellaneous Tasks
|
||||
|
||||
- *(cli)* Update schema (#3622)
|
||||
- *(cli)* Bump nhost/dashboard to 2.40.0 (#3629)
|
||||
|
||||
## [cli@1.34.2] - 2025-10-20
|
||||
|
||||
### ⚙️ Miscellaneous Tasks
|
||||
|
||||
@@ -56,7 +56,7 @@ func CommandCloud() *cli.Command {
|
||||
&cli.StringFlag{ //nolint:exhaustruct
|
||||
Name: flagDashboardVersion,
|
||||
Usage: "Dashboard version to use",
|
||||
Value: "nhost/dashboard:2.38.4",
|
||||
Value: "nhost/dashboard:2.42.0",
|
||||
Sources: cli.EnvVars("NHOST_DASHBOARD_VERSION"),
|
||||
},
|
||||
&cli.StringFlag{ //nolint:exhaustruct
|
||||
|
||||
@@ -111,7 +111,7 @@ func CommandUp() *cli.Command { //nolint:funlen
|
||||
&cli.StringFlag{ //nolint:exhaustruct
|
||||
Name: flagDashboardVersion,
|
||||
Usage: "Dashboard version to use",
|
||||
Value: "nhost/dashboard:2.38.4",
|
||||
Value: "nhost/dashboard:2.42.0",
|
||||
Sources: cli.EnvVars("NHOST_DASHBOARD_VERSION"),
|
||||
},
|
||||
&cli.StringFlag{ //nolint:exhaustruct
|
||||
|
||||
@@ -196,10 +196,12 @@ config validate after making changes to your nhost.toml file to ensure it is val
|
||||
"mutations": map[string]any{
|
||||
"description": string("list of mutations to fetch"),
|
||||
"type": string("array"),
|
||||
"items": map[string]any{"type": string("string")},
|
||||
},
|
||||
"queries": map[string]any{
|
||||
"description": string("list of queries to fetch"),
|
||||
"type": string("array"),
|
||||
"items": map[string]any{"type": string("string")},
|
||||
},
|
||||
"summary": map[string]any{
|
||||
"default": bool(true),
|
||||
|
||||
@@ -53,6 +53,7 @@ func expectedAuth() *Service {
|
||||
"AUTH_PROVIDER_APPLE_ENABLED": "true",
|
||||
"AUTH_PROVIDER_APPLE_KEY_ID": "appleKeyId",
|
||||
"AUTH_PROVIDER_APPLE_PRIVATE_KEY": "applePrivateKey",
|
||||
"AUTH_PROVIDER_APPLE_SCOPE": "",
|
||||
"AUTH_PROVIDER_APPLE_TEAM_ID": "appleTeamId",
|
||||
"AUTH_PROVIDER_AZUREAD_CLIENT_ID": "azureadClientId",
|
||||
"AUTH_PROVIDER_AZUREAD_CLIENT_SECRET": "azureadClientSecret",
|
||||
@@ -75,9 +76,12 @@ func expectedAuth() *Service {
|
||||
"AUTH_PROVIDER_FACEBOOK_CLIENT_SECRET": "facebookClientSecret",
|
||||
"AUTH_PROVIDER_FACEBOOK_ENABLED": "true",
|
||||
"AUTH_PROVIDER_FACEBOOK_SCOPE": "email",
|
||||
"AUTH_PROVIDER_GITHUB_AUDIENCE": "audience",
|
||||
"AUTH_PROVIDER_GITHUB_CLIENT_ID": "githubClientId",
|
||||
"AUTH_PROVIDER_GITHUB_CLIENT_SECRET": "githubClientSecret",
|
||||
"AUTH_PROVIDER_GITHUB_ENABLED": "true",
|
||||
"AUTH_PROVIDER_GITHUB_SCOPE": "user:email",
|
||||
"AUTH_PROVIDER_GITLAB_AUDIENCE": "audience",
|
||||
"AUTH_PROVIDER_GITLAB_CLIENT_ID": "gitlabClientId",
|
||||
"AUTH_PROVIDER_GITLAB_CLIENT_SECRET": "gitlabClientSecret",
|
||||
"AUTH_PROVIDER_GITLAB_ENABLED": "true",
|
||||
@@ -97,6 +101,7 @@ func expectedAuth() *Service {
|
||||
"AUTH_PROVIDER_SPOTIFY_CLIENT_SECRET": "spotifyClientSecret",
|
||||
"AUTH_PROVIDER_SPOTIFY_ENABLED": "true",
|
||||
"AUTH_PROVIDER_SPOTIFY_SCOPE": "user-read-email",
|
||||
"AUTH_PROVIDER_STRAVA_AUDIENCE": "audience",
|
||||
"AUTH_PROVIDER_STRAVA_CLIENT_ID": "stravaClientId",
|
||||
"AUTH_PROVIDER_STRAVA_CLIENT_SECRET": "stravaClientSecret",
|
||||
"AUTH_PROVIDER_STRAVA_ENABLED": "true",
|
||||
|
||||
@@ -344,7 +344,7 @@ func dashboard(
|
||||
subdomain, "hasura", httpPort, useTLS,
|
||||
) + "/console",
|
||||
"NEXT_PUBLIC_NHOST_HASURA_MIGRATIONS_API_URL": URL(
|
||||
subdomain, "hasura", httpPort, useTLS),
|
||||
subdomain, "hasura", httpPort, useTLS) + "/apis/migrate",
|
||||
"NEXT_PUBLIC_NHOST_STORAGE_URL": URL(
|
||||
subdomain, "storage", httpPort, useTLS) + "/v1",
|
||||
},
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// Package auth provides primitives to interact with the openapi HTTP API.
|
||||
//
|
||||
// Code generated by github.com/oapi-codegen/oapi-codegen/v2 version 2.4.1 DO NOT EDIT.
|
||||
// Code generated by github.com/oapi-codegen/oapi-codegen/v2 version 2.5.0 DO NOT EDIT.
|
||||
package auth
|
||||
|
||||
import (
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// Package graphql provides primitives to interact with the openapi HTTP API.
|
||||
//
|
||||
// Code generated by github.com/oapi-codegen/oapi-codegen/v2 version 2.4.1 DO NOT EDIT.
|
||||
// Code generated by github.com/oapi-codegen/oapi-codegen/v2 version 2.5.0 DO NOT EDIT.
|
||||
package graphql
|
||||
|
||||
import (
|
||||
|
||||
@@ -223,7 +223,7 @@ import (
|
||||
// Releases:
|
||||
//
|
||||
// https://github.com/nhost/hasura-storage/releases
|
||||
version: string | *"0.8.2"
|
||||
version: string | *"0.9.1"
|
||||
|
||||
// Networking (custom domains at the moment) are not allowed as we need to do further
|
||||
// configurations in the CDN. We will enable it again in the future.
|
||||
@@ -311,7 +311,7 @@ import (
|
||||
// Releases:
|
||||
//
|
||||
// https://github.com/nhost/hasura-auth/releases
|
||||
version: string | *"0.42.4"
|
||||
version: string | *"0.43.0"
|
||||
|
||||
// Resources for the service
|
||||
resources?: #Resources
|
||||
|
||||
@@ -68,10 +68,12 @@ func (t *Tool) Register(mcpServer *server.MCPServer) {
|
||||
),
|
||||
mcp.WithArray(
|
||||
"queries",
|
||||
mcp.WithStringItems(),
|
||||
mcp.Description("list of queries to fetch"),
|
||||
),
|
||||
mcp.WithArray(
|
||||
"mutations",
|
||||
mcp.WithStringItems(),
|
||||
mcp.Description("list of mutations to fetch"),
|
||||
),
|
||||
)
|
||||
|
||||
@@ -2247,6 +2247,14 @@ type AuthUserProvidersMinOrderBy struct {
|
||||
ProviderID *OrderBy `json:"providerId,omitempty"`
|
||||
}
|
||||
|
||||
// response of any mutation on the table "auth.user_providers"
|
||||
type AuthUserProvidersMutationResponse struct {
|
||||
// number of rows affected by the mutation
|
||||
AffectedRows int64 `json:"affected_rows"`
|
||||
// data from the rows affected by the mutation
|
||||
Returning []*AuthUserProviders `json:"returning"`
|
||||
}
|
||||
|
||||
// Ordering options when selecting data from "auth.user_providers".
|
||||
type AuthUserProvidersOrderBy struct {
|
||||
ID *OrderBy `json:"id,omitempty"`
|
||||
@@ -2823,6 +2831,7 @@ type Deployments struct {
|
||||
CommitSha string `json:"commitSHA"`
|
||||
CommitUserAvatarURL *string `json:"commitUserAvatarUrl,omitempty"`
|
||||
CommitUserName *string `json:"commitUserName,omitempty"`
|
||||
CreatedAt time.Time `json:"createdAt"`
|
||||
DeploymentEndedAt *time.Time `json:"deploymentEndedAt,omitempty"`
|
||||
// An array relationship
|
||||
DeploymentLogs []*DeploymentLogs `json:"deploymentLogs"`
|
||||
@@ -2865,6 +2874,7 @@ type DeploymentsBoolExp struct {
|
||||
CommitSha *StringComparisonExp `json:"commitSHA,omitempty"`
|
||||
CommitUserAvatarURL *StringComparisonExp `json:"commitUserAvatarUrl,omitempty"`
|
||||
CommitUserName *StringComparisonExp `json:"commitUserName,omitempty"`
|
||||
CreatedAt *TimestamptzComparisonExp `json:"createdAt,omitempty"`
|
||||
DeploymentEndedAt *TimestamptzComparisonExp `json:"deploymentEndedAt,omitempty"`
|
||||
DeploymentLogs *DeploymentLogsBoolExp `json:"deploymentLogs,omitempty"`
|
||||
DeploymentStartedAt *TimestamptzComparisonExp `json:"deploymentStartedAt,omitempty"`
|
||||
@@ -2899,6 +2909,7 @@ type DeploymentsMaxOrderBy struct {
|
||||
CommitSha *OrderBy `json:"commitSHA,omitempty"`
|
||||
CommitUserAvatarURL *OrderBy `json:"commitUserAvatarUrl,omitempty"`
|
||||
CommitUserName *OrderBy `json:"commitUserName,omitempty"`
|
||||
CreatedAt *OrderBy `json:"createdAt,omitempty"`
|
||||
DeploymentEndedAt *OrderBy `json:"deploymentEndedAt,omitempty"`
|
||||
DeploymentStartedAt *OrderBy `json:"deploymentStartedAt,omitempty"`
|
||||
DeploymentStatus *OrderBy `json:"deploymentStatus,omitempty"`
|
||||
@@ -2921,6 +2932,7 @@ type DeploymentsMinOrderBy struct {
|
||||
CommitSha *OrderBy `json:"commitSHA,omitempty"`
|
||||
CommitUserAvatarURL *OrderBy `json:"commitUserAvatarUrl,omitempty"`
|
||||
CommitUserName *OrderBy `json:"commitUserName,omitempty"`
|
||||
CreatedAt *OrderBy `json:"createdAt,omitempty"`
|
||||
DeploymentEndedAt *OrderBy `json:"deploymentEndedAt,omitempty"`
|
||||
DeploymentStartedAt *OrderBy `json:"deploymentStartedAt,omitempty"`
|
||||
DeploymentStatus *OrderBy `json:"deploymentStatus,omitempty"`
|
||||
@@ -2959,6 +2971,7 @@ type DeploymentsOrderBy struct {
|
||||
CommitSha *OrderBy `json:"commitSHA,omitempty"`
|
||||
CommitUserAvatarURL *OrderBy `json:"commitUserAvatarUrl,omitempty"`
|
||||
CommitUserName *OrderBy `json:"commitUserName,omitempty"`
|
||||
CreatedAt *OrderBy `json:"createdAt,omitempty"`
|
||||
DeploymentEndedAt *OrderBy `json:"deploymentEndedAt,omitempty"`
|
||||
DeploymentLogsAggregate *DeploymentLogsAggregateOrderBy `json:"deploymentLogs_aggregate,omitempty"`
|
||||
DeploymentStartedAt *OrderBy `json:"deploymentStartedAt,omitempty"`
|
||||
@@ -2990,6 +3003,7 @@ type DeploymentsStreamCursorValueInput struct {
|
||||
CommitSha *string `json:"commitSHA,omitempty"`
|
||||
CommitUserAvatarURL *string `json:"commitUserAvatarUrl,omitempty"`
|
||||
CommitUserName *string `json:"commitUserName,omitempty"`
|
||||
CreatedAt *time.Time `json:"createdAt,omitempty"`
|
||||
DeploymentEndedAt *time.Time `json:"deploymentEndedAt,omitempty"`
|
||||
DeploymentStartedAt *time.Time `json:"deploymentStartedAt,omitempty"`
|
||||
DeploymentStatus *string `json:"deploymentStatus,omitempty"`
|
||||
@@ -6983,6 +6997,8 @@ const (
|
||||
// column name
|
||||
DeploymentsSelectColumnCommitUserName DeploymentsSelectColumn = "commitUserName"
|
||||
// column name
|
||||
DeploymentsSelectColumnCreatedAt DeploymentsSelectColumn = "createdAt"
|
||||
// column name
|
||||
DeploymentsSelectColumnDeploymentEndedAt DeploymentsSelectColumn = "deploymentEndedAt"
|
||||
// column name
|
||||
DeploymentsSelectColumnDeploymentStartedAt DeploymentsSelectColumn = "deploymentStartedAt"
|
||||
@@ -7016,6 +7032,7 @@ var AllDeploymentsSelectColumn = []DeploymentsSelectColumn{
|
||||
DeploymentsSelectColumnCommitSha,
|
||||
DeploymentsSelectColumnCommitUserAvatarURL,
|
||||
DeploymentsSelectColumnCommitUserName,
|
||||
DeploymentsSelectColumnCreatedAt,
|
||||
DeploymentsSelectColumnDeploymentEndedAt,
|
||||
DeploymentsSelectColumnDeploymentStartedAt,
|
||||
DeploymentsSelectColumnDeploymentStatus,
|
||||
@@ -7033,7 +7050,7 @@ var AllDeploymentsSelectColumn = []DeploymentsSelectColumn{
|
||||
|
||||
func (e DeploymentsSelectColumn) IsValid() bool {
|
||||
switch e {
|
||||
case DeploymentsSelectColumnAppID, DeploymentsSelectColumnCommitMessage, DeploymentsSelectColumnCommitSha, DeploymentsSelectColumnCommitUserAvatarURL, DeploymentsSelectColumnCommitUserName, DeploymentsSelectColumnDeploymentEndedAt, DeploymentsSelectColumnDeploymentStartedAt, DeploymentsSelectColumnDeploymentStatus, DeploymentsSelectColumnFunctionsEndedAt, DeploymentsSelectColumnFunctionsStartedAt, DeploymentsSelectColumnFunctionsStatus, DeploymentsSelectColumnID, DeploymentsSelectColumnMetadataEndedAt, DeploymentsSelectColumnMetadataStartedAt, DeploymentsSelectColumnMetadataStatus, DeploymentsSelectColumnMigrationsEndedAt, DeploymentsSelectColumnMigrationsStartedAt, DeploymentsSelectColumnMigrationsStatus:
|
||||
case DeploymentsSelectColumnAppID, DeploymentsSelectColumnCommitMessage, DeploymentsSelectColumnCommitSha, DeploymentsSelectColumnCommitUserAvatarURL, DeploymentsSelectColumnCommitUserName, DeploymentsSelectColumnCreatedAt, DeploymentsSelectColumnDeploymentEndedAt, DeploymentsSelectColumnDeploymentStartedAt, DeploymentsSelectColumnDeploymentStatus, DeploymentsSelectColumnFunctionsEndedAt, DeploymentsSelectColumnFunctionsStartedAt, DeploymentsSelectColumnFunctionsStatus, DeploymentsSelectColumnID, DeploymentsSelectColumnMetadataEndedAt, DeploymentsSelectColumnMetadataStartedAt, DeploymentsSelectColumnMetadataStatus, DeploymentsSelectColumnMigrationsEndedAt, DeploymentsSelectColumnMigrationsStartedAt, DeploymentsSelectColumnMigrationsStatus:
|
||||
return true
|
||||
}
|
||||
return false
|
||||
|
||||
@@ -1,27 +1,27 @@
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIERDCCA8mgAwIBAgISBmRex3kpZ4Mz1/1kq05iqja/MAoGCCqGSM49BAMDMDIx
|
||||
MIIERTCCA8ugAwIBAgISBWD/E+b14mP5jv4DGWRVYv8fMAoGCCqGSM49BAMDMDIx
|
||||
CzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1MZXQncyBFbmNyeXB0MQswCQYDVQQDEwJF
|
||||
ODAeFw0yNTEwMDIxMDUxNDBaFw0yNTEyMzExMDUxMzlaMB8xHTAbBgNVBAMTFGxv
|
||||
Y2FsLmF1dGgubmhvc3QucnVuMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE2cVM
|
||||
ojf8iXZGLneNfnke5LMJIxyTEeGbNOfCv4SOR4K/N4OkpvkUVbH2bRvX99uE9jaK
|
||||
515Y48PzPA/4+W1zTKOCAtAwggLMMA4GA1UdDwEB/wQEAwIHgDAdBgNVHSUEFjAU
|
||||
BggrBgEFBQcDAQYIKwYBBQUHAwIwDAYDVR0TAQH/BAIwADAdBgNVHQ4EFgQUQqan
|
||||
raZoU5klAxsgkEVEMIkxmMQwHwYDVR0jBBgwFoAUjw0TovYuftFQbDMYOF1ZjiNy
|
||||
ODAeFw0yNTExMDYxMDUxMTBaFw0yNjAyMDQxMDUxMDlaMB8xHTAbBgNVBAMTFGxv
|
||||
Y2FsLmF1dGgubmhvc3QucnVuMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEOah5
|
||||
ZLuUQp3pdMBxBWnT6E6/amW9LerKKEEdy3Nc8iAwG9LlnPH0z3m7a9wgEhpFEdlL
|
||||
Rr+qO+NhSRnv6+UF5KOCAtIwggLOMA4GA1UdDwEB/wQEAwIHgDAdBgNVHSUEFjAU
|
||||
BggrBgEFBQcDAQYIKwYBBQUHAwIwDAYDVR0TAQH/BAIwADAdBgNVHQ4EFgQUGyb1
|
||||
TVK/0vf3uHO4x3R094aG2rEwHwYDVR0jBBgwFoAUjw0TovYuftFQbDMYOF1ZjiNy
|
||||
kcowMgYIKwYBBQUHAQEEJjAkMCIGCCsGAQUFBzAChhZodHRwOi8vZTguaS5sZW5j
|
||||
ci5vcmcvMIHOBgNVHREEgcYwgcOCFGxvY2FsLmF1dGgubmhvc3QucnVughlsb2Nh
|
||||
bC5kYXNoYm9hcmQubmhvc3QucnVughJsb2NhbC5kYi5uaG9zdC5ydW6CGWxvY2Fs
|
||||
LmZ1bmN0aW9ucy5uaG9zdC5ydW6CF2xvY2FsLmdyYXBocWwubmhvc3QucnVughZs
|
||||
b2NhbC5oYXN1cmEubmhvc3QucnVughdsb2NhbC5tYWlsaG9nLm5ob3N0LnJ1boIX
|
||||
bG9jYWwuc3RvcmFnZS5uaG9zdC5ydW4wEwYDVR0gBAwwCjAIBgZngQwBAgEwLQYD
|
||||
VR0fBCYwJDAioCCgHoYcaHR0cDovL2U4LmMubGVuY3Iub3JnLzY0LmNybDCCAQIG
|
||||
CisGAQQB1nkCBAIEgfMEgfAA7gB1AO08S9boBsKkogBX28sk4jgB31Ev7cSGxXAP
|
||||
IN23Pj/gAAABmaTCI4YAAAQDAEYwRAIgXLRFL1EAXfvN6kd5m6udqlxfz4+5B6rq
|
||||
Cdhp/ZwDAZ8CIFYvalTkl5NEBEMD3vpPvrj8s1Yy2xsropEh/AvpavvLAHUAGYbU
|
||||
xyiqb/66A294Kk0BkarOLXIxD67OXXBBLSVMx9QAAAGZpMIjhwAABAMARjBEAiBk
|
||||
H1vqU9HNuBcf4UYL/xZ42BeUAARHStiFaIZtnR1kEgIgbIJ0CGqIpxmWuwCunl9p
|
||||
ar+rGLdQrCk9BZXq/VjPPAAwCgYIKoZIzj0EAwMDaQAwZgIxAKvk5a2zQsv7JLNj
|
||||
NO1ly+DI8qiy5nf4HQrOrHOjtmx5RUu0HSO9P0J0u069qAqXMgIxAMLdME9JUo2c
|
||||
TJo3pwWv5MRyg/MkOJ4ImKdDJXfIZNkEIUyP3vwTqImvZe07gJDsYg==
|
||||
VR0fBCYwJDAioCCgHoYcaHR0cDovL2U4LmMubGVuY3Iub3JnLzMyLmNybDCCAQQG
|
||||
CisGAQQB1nkCBAIEgfUEgfIA8AB2ABmG1Mcoqm/+ugNveCpNAZGqzi1yMQ+uzl1w
|
||||
QS0lTMfUAAABmlkAQokAAAQDAEcwRQIgWDtSxJfM2xcjvScVHOkn8bipzBhNhTnm
|
||||
B89TDh1/4XUCIQDe08W33PCx2D+akCdW9U9mZKQpIW6deLZSI3ZWpSNKMAB2AA5X
|
||||
lLzzrqk+MxssmQez95Dfm8I9cTIl3SGpJaxhxU4hAAABmlkAQn8AAAQDAEcwRQIg
|
||||
KnojmNTpNk1OFTQI0EnlPa2bpwqmUgmUCLeqE6SWfgoCIQCrhZbxYPHbGLF/HpRq
|
||||
vCTcOh24SRCuxlkqtaowbbfmKjAKBggqhkjOPQQDAwNoADBlAjEArstFIC+KAsfQ
|
||||
nLhtqsaNzkhftN5adDyr2CoE0WUPF1sLDi+xDnDO+JgIPL0YKAFNAjATJ4omhpc+
|
||||
I6/kWcef2RyO9YCGQQE9pdez5CYKb9o8YAntDSHM3b5nXXj3AX/USdQ=
|
||||
-----END CERTIFICATE-----
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIEVjCCAj6gAwIBAgIQY5WTY8JOcIJxWRi/w9ftVjANBgkqhkiG9w0BAQsFADBP
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
-----BEGIN PRIVATE KEY-----
|
||||
MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgfJZOkvawA0vBMw9W
|
||||
ph8i1Z+SJQrFscPbqSYpxngzEDahRANCAATZxUyiN/yJdkYud41+eR7kswkjHJMR
|
||||
4Zs058K/hI5Hgr83g6Sm+RRVsfZtG9f324T2NornXljjw/M8D/j5bXNM
|
||||
MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgInXN4JRnXNTjx7rM
|
||||
avurZrN1EV1iebQeNUlMlFp7VJ+hRANCAAQ5qHlku5RCnel0wHEFadPoTr9qZb0t
|
||||
6sooQR3Lc1zyIDAb0uWc8fTPebtr3CASGkUR2UtGv6o742FJGe/r5QXk
|
||||
-----END PRIVATE KEY-----
|
||||
|
||||
@@ -1,52 +1,52 @@
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIEWDCCA96gAwIBAgISBbvrSsjDQm4zevwwjxFGmeTMMAoGCCqGSM49BAMDMDIx
|
||||
MIIEVzCCA92gAwIBAgISBm54VdkoqD8s8efq7ceHaTihMAoGCCqGSM49BAMDMDIx
|
||||
CzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1MZXQncyBFbmNyeXB0MQswCQYDVQQDEwJF
|
||||
NzAeFw0yNTEwMDIxMDUyNTdaFw0yNTEyMzExMDUyNTZaMCExHzAdBgNVBAMMFiou
|
||||
YXV0aC5sb2NhbC5uaG9zdC5ydW4wWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAATG
|
||||
x0o7t0pSrOoFc+pljtqJVxgaSW+w9D9C2WdysMeSKKOU+0MzaM4ynLUhETOpBs8E
|
||||
612mdcoeak+G1Emj6UVwo4IC4zCCAt8wDgYDVR0PAQH/BAQDAgeAMB0GA1UdJQQW
|
||||
MBQGCCsGAQUFBwMBBggrBgEFBQcDAjAMBgNVHRMBAf8EAjAAMB0GA1UdDgQWBBQ+
|
||||
lVsLiXSRLAECs9OgkCEBS7jMmzAfBgNVHSMEGDAWgBSuSJ7chx1EoG/aouVgdAR4
|
||||
wpwAgDAyBggrBgEFBQcBAQQmMCQwIgYIKwYBBQUHMAKGFmh0dHA6Ly9lNy5pLmxl
|
||||
ODAeFw0yNTExMDYxMDUyMjBaFw0yNjAyMDQxMDUyMTlaMCExHzAdBgNVBAMMFiou
|
||||
YXV0aC5sb2NhbC5uaG9zdC5ydW4wWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAASI
|
||||
rTkZOM4ip42DCyDADXGc7oV3+OkimyTM3st2RIZWG28rFRwH0LebJV2cduq1Hdtl
|
||||
VxIEr+RhvyIL7gllueXUo4IC4jCCAt4wDgYDVR0PAQH/BAQDAgeAMB0GA1UdJQQW
|
||||
MBQGCCsGAQUFBwMBBggrBgEFBQcDAjAMBgNVHRMBAf8EAjAAMB0GA1UdDgQWBBTw
|
||||
bM86O381+aljU3oTUvwhZ90PCDAfBgNVHSMEGDAWgBSPDROi9i5+0VBsMxg4XVmO
|
||||
I3KRyjAyBggrBgEFBQcBAQQmMCQwIgYIKwYBBQUHMAKGFmh0dHA6Ly9lOC5pLmxl
|
||||
bmNyLm9yZy8wgd4GA1UdEQSB1jCB04IWKi5hdXRoLmxvY2FsLm5ob3N0LnJ1boIb
|
||||
Ki5kYXNoYm9hcmQubG9jYWwubmhvc3QucnVughQqLmRiLmxvY2FsLm5ob3N0LnJ1
|
||||
boIbKi5mdW5jdGlvbnMubG9jYWwubmhvc3QucnVughkqLmdyYXBocWwubG9jYWwu
|
||||
bmhvc3QucnVughgqLmhhc3VyYS5sb2NhbC5uaG9zdC5ydW6CGSoubWFpbGhvZy5s
|
||||
b2NhbC5uaG9zdC5ydW6CGSouc3RvcmFnZS5sb2NhbC5uaG9zdC5ydW4wEwYDVR0g
|
||||
BAwwCjAIBgZngQwBAgEwLQYDVR0fBCYwJDAioCCgHoYcaHR0cDovL2U3LmMubGVu
|
||||
Y3Iub3JnLzc3LmNybDCCAQUGCisGAQQB1nkCBAIEgfYEgfMA8QB2AN3cyjSV1+EW
|
||||
BeeVMvrHn/g9HFDf2wA6FBJ2Ciysu8gqAAABmaTDUHkAAAQDAEcwRQIgWudJ8XKA
|
||||
BT5jq5Tl0xQLNb953pBi22Tb0TIWk+RSqHgCIQDsTrLVMFaQTV7EFCY1tFhi5qae
|
||||
SCpEwwdFcnom/nz6EAB3AO08S9boBsKkogBX28sk4jgB31Ev7cSGxXAPIN23Pj/g
|
||||
AAABmaTDWAsAAAQDAEgwRgIhALxIgIiutEwgNcGw7/cAdjFqUugct4HlZezIOLLP
|
||||
rg69AiEA8YCaK41rJDYztEKUIJEq2J2ktSqGYcl9gNKC+SiR4acwCgYIKoZIzj0E
|
||||
AwMDaAAwZQIwVG9yOiMRfKFFyFj1R8X/5U67QD84OhZ0oM0SZsVhezLedG5b8eFf
|
||||
/cWraREi8xbFAjEA/6RXweGzl08F7EtqBDoiqitScI2rbwGtP6s/evL0zXTABZD2
|
||||
ih7AGxjtg80IqIRe
|
||||
BAwwCjAIBgZngQwBAgEwLQYDVR0fBCYwJDAioCCgHoYcaHR0cDovL2U4LmMubGVu
|
||||
Y3Iub3JnLzM0LmNybDCCAQQGCisGAQQB1nkCBAIEgfUEgfIA8AB2AEmcm2neHXzs
|
||||
/DbezYdkprhbrwqHgBnRVVL76esp3fjDAAABmlkBVgkAAAQDAEcwRQIhANH6Ml3u
|
||||
IM4nAzwAIjIjBjn8EWbn1ZHfgwO+rlSo5rzpAiATPKE8Mx5LK1IayG5VCK1eCDyc
|
||||
rzt1HNbP9WSrpuHx+gB2ABmG1Mcoqm/+ugNveCpNAZGqzi1yMQ+uzl1wQS0lTMfU
|
||||
AAABmlkBVgcAAAQDAEcwRQIgIT/DhsIj9Aw7qf/2lknJCr907dEqC3/+QN3zlcOj
|
||||
iKoCIQCTguinYjJPZwU2dblaRQ2q7MTCMT2ZENExltxwYG3GzjAKBggqhkjOPQQD
|
||||
AwNoADBlAjEA5nFoNrLyeC079YpRvdah/HZIA/lUBh+LOo/NcEBD3aTGs2z8hU8z
|
||||
H4vMy3OnfQ9TAjBxigm7zE5/3CAcGoSOr/P0TL52nh+lO4SUVxcbKgYB8A2yo6o/
|
||||
kUkG7PiRB0uUpNw=
|
||||
-----END CERTIFICATE-----
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIEVzCCAj+gAwIBAgIRAKp18eYrjwoiCWbTi7/UuqEwDQYJKoZIhvcNAQELBQAw
|
||||
TzELMAkGA1UEBhMCVVMxKTAnBgNVBAoTIEludGVybmV0IFNlY3VyaXR5IFJlc2Vh
|
||||
cmNoIEdyb3VwMRUwEwYDVQQDEwxJU1JHIFJvb3QgWDEwHhcNMjQwMzEzMDAwMDAw
|
||||
WhcNMjcwMzEyMjM1OTU5WjAyMQswCQYDVQQGEwJVUzEWMBQGA1UEChMNTGV0J3Mg
|
||||
RW5jcnlwdDELMAkGA1UEAxMCRTcwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAARB6AST
|
||||
CFh/vjcwDMCgQer+VtqEkz7JANurZxLP+U9TCeioL6sp5Z8VRvRbYk4P1INBmbef
|
||||
QHJFHCxcSjKmwtvGBWpl/9ra8HW0QDsUaJW2qOJqceJ0ZVFT3hbUHifBM/2jgfgw
|
||||
gfUwDgYDVR0PAQH/BAQDAgGGMB0GA1UdJQQWMBQGCCsGAQUFBwMCBggrBgEFBQcD
|
||||
ATASBgNVHRMBAf8ECDAGAQH/AgEAMB0GA1UdDgQWBBSuSJ7chx1EoG/aouVgdAR4
|
||||
wpwAgDAfBgNVHSMEGDAWgBR5tFnme7bl5AFzgAiIyBpY9umbbjAyBggrBgEFBQcB
|
||||
AQQmMCQwIgYIKwYBBQUHMAKGFmh0dHA6Ly94MS5pLmxlbmNyLm9yZy8wEwYDVR0g
|
||||
BAwwCjAIBgZngQwBAgEwJwYDVR0fBCAwHjAcoBqgGIYWaHR0cDovL3gxLmMubGVu
|
||||
Y3Iub3JnLzANBgkqhkiG9w0BAQsFAAOCAgEAjx66fDdLk5ywFn3CzA1w1qfylHUD
|
||||
aEf0QZpXcJseddJGSfbUUOvbNR9N/QQ16K1lXl4VFyhmGXDT5Kdfcr0RvIIVrNxF
|
||||
h4lqHtRRCP6RBRstqbZ2zURgqakn/Xip0iaQL0IdfHBZr396FgknniRYFckKORPG
|
||||
yM3QKnd66gtMst8I5nkRQlAg/Jb+Gc3egIvuGKWboE1G89NTsN9LTDD3PLj0dUMr
|
||||
OIuqVjLB8pEC6yk9enrlrqjXQgkLEYhXzq7dLafv5Vkig6Gl0nuuqjqfp0Q1bi1o
|
||||
yVNAlXe6aUXw92CcghC9bNsKEO1+M52YY5+ofIXlS/SEQbvVYYBLZ5yeiglV6t3S
|
||||
M6H+vTG0aP9YHzLn/KVOHzGQfXDP7qM5tkf+7diZe7o2fw6O7IvN6fsQXEQQj8TJ
|
||||
UXJxv2/uJhcuy/tSDgXwHM8Uk34WNbRT7zGTGkQRX0gsbjAea/jYAoWv0ZvQRwpq
|
||||
Pe79D/i7Cep8qWnA+7AE/3B3S/3dEEYmc0lpe1366A/6GEgk3ktr9PEoQrLChs6I
|
||||
tu3wnNLB2euC8IKGLQFpGtOO/2/hiAKjyajaBP25w1jF0Wl8Bbqne3uZ2q1GyPFJ
|
||||
YRmT7/OXpmOH/FVLtwS+8ng1cAmpCujPwteJZNcDG0sF2n/sc0+SQf49fdyUK0ty
|
||||
+VUwFj9tmWxyR/M=
|
||||
MIIEVjCCAj6gAwIBAgIQY5WTY8JOcIJxWRi/w9ftVjANBgkqhkiG9w0BAQsFADBP
|
||||
MQswCQYDVQQGEwJVUzEpMCcGA1UEChMgSW50ZXJuZXQgU2VjdXJpdHkgUmVzZWFy
|
||||
Y2ggR3JvdXAxFTATBgNVBAMTDElTUkcgUm9vdCBYMTAeFw0yNDAzMTMwMDAwMDBa
|
||||
Fw0yNzAzMTIyMzU5NTlaMDIxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1MZXQncyBF
|
||||
bmNyeXB0MQswCQYDVQQDEwJFODB2MBAGByqGSM49AgEGBSuBBAAiA2IABNFl8l7c
|
||||
S7QMApzSsvru6WyrOq44ofTUOTIzxULUzDMMNMchIJBwXOhiLxxxs0LXeb5GDcHb
|
||||
R6EToMffgSZjO9SNHfY9gjMy9vQr5/WWOrQTZxh7az6NSNnq3u2ubT6HTKOB+DCB
|
||||
9TAOBgNVHQ8BAf8EBAMCAYYwHQYDVR0lBBYwFAYIKwYBBQUHAwIGCCsGAQUFBwMB
|
||||
MBIGA1UdEwEB/wQIMAYBAf8CAQAwHQYDVR0OBBYEFI8NE6L2Ln7RUGwzGDhdWY4j
|
||||
cpHKMB8GA1UdIwQYMBaAFHm0WeZ7tuXkAXOACIjIGlj26ZtuMDIGCCsGAQUFBwEB
|
||||
BCYwJDAiBggrBgEFBQcwAoYWaHR0cDovL3gxLmkubGVuY3Iub3JnLzATBgNVHSAE
|
||||
DDAKMAgGBmeBDAECATAnBgNVHR8EIDAeMBygGqAYhhZodHRwOi8veDEuYy5sZW5j
|
||||
ci5vcmcvMA0GCSqGSIb3DQEBCwUAA4ICAQBnE0hGINKsCYWi0Xx1ygxD5qihEjZ0
|
||||
RI3tTZz1wuATH3ZwYPIp97kWEayanD1j0cDhIYzy4CkDo2jB8D5t0a6zZWzlr98d
|
||||
AQFNh8uKJkIHdLShy+nUyeZxc5bNeMp1Lu0gSzE4McqfmNMvIpeiwWSYO9w82Ob8
|
||||
otvXcO2JUYi3svHIWRm3+707DUbL51XMcY2iZdlCq4Wa9nbuk3WTU4gr6LY8MzVA
|
||||
aDQG2+4U3eJ6qUF10bBnR1uuVyDYs9RhrwucRVnfuDj29CMLTsplM5f5wSV5hUpm
|
||||
Uwp/vV7M4w4aGunt74koX71n4EdagCsL/Yk5+mAQU0+tue0JOfAV/R6t1k+Xk9s2
|
||||
HMQFeoxppfzAVC04FdG9M+AC2JWxmFSt6BCuh3CEey3fE52Qrj9YM75rtvIjsm/1
|
||||
Hl+u//Wqxnu1ZQ4jpa+VpuZiGOlWrqSP9eogdOhCGisnyewWJwRQOqK16wiGyZeR
|
||||
xs/Bekw65vwSIaVkBruPiTfMOo0Zh4gVa8/qJgMbJbyrwwG97z/PRgmLKCDl8z3d
|
||||
tA0Z7qq7fta0Gl24uyuB05dqI5J1LvAzKuWdIjT1tP8qCoxSE/xpix8hX2dt3h+/
|
||||
jujUgFPFZ0EVZ0xSyBNRF3MboGZnYXFUxpNjTWPKpagDHJQmqrAcDmWJnMsFY3jS
|
||||
u1igv3OefnWjSQ==
|
||||
-----END CERTIFICATE-----
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
-----BEGIN PRIVATE KEY-----
|
||||
MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgrfNUSjLV/7j7LSBf
|
||||
zL/hvGEuv+uvf3/aimqjecO7vcShRANCAATGx0o7t0pSrOoFc+pljtqJVxgaSW+w
|
||||
9D9C2WdysMeSKKOU+0MzaM4ynLUhETOpBs8E612mdcoeak+G1Emj6UVw
|
||||
MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgcrhROXQT85e+S8h8
|
||||
RE3Z7TPo3+WA2RmzJsXJbXkbi5qhRANCAASIrTkZOM4ip42DCyDADXGc7oV3+Oki
|
||||
myTM3st2RIZWG28rFRwH0LebJV2cduq1HdtlVxIEr+RhvyIL7gllueXU
|
||||
-----END PRIVATE KEY-----
|
||||
|
||||
@@ -3,12 +3,13 @@ NEXT_PUBLIC_ENV=dev
|
||||
NEXT_PUBLIC_NHOST_PLATFORM=false
|
||||
|
||||
# Environment Variables for Self Hosting and Local Development
|
||||
NEXT_PUBLIC_NHOST_AUTH_URL=https://local.auth.nhost.local.run/v1
|
||||
NEXT_PUBLIC_NHOST_AUTH_URL=https://local.auth.local.nhost.run/v1
|
||||
NEXT_PUBLIC_NHOST_CONFIGSERVER_URL=https://local.dashboard.local.nhost.run/v1/configserver/graphql
|
||||
NEXT_PUBLIC_NHOST_FUNCTIONS_URL=https://local.functions.local.nhost.run/v1
|
||||
NEXT_PUBLIC_NHOST_GRAPHQL_URL=https://local.graphql.local.nhost.run/v1
|
||||
NEXT_PUBLIC_NHOST_STORAGE_URL=https://local.storage.local.nhost.run/v1
|
||||
NEXT_PUBLIC_NHOST_HASURA_CONSOLE_URL=https://local.hasura.local.nhost.run
|
||||
NEXT_PUBLIC_NHOST_HASURA_MIGRATIONS_API_URL=https://local.hasura.local.nhost.run/v1/migrations
|
||||
NEXT_PUBLIC_NHOST_HASURA_CONSOLE_URL=https://local.hasura.local.nhost.run/console
|
||||
NEXT_PUBLIC_NHOST_HASURA_MIGRATIONS_API_URL=https://local.hasura.local.nhost.run/apis/migrate
|
||||
NEXT_PUBLIC_NHOST_HASURA_API_URL=https://local.hasura.local.nhost.run
|
||||
|
||||
# Environment Variables when running the Nhost Dashboard against the Nhost Backend
|
||||
|
||||
@@ -1,7 +1,41 @@
|
||||
## [@nhost/dashboard@2.42.0] - 2025-11-12
|
||||
|
||||
### 🚀 Features
|
||||
|
||||
- *(dashboard)* Datatable design improvements (#3657)
|
||||
|
||||
|
||||
### ⚙️ Miscellaneous Tasks
|
||||
|
||||
- *(dashboard)* Remove v2 ui components from datatable (#3568)
|
||||
|
||||
## [@nhost/dashboard@2.41.0] - 2025-11-04
|
||||
|
||||
### 🚀 Features
|
||||
|
||||
- *(auth)* Added endpoints to retrieve and refresh oauth2 providers' tokens (#3614)
|
||||
- *(dashboard)* Get github repositories from github itself (#3640)
|
||||
|
||||
|
||||
### 🐛 Bug Fixes
|
||||
|
||||
- *(dashboard)* Update SQL editor to use correct hasura migrations API URL (#3645)
|
||||
|
||||
# Changelog
|
||||
|
||||
All notable changes to this project will be documented in this file.
|
||||
|
||||
## [@nhost/dashboard@2.40.0] - 2025-10-27
|
||||
|
||||
### 🚀 Features
|
||||
|
||||
- *(dashboard)* Allow configuring CSP header (#3627)
|
||||
|
||||
|
||||
### ⚙️ Miscellaneous Tasks
|
||||
|
||||
- *(dashboard)* Various improvements to support ticket page (#3630)
|
||||
|
||||
## [@nhost/dashboard@2.39.0] - 2025-10-22
|
||||
|
||||
### 🚀 Features
|
||||
|
||||
@@ -82,6 +82,15 @@ This will connect the Nhost Dashboard to your locally running Nhost backend.
|
||||
| `NEXT_PUBLIC_NHOST_HASURA_MIGRATIONS_API_URL` | The URL of Hasura's Migrations service. When working locally, point it to the Migrations service started by the CLI. |
|
||||
| `NEXT_PUBLIC_NHOST_HASURA_API_URL` | The URL of Hasura's Schema and Metadata API. When working locally, point it to the Schema and Metadata API started by the CLI. When self-hosting, point it to the self-hosted Schema and Metadata API. |
|
||||
|
||||
### Content Security Policy (CSP) Configuration
|
||||
|
||||
The dashboard supports build-time CSP configuration to enable self-hosted deployments on custom domains.
|
||||
|
||||
| Name | Description |
|
||||
| ------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| `CSP_MODE` | Controls CSP behavior. Options: `nhost` (default, uses Nhost Cloud CSP), `disabled` (no CSP headers), `custom` (use custom CSP via `CSP_HEADER`). For self-hosted deployments on custom domains, set to `disabled` or `custom`. |
|
||||
| `CSP_HEADER` | Custom Content Security Policy header value. Only used when `CSP_MODE=custom`. Should be a complete CSP string (e.g., `default-src 'self'; script-src 'self' 'unsafe-eval'; ...`). |
|
||||
|
||||
### Other Environment Variables
|
||||
|
||||
| Name | Description |
|
||||
|
||||
@@ -102,7 +102,7 @@ test('should create a table with nullable columns', async ({
|
||||
page.getByRole('link', { name: tableName, exact: true }),
|
||||
).toBeVisible();
|
||||
await page
|
||||
.locator(`li:has-text("${tableName}") #table-management-menu button`)
|
||||
.locator(`li:has-text("${tableName}") #table-management-menu-${tableName}`)
|
||||
.click();
|
||||
await page.getByText('Edit Table').click();
|
||||
await expect(page.locator('h2:has-text("Edit Table")')).toBeVisible();
|
||||
@@ -143,7 +143,7 @@ test('should create a table with an identity column', async ({
|
||||
page.getByRole('link', { name: tableName, exact: true }),
|
||||
).toBeVisible();
|
||||
await page
|
||||
.locator(`li:has-text("${tableName}") #table-management-menu button`)
|
||||
.locator(`li:has-text("${tableName}") #table-management-menu-${tableName}`)
|
||||
.click();
|
||||
await page.getByText('Edit Table').click();
|
||||
await expect(page.locator('h2:has-text("Edit Table")')).toBeVisible();
|
||||
@@ -267,7 +267,7 @@ test('should be able to create a table with a composite key', async ({
|
||||
).toBeVisible();
|
||||
|
||||
await page
|
||||
.locator(`li:has-text("${tableName}") #table-management-menu button`)
|
||||
.locator(`li:has-text("${tableName}") #table-management-menu-${tableName}`)
|
||||
.click();
|
||||
await page.getByText('Edit Table').click();
|
||||
await expect(page.locator('div[data-testid="id"]')).toBeVisible();
|
||||
|
||||
@@ -41,7 +41,7 @@ test('should create a table with role permissions to select row', async ({
|
||||
|
||||
// Press three horizontal dots more options button next to the table name
|
||||
await page
|
||||
.locator(`li:has-text("${tableName}") #table-management-menu button`)
|
||||
.locator(`li:has-text("${tableName}") #table-management-menu-${tableName}`)
|
||||
.click();
|
||||
|
||||
await page.getByRole('menuitem', { name: /edit permissions/i }).click();
|
||||
@@ -89,7 +89,7 @@ test('should create a table with role permissions and a custom check to select r
|
||||
|
||||
// Press three horizontal dots more options button next to the table name
|
||||
await page
|
||||
.locator(`li:has-text("${tableName}") #table-management-menu button`)
|
||||
.locator(`li:has-text("${tableName}") #table-management-menu-${tableName}`)
|
||||
.click();
|
||||
|
||||
await page.getByRole('menuitem', { name: /edit permissions/i }).click();
|
||||
@@ -114,7 +114,7 @@ test('should create a table with role permissions and a custom check to select r
|
||||
|
||||
await page.getByText('Select variable...', { exact: true }).click();
|
||||
|
||||
const variableSelector = await page.locator('input[role="combobox"]');
|
||||
const variableSelector = page.locator('input[role="combobox"]');
|
||||
|
||||
await variableSelector.fill('X-Hasura-User-Id');
|
||||
|
||||
|
||||
@@ -4,21 +4,31 @@ const withBundleAnalyzer = require('@next/bundle-analyzer')({
|
||||
});
|
||||
const { version } = require('./package.json');
|
||||
|
||||
const cspHeader = `
|
||||
default-src 'self' *.nhost.run wss://*.nhost.run nhost.run wss://nhost.run;
|
||||
script-src 'self' 'unsafe-eval' cdn.segment.com js.stripe.com challenges.cloudflare.com googletagmanager.com;
|
||||
connect-src 'self' *.nhost.run wss://*.nhost.run nhost.run wss://nhost.run discord.com api.segment.io api.segment.com cdn.segment.com nhost.zendesk.com;
|
||||
style-src 'self' 'unsafe-inline';
|
||||
img-src 'self' blob: data: github.com avatars.githubusercontent.com s.gravatar.com *.nhost.run nhost.run;
|
||||
font-src 'self' data:;
|
||||
object-src 'none';
|
||||
base-uri 'self';
|
||||
form-action 'self';
|
||||
frame-ancestors 'none';
|
||||
frame-src 'self' js.stripe.com challenges.cloudflare.com;
|
||||
block-all-mixed-content;
|
||||
upgrade-insecure-requests;
|
||||
`;
|
||||
function getCspHeader() {
|
||||
switch (process.env.CSP_MODE) {
|
||||
case 'disabled':
|
||||
return null;
|
||||
case 'custom':
|
||||
return process.env.CSP_HEADER || null;
|
||||
case 'nhost':
|
||||
default:
|
||||
return [
|
||||
"default-src 'self' *.nhost.run wss://*.nhost.run nhost.run wss://nhost.run",
|
||||
"script-src 'self' 'unsafe-eval' cdn.segment.com js.stripe.com challenges.cloudflare.com googletagmanager.com",
|
||||
"connect-src 'self' *.nhost.run wss://*.nhost.run nhost.run wss://nhost.run discord.com api.segment.io api.segment.com cdn.segment.com nhost.zendesk.com api.github.com",
|
||||
"style-src 'self' 'unsafe-inline'",
|
||||
"img-src 'self' blob: data: github.com avatars.githubusercontent.com s.gravatar.com *.nhost.run nhost.run",
|
||||
"font-src 'self' data:",
|
||||
"object-src 'none'",
|
||||
"base-uri 'self'",
|
||||
"form-action 'self'",
|
||||
"frame-ancestors 'none'",
|
||||
"frame-src 'self' js.stripe.com challenges.cloudflare.com",
|
||||
"block-all-mixed-content",
|
||||
"upgrade-insecure-requests",
|
||||
].join('; ') + ';';
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = withBundleAnalyzer({
|
||||
reactStrictMode: false,
|
||||
@@ -34,13 +44,19 @@ module.exports = withBundleAnalyzer({
|
||||
dirs: ['src'],
|
||||
},
|
||||
async headers() {
|
||||
const cspHeader = getCspHeader();
|
||||
|
||||
if (!cspHeader) {
|
||||
return []; // No CSP headers
|
||||
}
|
||||
|
||||
return [
|
||||
{
|
||||
source: '/(.*)',
|
||||
source: '/:path*',
|
||||
headers: [
|
||||
{
|
||||
key: 'Content-Security-Policy',
|
||||
value: cspHeader.replace(/\s+/g, ' ').trim(),
|
||||
value: cspHeader,
|
||||
},
|
||||
{
|
||||
key: 'X-Frame-Options',
|
||||
@@ -110,4 +126,4 @@ module.exports = withBundleAnalyzer({
|
||||
},
|
||||
];
|
||||
},
|
||||
});
|
||||
});
|
||||
@@ -38,6 +38,7 @@
|
||||
"@graphiql/react": "^0.22.3",
|
||||
"@graphiql/toolkit": "^0.9.1",
|
||||
"@headlessui/react": "^1.7.18",
|
||||
"@hello-pangea/dnd": "^18.0.1",
|
||||
"@heroicons/react": "^1.0.6",
|
||||
"@hookform/resolvers": "^3.9.0",
|
||||
"@iarna/toml": "^2.2.5",
|
||||
@@ -60,7 +61,7 @@
|
||||
"@radix-ui/react-radio-group": "^1.2.0",
|
||||
"@radix-ui/react-select": "^2.1.2",
|
||||
"@radix-ui/react-separator": "^1.1.0",
|
||||
"@radix-ui/react-slot": "^1.1.1",
|
||||
"@radix-ui/react-slot": "^1.1.2",
|
||||
"@radix-ui/react-switch": "^1.2.6",
|
||||
"@radix-ui/react-tabs": "^1.1.3",
|
||||
"@radix-ui/react-tooltip": "^1.1.2",
|
||||
@@ -93,7 +94,7 @@
|
||||
"just-kebab-case": "^4.2.0",
|
||||
"jwt-decode": "^4.0.0",
|
||||
"lodash.debounce": "^4.0.8",
|
||||
"lucide-react": "^0.416.0",
|
||||
"lucide-react": "^0.552.0",
|
||||
"next": "^14.2.31",
|
||||
"next-nprogress-bar": "^2.3.13",
|
||||
"next-seo": "^6.5.0",
|
||||
@@ -125,7 +126,7 @@
|
||||
"timezones-list": "^3.1.0",
|
||||
"utility-types": "^3.11.0",
|
||||
"uuid": "^9.0.1",
|
||||
"validator": "^13.11.0",
|
||||
"validator": "^13.15.20",
|
||||
"yup": "^1.4.0",
|
||||
"yup-password": "^0.2.2",
|
||||
"zod": "^3.23.8"
|
||||
@@ -231,7 +232,8 @@
|
||||
}
|
||||
},
|
||||
"overrides": {
|
||||
"esbuild@<=0.24.2": ">=0.25.0"
|
||||
"esbuild@<=0.24.2": ">=0.25.0",
|
||||
"js-yaml@<=4.1.0": ">=4.1.1"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
170
dashboard/pnpm-lock.yaml
generated
170
dashboard/pnpm-lock.yaml
generated
@@ -6,6 +6,7 @@ settings:
|
||||
|
||||
overrides:
|
||||
esbuild@<=0.24.2: '>=0.25.0'
|
||||
js-yaml@<=4.1.0: '>=4.1.1'
|
||||
|
||||
packageExtensionsChecksum: sha256-gRFeykwiwMfEE6etcYx6N48XwVeKzxbqNveL7KTQgSQ=
|
||||
|
||||
@@ -55,6 +56,9 @@ importers:
|
||||
'@headlessui/react':
|
||||
specifier: ^1.7.18
|
||||
version: 1.7.19(react-dom@18.2.0(react@18.2.0))(react@18.2.0)
|
||||
'@hello-pangea/dnd':
|
||||
specifier: ^18.0.1
|
||||
version: 18.0.1(@types/react@18.2.73)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)
|
||||
'@heroicons/react':
|
||||
specifier: ^1.0.6
|
||||
version: 1.0.6(react@18.2.0)
|
||||
@@ -122,8 +126,8 @@ importers:
|
||||
specifier: ^1.1.0
|
||||
version: 1.1.0(@types/react-dom@18.3.0)(@types/react@18.2.73)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)
|
||||
'@radix-ui/react-slot':
|
||||
specifier: ^1.1.1
|
||||
version: 1.1.2(@types/react@18.2.73)(react@18.2.0)
|
||||
specifier: ^1.1.2
|
||||
version: 1.2.3(@types/react@18.2.73)(react@18.2.0)
|
||||
'@radix-ui/react-switch':
|
||||
specifier: ^1.2.6
|
||||
version: 1.2.6(@types/react-dom@18.3.0)(@types/react@18.2.73)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)
|
||||
@@ -221,8 +225,8 @@ importers:
|
||||
specifier: ^4.0.8
|
||||
version: 4.0.8
|
||||
lucide-react:
|
||||
specifier: ^0.416.0
|
||||
version: 0.416.0(react@18.2.0)
|
||||
specifier: ^0.552.0
|
||||
version: 0.552.0(react@18.2.0)
|
||||
next:
|
||||
specifier: ^14.2.31
|
||||
version: 14.2.32(@babel/core@7.26.10)(@playwright/test@1.54.1)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)
|
||||
@@ -317,8 +321,8 @@ importers:
|
||||
specifier: ^9.0.1
|
||||
version: 9.0.1
|
||||
validator:
|
||||
specifier: ^13.11.0
|
||||
version: 13.12.0
|
||||
specifier: ^13.15.20
|
||||
version: 13.15.23
|
||||
yup:
|
||||
specifier: ^1.4.0
|
||||
version: 1.5.0
|
||||
@@ -2063,6 +2067,12 @@ packages:
|
||||
react: ^16 || ^17 || ^18
|
||||
react-dom: ^16 || ^17 || ^18
|
||||
|
||||
'@hello-pangea/dnd@18.0.1':
|
||||
resolution: {integrity: sha512-xojVWG8s/TGrKT1fC8K2tIWeejJYTAeJuj36zM//yEm/ZrnZUSFGS15BpO+jGZT1ybWvyXmeDJwPYb4dhWlbZQ==}
|
||||
peerDependencies:
|
||||
react: ^18.0.0 || ^19.0.0
|
||||
react-dom: ^18.0.0 || ^19.0.0
|
||||
|
||||
'@heroicons/react@1.0.6':
|
||||
resolution: {integrity: sha512-JJCXydOFWMDpCP4q13iEplA503MQO3xLoZiKum+955ZCtHINWnx26CUxVxxFQu/uLb4LW3ge15ZpzIkXKkJ8oQ==}
|
||||
peerDependencies:
|
||||
@@ -4048,6 +4058,9 @@ packages:
|
||||
'@types/urijs@1.19.25':
|
||||
resolution: {integrity: sha512-XOfUup9r3Y06nFAZh3WvO0rBU4OtlfPB/vgxpjg+NRdGU6CN6djdc6OEiH+PcqHCY6eFLo9Ista73uarf4gnBg==}
|
||||
|
||||
'@types/use-sync-external-store@0.0.6':
|
||||
resolution: {integrity: sha512-zFDAD+tlpf2r4asuHEj0XH6pY6i0g5NeAHPn+15wk3BV6JA69eERFXC1gyGThDkVa1zCyKr5jox1+2LbV/AMLg==}
|
||||
|
||||
'@types/uuid@9.0.8':
|
||||
resolution: {integrity: sha512-jg+97EGIcY9AGHJJRaaPVgetKDsrTgbRjQ5Msgjh/DQKEFl0DtyRr/VCOyD1T2R1MNeWPK/u7JoGhlDZnKBAfA==}
|
||||
|
||||
@@ -4964,6 +4977,9 @@ packages:
|
||||
resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==}
|
||||
engines: {node: '>= 8'}
|
||||
|
||||
css-box-model@1.2.1:
|
||||
resolution: {integrity: sha512-a7Vr4Q/kd/aw96bnJG332W9V9LkJO69JRcaCYDUqjp6/z0w6VcZjgAcTbgFxEPfBgdnAwlh3iwu+hLopa+flJw==}
|
||||
|
||||
css.escape@1.5.1:
|
||||
resolution: {integrity: sha512-YUifsXXuknHlUsmlgyY0PKzgPOr7/FjCePfHNt0jxm83wHZi44VDMQ7/fGNkjY3/jV1MC+1CmZbaHzugyeRtpg==}
|
||||
|
||||
@@ -6322,8 +6338,8 @@ packages:
|
||||
js-tokens@9.0.1:
|
||||
resolution: {integrity: sha512-mxa9E9ITFOt0ban3j6L5MpjwegGz6lBQmM1IJkWeBZGcMxto50+eWdjC/52xDbS2vy0k7vIMK0Fe2wfL9OQSpQ==}
|
||||
|
||||
js-yaml@4.1.0:
|
||||
resolution: {integrity: sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==}
|
||||
js-yaml@4.1.1:
|
||||
resolution: {integrity: sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==}
|
||||
hasBin: true
|
||||
|
||||
jsdom@22.1.0:
|
||||
@@ -6547,8 +6563,8 @@ packages:
|
||||
lru-cache@5.1.1:
|
||||
resolution: {integrity: sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==}
|
||||
|
||||
lucide-react@0.416.0:
|
||||
resolution: {integrity: sha512-wPWxTzdss1CTz2aqcNWNlbh4YSnH9neJWP3RaeXepxpLCTW+pmu7WcT/wxJe+Q7Y7DqGOxAqakJv0pIK3431Ag==}
|
||||
lucide-react@0.552.0:
|
||||
resolution: {integrity: sha512-g9WCjmfwqbexSnZE+2cl21PCfXOcqnGeWeMTNAOGEfpPbm/ZF4YIq77Z8qWrxbu660EKuLB4nSLggoKnCb+isw==}
|
||||
peerDependencies:
|
||||
react: ^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0
|
||||
|
||||
@@ -7407,6 +7423,9 @@ packages:
|
||||
queue-microtask@1.2.3:
|
||||
resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==}
|
||||
|
||||
raf-schd@4.0.3:
|
||||
resolution: {integrity: sha512-tQkJl2GRWh83ui2DiPTJz9wEiMN20syf+5oKfB03yYP7ioZcJwsIK8FjrtLwH1m7C7e+Tt2yYBlrOpdT+dyeIQ==}
|
||||
|
||||
randombytes@2.1.0:
|
||||
resolution: {integrity: sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==}
|
||||
|
||||
@@ -7481,6 +7500,18 @@ packages:
|
||||
react:
|
||||
optional: true
|
||||
|
||||
react-redux@9.2.0:
|
||||
resolution: {integrity: sha512-ROY9fvHhwOD9ySfrF0wmvu//bKCQ6AeZZq1nJNtbDC+kk5DuSuNX/n6YWYF/SYy7bSba4D4FSz8DJeKY/S/r+g==}
|
||||
peerDependencies:
|
||||
'@types/react': ^18.2.25 || ^19
|
||||
react: ^18.0 || ^19
|
||||
redux: ^5.0.0
|
||||
peerDependenciesMeta:
|
||||
'@types/react':
|
||||
optional: true
|
||||
redux:
|
||||
optional: true
|
||||
|
||||
react-refresh@0.17.0:
|
||||
resolution: {integrity: sha512-z6F7K9bV85EfseRCp2bzrpyQ0Gkw1uLoCel9XBVWPg/TjRj94SkJzUTGfOa4bs7iJvBWtQG0Wq7wnI0syw3EBQ==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
@@ -7598,6 +7629,9 @@ packages:
|
||||
resolution: {integrity: sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg==}
|
||||
engines: {node: '>=8'}
|
||||
|
||||
redux@5.0.1:
|
||||
resolution: {integrity: sha512-M9/ELqF6fy8FwmkpnF0S3YKOqMyoWJ4+CS5Efg2ct3oY9daQvd/Pc71FpGZsVsbl3Cpb+IIcjBDUnnyBdQbq4w==}
|
||||
|
||||
reflect.getprototypeof@1.0.10:
|
||||
resolution: {integrity: sha512-00o4I+DVrefhv+nX0ulyi3biSHCPDe+yLv5o/p6d/UVlirijB8E16FtfwSAi4g3tcqrQ4lRAqQSoFEZJehYEcw==}
|
||||
engines: {node: '>= 0.4'}
|
||||
@@ -8206,6 +8240,9 @@ packages:
|
||||
tiny-case@1.0.3:
|
||||
resolution: {integrity: sha512-Eet/eeMhkO6TX8mnUteS9zgPbUMQa4I6Kkp5ORiBD5476/m+PIRiumP5tmh5ioJpH7k51Kehawy2UDfsnxxY8Q==}
|
||||
|
||||
tiny-invariant@1.3.3:
|
||||
resolution: {integrity: sha512-+FbBPE1o9QAYvviau/qC5SE3caw21q3xkvWKBtja5vgqOWIHHJ3ioaq1VPfn/Szqctz2bU/oYeKd9/z5BL+PVg==}
|
||||
|
||||
tinybench@2.9.0:
|
||||
resolution: {integrity: sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==}
|
||||
|
||||
@@ -8558,8 +8595,8 @@ packages:
|
||||
v8-compile-cache-lib@3.0.1:
|
||||
resolution: {integrity: sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==}
|
||||
|
||||
validator@13.12.0:
|
||||
resolution: {integrity: sha512-c1Q0mCiPlgdTVVVIJIrBuxNicYE+t/7oKeI9MWLj3fh/uq2Pxh/3eeWbVZ4OcGW1TUf53At0njHw5SMdA3tmMg==}
|
||||
validator@13.15.23:
|
||||
resolution: {integrity: sha512-4yoz1kEWqUjzi5zsPbAS/903QXSYp0UOtHsPpp7p9rHAw/W+dkInskAE386Fat3oKRROwO98d9ZB0G4cObgUyw==}
|
||||
engines: {node: '>= 0.10'}
|
||||
|
||||
vfile-message@4.0.2:
|
||||
@@ -8576,7 +8613,7 @@ packages:
|
||||
vite-tsconfig-paths@4.3.2:
|
||||
resolution: {integrity: sha512-0Vd/a6po6Q+86rPlntHye7F31zA2URZMbH8M3saAZ/xR9QoGN/L21bxEGfXdWmFdNkqPpRdxFT7nmNe12e9/uA==}
|
||||
peerDependencies:
|
||||
vite: '>=4.5.14'
|
||||
vite: '*'
|
||||
peerDependenciesMeta:
|
||||
vite:
|
||||
optional: true
|
||||
@@ -8900,7 +8937,7 @@ snapshots:
|
||||
dependencies:
|
||||
'@jsdevtools/ono': 7.1.3
|
||||
'@types/json-schema': 7.0.15
|
||||
js-yaml: 4.1.0
|
||||
js-yaml: 4.1.1
|
||||
|
||||
'@apidevtools/openapi-schemas@2.1.0': {}
|
||||
|
||||
@@ -8946,7 +8983,7 @@ snapshots:
|
||||
'@babel/core': 7.26.10
|
||||
'@babel/generator': 7.28.3
|
||||
'@babel/parser': 7.28.3
|
||||
'@babel/runtime': 7.26.10
|
||||
'@babel/runtime': 7.28.4
|
||||
'@babel/traverse': 7.28.3
|
||||
'@babel/types': 7.28.2
|
||||
babel-preset-fbjs: 3.4.0(@babel/core@7.26.10)
|
||||
@@ -10094,7 +10131,7 @@ snapshots:
|
||||
'@emotion/babel-plugin@11.11.0':
|
||||
dependencies:
|
||||
'@babel/helper-module-imports': 7.27.1
|
||||
'@babel/runtime': 7.26.10
|
||||
'@babel/runtime': 7.28.4
|
||||
'@emotion/hash': 0.9.1
|
||||
'@emotion/memoize': 0.8.1
|
||||
'@emotion/serialize': 1.1.4
|
||||
@@ -10299,7 +10336,7 @@ snapshots:
|
||||
globals: 13.24.0
|
||||
ignore: 5.3.2
|
||||
import-fresh: 3.3.0
|
||||
js-yaml: 4.1.0
|
||||
js-yaml: 4.1.1
|
||||
minimatch: 3.1.2
|
||||
strip-json-comments: 3.1.1
|
||||
transitivePeerDependencies:
|
||||
@@ -10934,6 +10971,18 @@ snapshots:
|
||||
react: 18.2.0
|
||||
react-dom: 18.2.0(react@18.2.0)
|
||||
|
||||
'@hello-pangea/dnd@18.0.1(@types/react@18.2.73)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)':
|
||||
dependencies:
|
||||
'@babel/runtime': 7.28.4
|
||||
css-box-model: 1.2.1
|
||||
raf-schd: 4.0.3
|
||||
react: 18.2.0
|
||||
react-dom: 18.2.0(react@18.2.0)
|
||||
react-redux: 9.2.0(@types/react@18.2.73)(react@18.2.0)(redux@5.0.1)
|
||||
redux: 5.0.1
|
||||
transitivePeerDependencies:
|
||||
- '@types/react'
|
||||
|
||||
'@heroicons/react@1.0.6(react@18.2.0)':
|
||||
dependencies:
|
||||
react: 18.2.0
|
||||
@@ -10971,7 +11020,7 @@ snapshots:
|
||||
loglevel: 1.9.2
|
||||
loglevel-plugin-prefix: 0.8.4
|
||||
minimatch: 6.2.0
|
||||
validator: 13.12.0
|
||||
validator: 13.15.23
|
||||
transitivePeerDependencies:
|
||||
- encoding
|
||||
|
||||
@@ -11273,7 +11322,7 @@ snapshots:
|
||||
|
||||
'@mui/base@5.0.0-beta.40(@types/react@18.2.73)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)':
|
||||
dependencies:
|
||||
'@babel/runtime': 7.26.10
|
||||
'@babel/runtime': 7.28.4
|
||||
'@floating-ui/react-dom': 2.1.1(react-dom@18.2.0(react@18.2.0))(react@18.2.0)
|
||||
'@mui/types': 7.2.14(@types/react@18.2.73)
|
||||
'@mui/utils': 5.15.14(@types/react@18.2.73)(react@18.2.0)
|
||||
@@ -11310,7 +11359,7 @@ snapshots:
|
||||
|
||||
'@mui/private-theming@5.15.14(@types/react@18.2.73)(react@18.2.0)':
|
||||
dependencies:
|
||||
'@babel/runtime': 7.26.10
|
||||
'@babel/runtime': 7.28.4
|
||||
'@mui/utils': 5.15.14(@types/react@18.2.73)(react@18.2.0)
|
||||
prop-types: 15.8.1
|
||||
react: 18.2.0
|
||||
@@ -11319,7 +11368,7 @@ snapshots:
|
||||
|
||||
'@mui/styled-engine@5.15.14(@emotion/react@11.11.4(@types/react@18.2.73)(react@18.2.0))(@emotion/styled@11.11.5(@emotion/react@11.11.4(@types/react@18.2.73)(react@18.2.0))(@types/react@18.2.73)(react@18.2.0))(react@18.2.0)':
|
||||
dependencies:
|
||||
'@babel/runtime': 7.26.10
|
||||
'@babel/runtime': 7.28.4
|
||||
'@emotion/cache': 11.11.0
|
||||
csstype: 3.1.3
|
||||
prop-types: 15.8.1
|
||||
@@ -11350,7 +11399,7 @@ snapshots:
|
||||
|
||||
'@mui/utils@5.15.14(@types/react@18.2.73)(react@18.2.0)':
|
||||
dependencies:
|
||||
'@babel/runtime': 7.26.10
|
||||
'@babel/runtime': 7.28.4
|
||||
'@types/prop-types': 15.7.12
|
||||
prop-types: 15.8.1
|
||||
react: 18.2.0
|
||||
@@ -11571,7 +11620,7 @@ snapshots:
|
||||
|
||||
'@radix-ui/primitive@1.0.1':
|
||||
dependencies:
|
||||
'@babel/runtime': 7.26.10
|
||||
'@babel/runtime': 7.28.4
|
||||
|
||||
'@radix-ui/primitive@1.1.0': {}
|
||||
|
||||
@@ -11698,7 +11747,7 @@ snapshots:
|
||||
|
||||
'@radix-ui/react-compose-refs@1.0.1(@types/react@18.2.73)(react@18.2.0)':
|
||||
dependencies:
|
||||
'@babel/runtime': 7.26.10
|
||||
'@babel/runtime': 7.28.4
|
||||
react: 18.2.0
|
||||
optionalDependencies:
|
||||
'@types/react': 18.2.73
|
||||
@@ -11723,7 +11772,7 @@ snapshots:
|
||||
|
||||
'@radix-ui/react-context@1.0.1(@types/react@18.2.73)(react@18.2.0)':
|
||||
dependencies:
|
||||
'@babel/runtime': 7.26.10
|
||||
'@babel/runtime': 7.28.4
|
||||
react: 18.2.0
|
||||
optionalDependencies:
|
||||
'@types/react': 18.2.73
|
||||
@@ -11748,7 +11797,7 @@ snapshots:
|
||||
|
||||
'@radix-ui/react-dialog@1.0.5(@types/react-dom@18.3.0)(@types/react@18.2.73)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)':
|
||||
dependencies:
|
||||
'@babel/runtime': 7.26.10
|
||||
'@babel/runtime': 7.28.4
|
||||
'@radix-ui/primitive': 1.0.1
|
||||
'@radix-ui/react-compose-refs': 1.0.1(@types/react@18.2.73)(react@18.2.0)
|
||||
'@radix-ui/react-context': 1.0.1(@types/react@18.2.73)(react@18.2.0)
|
||||
@@ -11799,7 +11848,7 @@ snapshots:
|
||||
|
||||
'@radix-ui/react-dismissable-layer@1.0.5(@types/react-dom@18.3.0)(@types/react@18.2.73)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)':
|
||||
dependencies:
|
||||
'@babel/runtime': 7.26.10
|
||||
'@babel/runtime': 7.28.4
|
||||
'@radix-ui/primitive': 1.0.1
|
||||
'@radix-ui/react-compose-refs': 1.0.1(@types/react@18.2.73)(react@18.2.0)
|
||||
'@radix-ui/react-primitive': 1.0.3(@types/react-dom@18.3.0)(@types/react@18.2.73)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)
|
||||
@@ -11854,7 +11903,7 @@ snapshots:
|
||||
|
||||
'@radix-ui/react-focus-guards@1.0.1(@types/react@18.2.73)(react@18.2.0)':
|
||||
dependencies:
|
||||
'@babel/runtime': 7.26.10
|
||||
'@babel/runtime': 7.28.4
|
||||
react: 18.2.0
|
||||
optionalDependencies:
|
||||
'@types/react': 18.2.73
|
||||
@@ -11873,7 +11922,7 @@ snapshots:
|
||||
|
||||
'@radix-ui/react-focus-scope@1.0.4(@types/react-dom@18.3.0)(@types/react@18.2.73)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)':
|
||||
dependencies:
|
||||
'@babel/runtime': 7.26.10
|
||||
'@babel/runtime': 7.28.4
|
||||
'@radix-ui/react-compose-refs': 1.0.1(@types/react@18.2.73)(react@18.2.0)
|
||||
'@radix-ui/react-primitive': 1.0.3(@types/react-dom@18.3.0)(@types/react@18.2.73)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)
|
||||
'@radix-ui/react-use-callback-ref': 1.0.1(@types/react@18.2.73)(react@18.2.0)
|
||||
@@ -11924,7 +11973,7 @@ snapshots:
|
||||
|
||||
'@radix-ui/react-id@1.0.1(@types/react@18.2.73)(react@18.2.0)':
|
||||
dependencies:
|
||||
'@babel/runtime': 7.26.10
|
||||
'@babel/runtime': 7.28.4
|
||||
'@radix-ui/react-use-layout-effect': 1.0.1(@types/react@18.2.73)(react@18.2.0)
|
||||
react: 18.2.0
|
||||
optionalDependencies:
|
||||
@@ -12033,7 +12082,7 @@ snapshots:
|
||||
|
||||
'@radix-ui/react-portal@1.0.4(@types/react-dom@18.3.0)(@types/react@18.2.73)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)':
|
||||
dependencies:
|
||||
'@babel/runtime': 7.26.10
|
||||
'@babel/runtime': 7.28.4
|
||||
'@radix-ui/react-primitive': 1.0.3(@types/react-dom@18.3.0)(@types/react@18.2.73)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)
|
||||
react: 18.2.0
|
||||
react-dom: 18.2.0(react@18.2.0)
|
||||
@@ -12063,7 +12112,7 @@ snapshots:
|
||||
|
||||
'@radix-ui/react-presence@1.0.1(@types/react-dom@18.3.0)(@types/react@18.2.73)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)':
|
||||
dependencies:
|
||||
'@babel/runtime': 7.26.10
|
||||
'@babel/runtime': 7.28.4
|
||||
'@radix-ui/react-compose-refs': 1.0.1(@types/react@18.2.73)(react@18.2.0)
|
||||
'@radix-ui/react-use-layout-effect': 1.0.1(@types/react@18.2.73)(react@18.2.0)
|
||||
react: 18.2.0
|
||||
@@ -12094,7 +12143,7 @@ snapshots:
|
||||
|
||||
'@radix-ui/react-primitive@1.0.3(@types/react-dom@18.3.0)(@types/react@18.2.73)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)':
|
||||
dependencies:
|
||||
'@babel/runtime': 7.26.10
|
||||
'@babel/runtime': 7.28.4
|
||||
'@radix-ui/react-slot': 1.0.2(@types/react@18.2.73)(react@18.2.0)
|
||||
react: 18.2.0
|
||||
react-dom: 18.2.0(react@18.2.0)
|
||||
@@ -12257,7 +12306,7 @@ snapshots:
|
||||
|
||||
'@radix-ui/react-slot@1.0.2(@types/react@18.2.73)(react@18.2.0)':
|
||||
dependencies:
|
||||
'@babel/runtime': 7.26.10
|
||||
'@babel/runtime': 7.28.4
|
||||
'@radix-ui/react-compose-refs': 1.0.1(@types/react@18.2.73)(react@18.2.0)
|
||||
react: 18.2.0
|
||||
optionalDependencies:
|
||||
@@ -12344,7 +12393,7 @@ snapshots:
|
||||
|
||||
'@radix-ui/react-use-callback-ref@1.0.1(@types/react@18.2.73)(react@18.2.0)':
|
||||
dependencies:
|
||||
'@babel/runtime': 7.26.10
|
||||
'@babel/runtime': 7.28.4
|
||||
react: 18.2.0
|
||||
optionalDependencies:
|
||||
'@types/react': 18.2.73
|
||||
@@ -12357,7 +12406,7 @@ snapshots:
|
||||
|
||||
'@radix-ui/react-use-controllable-state@1.0.1(@types/react@18.2.73)(react@18.2.0)':
|
||||
dependencies:
|
||||
'@babel/runtime': 7.26.10
|
||||
'@babel/runtime': 7.28.4
|
||||
'@radix-ui/react-use-callback-ref': 1.0.1(@types/react@18.2.73)(react@18.2.0)
|
||||
react: 18.2.0
|
||||
optionalDependencies:
|
||||
@@ -12387,7 +12436,7 @@ snapshots:
|
||||
|
||||
'@radix-ui/react-use-escape-keydown@1.0.3(@types/react@18.2.73)(react@18.2.0)':
|
||||
dependencies:
|
||||
'@babel/runtime': 7.26.10
|
||||
'@babel/runtime': 7.28.4
|
||||
'@radix-ui/react-use-callback-ref': 1.0.1(@types/react@18.2.73)(react@18.2.0)
|
||||
react: 18.2.0
|
||||
optionalDependencies:
|
||||
@@ -12402,7 +12451,7 @@ snapshots:
|
||||
|
||||
'@radix-ui/react-use-layout-effect@1.0.1(@types/react@18.2.73)(react@18.2.0)':
|
||||
dependencies:
|
||||
'@babel/runtime': 7.26.10
|
||||
'@babel/runtime': 7.28.4
|
||||
react: 18.2.0
|
||||
optionalDependencies:
|
||||
'@types/react': 18.2.73
|
||||
@@ -13041,6 +13090,8 @@ snapshots:
|
||||
|
||||
'@types/urijs@1.19.25': {}
|
||||
|
||||
'@types/use-sync-external-store@0.0.6': {}
|
||||
|
||||
'@types/uuid@9.0.8': {}
|
||||
|
||||
'@types/validator@13.11.10': {}
|
||||
@@ -13743,7 +13794,7 @@ snapshots:
|
||||
|
||||
babel-plugin-macros@3.1.0:
|
||||
dependencies:
|
||||
'@babel/runtime': 7.26.10
|
||||
'@babel/runtime': 7.28.4
|
||||
cosmiconfig: 7.1.0
|
||||
resolve: 1.22.10
|
||||
|
||||
@@ -13834,7 +13885,7 @@ snapshots:
|
||||
'@babel/preset-env': 7.24.7(@babel/core@7.26.10)
|
||||
'@babel/preset-react': 7.24.6(@babel/core@7.26.10)
|
||||
'@babel/preset-typescript': 7.24.7(@babel/core@7.26.10)
|
||||
'@babel/runtime': 7.26.10
|
||||
'@babel/runtime': 7.28.4
|
||||
babel-plugin-macros: 3.1.0
|
||||
babel-plugin-transform-react-remove-prop-types: 0.4.24
|
||||
transitivePeerDependencies:
|
||||
@@ -14148,7 +14199,7 @@ snapshots:
|
||||
cosmiconfig@8.3.6(typescript@5.8.3):
|
||||
dependencies:
|
||||
import-fresh: 3.3.1
|
||||
js-yaml: 4.1.0
|
||||
js-yaml: 4.1.1
|
||||
parse-json: 5.2.0
|
||||
path-type: 4.0.0
|
||||
optionalDependencies:
|
||||
@@ -14158,7 +14209,7 @@ snapshots:
|
||||
dependencies:
|
||||
env-paths: 2.2.1
|
||||
import-fresh: 3.3.1
|
||||
js-yaml: 4.1.0
|
||||
js-yaml: 4.1.1
|
||||
parse-json: 5.2.0
|
||||
optionalDependencies:
|
||||
typescript: 5.8.3
|
||||
@@ -14183,6 +14234,10 @@ snapshots:
|
||||
shebang-command: 2.0.0
|
||||
which: 2.0.2
|
||||
|
||||
css-box-model@1.2.1:
|
||||
dependencies:
|
||||
tiny-invariant: 1.3.3
|
||||
|
||||
css.escape@1.5.1: {}
|
||||
|
||||
cssesc@3.0.0: {}
|
||||
@@ -14354,7 +14409,7 @@ snapshots:
|
||||
|
||||
dom-helpers@5.2.1:
|
||||
dependencies:
|
||||
'@babel/runtime': 7.26.10
|
||||
'@babel/runtime': 7.28.4
|
||||
csstype: 3.1.3
|
||||
|
||||
domexception@4.0.0:
|
||||
@@ -15008,7 +15063,7 @@ snapshots:
|
||||
imurmurhash: 0.1.4
|
||||
is-glob: 4.0.3
|
||||
is-path-inside: 3.0.3
|
||||
js-yaml: 4.1.0
|
||||
js-yaml: 4.1.1
|
||||
json-stable-stringify-without-jsonify: 1.0.1
|
||||
levn: 0.4.1
|
||||
lodash.merge: 4.6.2
|
||||
@@ -15919,7 +15974,7 @@ snapshots:
|
||||
|
||||
js-tokens@9.0.1: {}
|
||||
|
||||
js-yaml@4.1.0:
|
||||
js-yaml@4.1.1:
|
||||
dependencies:
|
||||
argparse: 2.0.1
|
||||
|
||||
@@ -16162,7 +16217,7 @@ snapshots:
|
||||
dependencies:
|
||||
yallist: 3.1.1
|
||||
|
||||
lucide-react@0.416.0(react@18.2.0):
|
||||
lucide-react@0.552.0(react@18.2.0):
|
||||
dependencies:
|
||||
react: 18.2.0
|
||||
|
||||
@@ -17202,6 +17257,8 @@ snapshots:
|
||||
|
||||
queue-microtask@1.2.3: {}
|
||||
|
||||
raf-schd@4.0.3: {}
|
||||
|
||||
randombytes@2.1.0:
|
||||
dependencies:
|
||||
safe-buffer: 5.2.1
|
||||
@@ -17277,6 +17334,15 @@ snapshots:
|
||||
optionalDependencies:
|
||||
react: 18.2.0
|
||||
|
||||
react-redux@9.2.0(@types/react@18.2.73)(react@18.2.0)(redux@5.0.1):
|
||||
dependencies:
|
||||
'@types/use-sync-external-store': 0.0.6
|
||||
react: 18.2.0
|
||||
use-sync-external-store: 1.4.0(react@18.2.0)
|
||||
optionalDependencies:
|
||||
'@types/react': 18.2.73
|
||||
redux: 5.0.1
|
||||
|
||||
react-refresh@0.17.0: {}
|
||||
|
||||
react-remove-scroll-bar@2.3.8(@types/react@18.2.73)(react@18.2.0):
|
||||
@@ -17339,7 +17405,7 @@ snapshots:
|
||||
|
||||
react-transition-group@4.4.5(react-dom@18.2.0(react@18.2.0))(react@18.2.0):
|
||||
dependencies:
|
||||
'@babel/runtime': 7.26.10
|
||||
'@babel/runtime': 7.28.4
|
||||
dom-helpers: 5.2.1
|
||||
loose-envify: 1.4.0
|
||||
prop-types: 15.8.1
|
||||
@@ -17395,6 +17461,8 @@ snapshots:
|
||||
indent-string: 4.0.0
|
||||
strip-indent: 3.0.0
|
||||
|
||||
redux@5.0.1: {}
|
||||
|
||||
reflect.getprototypeof@1.0.10:
|
||||
dependencies:
|
||||
call-bind: 1.0.8
|
||||
@@ -17429,7 +17497,7 @@ snapshots:
|
||||
|
||||
regenerator-transform@0.15.2:
|
||||
dependencies:
|
||||
'@babel/runtime': 7.26.10
|
||||
'@babel/runtime': 7.28.4
|
||||
|
||||
regexp.prototype.flags@1.5.3:
|
||||
dependencies:
|
||||
@@ -17477,7 +17545,7 @@ snapshots:
|
||||
|
||||
relay-runtime@12.0.0(encoding@0.1.13):
|
||||
dependencies:
|
||||
'@babel/runtime': 7.26.10
|
||||
'@babel/runtime': 7.28.4
|
||||
fbjs: 3.0.5(encoding@0.1.13)
|
||||
invariant: 2.2.4
|
||||
transitivePeerDependencies:
|
||||
@@ -18122,6 +18190,8 @@ snapshots:
|
||||
|
||||
tiny-case@1.0.3: {}
|
||||
|
||||
tiny-invariant@1.3.3: {}
|
||||
|
||||
tinybench@2.9.0: {}
|
||||
|
||||
tinyexec@0.3.2: {}
|
||||
@@ -18466,7 +18536,7 @@ snapshots:
|
||||
|
||||
v8-compile-cache-lib@3.0.1: {}
|
||||
|
||||
validator@13.12.0: {}
|
||||
validator@13.15.23: {}
|
||||
|
||||
vfile-message@4.0.2:
|
||||
dependencies:
|
||||
|
||||
@@ -166,6 +166,12 @@ rec {
|
||||
'';
|
||||
};
|
||||
|
||||
packageWithDisabledCSP = package.overrideAttrs (oldAttrs: {
|
||||
configurePhase = oldAttrs.configurePhase + ''
|
||||
export CSP_MODE=disabled
|
||||
'';
|
||||
});
|
||||
|
||||
dockerImage = pkgs.runCommand "image-as-dir" { } ''
|
||||
${(nix2containerPkgs.nix2container.buildImage {
|
||||
inherit name created;
|
||||
@@ -175,7 +181,7 @@ rec {
|
||||
copyToRoot = pkgs.buildEnv {
|
||||
name = "image";
|
||||
paths = [
|
||||
package
|
||||
packageWithDisabledCSP
|
||||
(pkgs.writeTextFile {
|
||||
name = "tmp-file";
|
||||
text = ''
|
||||
|
||||
1
dashboard/react-table-config.d.ts
vendored
1
dashboard/react-table-config.d.ts
vendored
@@ -64,7 +64,6 @@ declare module 'react-table' {
|
||||
|
||||
export interface Cell<
|
||||
D extends Record<string, unknown> = Record<string, unknown>,
|
||||
V = any,
|
||||
> extends UseGroupByCellProps<D>,
|
||||
UseRowStateCellProps<D> {}
|
||||
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
import { cn } from '@/lib/utils';
|
||||
import {
|
||||
DragDropContext,
|
||||
Droppable,
|
||||
type DragDropContextProps,
|
||||
type DroppableProps,
|
||||
} from '@hello-pangea/dnd';
|
||||
import type { PropsWithChildren } from 'react';
|
||||
|
||||
type DragAndDropListProps = Omit<
|
||||
DroppableProps & DragDropContextProps,
|
||||
'children'
|
||||
> & {
|
||||
wrapperClassName?: string;
|
||||
};
|
||||
|
||||
function DragAndDropList({
|
||||
droppableId,
|
||||
onDragEnd,
|
||||
children,
|
||||
wrapperClassName,
|
||||
}: PropsWithChildren<DragAndDropListProps>) {
|
||||
return (
|
||||
<DragDropContext onDragEnd={onDragEnd}>
|
||||
<Droppable droppableId={droppableId}>
|
||||
{(provided) => (
|
||||
<div
|
||||
{...provided.droppableProps}
|
||||
ref={provided.innerRef}
|
||||
className={cn(wrapperClassName)}
|
||||
>
|
||||
{children}
|
||||
{provided.placeholder}
|
||||
</div>
|
||||
)}
|
||||
</Droppable>
|
||||
</DragDropContext>
|
||||
);
|
||||
}
|
||||
|
||||
export default DragAndDropList;
|
||||
@@ -0,0 +1,30 @@
|
||||
import { cn } from '@/lib/utils';
|
||||
import { Draggable, type DraggableProps } from '@hello-pangea/dnd';
|
||||
import type { PropsWithChildren } from 'react';
|
||||
|
||||
export type DraggableItemProps = PropsWithChildren<
|
||||
Omit<DraggableProps, 'children'> & { className?: string }
|
||||
>;
|
||||
|
||||
function DraggableItem({
|
||||
children,
|
||||
className,
|
||||
...draggableProps
|
||||
}: DraggableItemProps) {
|
||||
return (
|
||||
<Draggable {...draggableProps}>
|
||||
{(provided) => (
|
||||
<div
|
||||
ref={provided.innerRef}
|
||||
{...provided.draggableProps}
|
||||
{...provided.dragHandleProps}
|
||||
className={cn(className)}
|
||||
>
|
||||
{children}
|
||||
</div>
|
||||
)}
|
||||
</Draggable>
|
||||
);
|
||||
}
|
||||
|
||||
export default DraggableItem;
|
||||
3
dashboard/src/components/common/DragAndDropList/index.ts
Normal file
3
dashboard/src/components/common/DragAndDropList/index.ts
Normal file
@@ -0,0 +1,3 @@
|
||||
export { default as DragAndDropList } from './DragAndDropList';
|
||||
export * from './DraggableItem';
|
||||
export { default as DraggableItem } from './DraggableItem';
|
||||
@@ -123,7 +123,7 @@ const TimePickerInput = React.forwardRef<
|
||||
id={id || picker}
|
||||
name={name || picker}
|
||||
className={cn(
|
||||
'w-[48px] text-center font-mono text-base tabular-nums focus:bg-accent focus:text-accent-foreground [&::-webkit-inner-spin-button]:appearance-none',
|
||||
'w-[48px] text-center font-mono text-base tabular-nums focus:bg-accent-background focus:text-accent-foreground [&::-webkit-inner-spin-button]:appearance-none',
|
||||
className,
|
||||
)}
|
||||
value={value || calculatedValue}
|
||||
|
||||
@@ -1,26 +1,25 @@
|
||||
import { ActivityIndicator } from '@/components/ui/v2/ActivityIndicator';
|
||||
import type { BoxProps } from '@/components/ui/v2/Box';
|
||||
import { Box } from '@/components/ui/v2/Box';
|
||||
import { twMerge } from 'tailwind-merge';
|
||||
import { Spinner } from '@/components/ui/v3/spinner';
|
||||
import { cn } from '@/lib/utils';
|
||||
|
||||
export interface FormActivityIndicatorProps extends BoxProps {}
|
||||
export interface FormActivityIndicatorProps {
|
||||
className?: string;
|
||||
}
|
||||
|
||||
export default function FormActivityIndicator({
|
||||
className,
|
||||
...props
|
||||
}: FormActivityIndicatorProps) {
|
||||
return (
|
||||
<Box
|
||||
<div
|
||||
{...props}
|
||||
className={twMerge(
|
||||
'grid items-center justify-center px-6 py-4',
|
||||
className={cn(
|
||||
'box grid h-full items-center justify-center px-6 py-4',
|
||||
className,
|
||||
)}
|
||||
>
|
||||
<ActivityIndicator
|
||||
circularProgressProps={{ className: 'w-5 h-5' }}
|
||||
label="Loading form..."
|
||||
/>
|
||||
</Box>
|
||||
<Spinner className="h-5 w-5" wrapperClassName="flex-row gap-1">
|
||||
Loading form...
|
||||
</Spinner>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,12 +1,27 @@
|
||||
import {
|
||||
FormControl,
|
||||
FormDescription,
|
||||
FormField,
|
||||
FormItem,
|
||||
FormLabel,
|
||||
FormMessage,
|
||||
} from '@/components/ui/v3/form';
|
||||
import { Input } from '@/components/ui/v3/input';
|
||||
import type { Control, FieldPath, FieldValues } from 'react-hook-form';
|
||||
import { cn, isNotEmptyValue } from '@/lib/utils';
|
||||
import {
|
||||
type ChangeEvent,
|
||||
type ForwardedRef,
|
||||
forwardRef,
|
||||
type ReactNode,
|
||||
} from 'react';
|
||||
import type {
|
||||
Control,
|
||||
ControllerRenderProps,
|
||||
FieldPath,
|
||||
FieldValues,
|
||||
PathValue,
|
||||
} from 'react-hook-form';
|
||||
import { mergeRefs } from 'react-merge-refs';
|
||||
|
||||
const inputClasses =
|
||||
'!bg-transparent aria-[invalid=true]:border-red-500 aria-[invalid=true]:focus:border-red-500 aria-[invalid=true]:focus:ring-red-500';
|
||||
@@ -17,43 +32,116 @@ interface FormInputProps<
|
||||
> {
|
||||
control: Control<TFieldValues>;
|
||||
name: TName;
|
||||
label: string;
|
||||
label: ReactNode;
|
||||
placeholder?: string;
|
||||
className?: string;
|
||||
type?: string;
|
||||
inline?: boolean;
|
||||
helperText?: string | null;
|
||||
transformValue?: (
|
||||
value: PathValue<TFieldValues, TName>,
|
||||
) => PathValue<TFieldValues, TName>;
|
||||
}
|
||||
|
||||
function FormInput<
|
||||
function InnerFormInput<
|
||||
TFieldValues extends FieldValues = FieldValues,
|
||||
TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>,
|
||||
>({
|
||||
control,
|
||||
name,
|
||||
label,
|
||||
placeholder,
|
||||
className = '',
|
||||
type = 'text',
|
||||
}: FormInputProps<TFieldValues, TName>) {
|
||||
>(
|
||||
{
|
||||
control,
|
||||
name,
|
||||
label,
|
||||
placeholder,
|
||||
className = '',
|
||||
type = 'text',
|
||||
inline,
|
||||
helperText,
|
||||
transformValue,
|
||||
}: FormInputProps<TFieldValues, TName>,
|
||||
ref: ForwardedRef<HTMLInputElement>,
|
||||
) {
|
||||
function getOnChangeHandlerAndValue(
|
||||
field: ControllerRenderProps<TFieldValues, TName>,
|
||||
): [
|
||||
PathValue<TFieldValues, TName>,
|
||||
(e: ChangeEvent<HTMLInputElement>) => void,
|
||||
] {
|
||||
const { onChange, value } = field;
|
||||
|
||||
function handleOnChange(event: ChangeEvent<HTMLInputElement>) {
|
||||
let transformedValue = event.target.value;
|
||||
if (isNotEmptyValue(transformValue)) {
|
||||
transformedValue = transformValue(
|
||||
event.target.value as PathValue<TFieldValues, TName>,
|
||||
);
|
||||
}
|
||||
onChange(transformedValue);
|
||||
}
|
||||
|
||||
const transformedValue = isNotEmptyValue(transformValue)
|
||||
? transformValue(value)
|
||||
: value;
|
||||
|
||||
return [transformedValue, handleOnChange];
|
||||
}
|
||||
return (
|
||||
<FormField
|
||||
control={control}
|
||||
name={name}
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>{label}</FormLabel>
|
||||
<FormControl>
|
||||
<Input
|
||||
type={type}
|
||||
placeholder={placeholder || label}
|
||||
{...field}
|
||||
className={`${inputClasses} ${className}`}
|
||||
/>
|
||||
</FormControl>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
render={({ field }) => {
|
||||
const { onChange, value, ...fieldProps } = field;
|
||||
|
||||
const [tValue, handleOnChange] = getOnChangeHandlerAndValue(field);
|
||||
return (
|
||||
<FormItem
|
||||
className={cn({ 'flex w-full items-center gap-4 py-3': inline })}
|
||||
>
|
||||
<FormLabel
|
||||
className={cn({
|
||||
'mt-2 w-52 max-w-52 flex-shrink-0 self-start': inline,
|
||||
})}
|
||||
>
|
||||
{label}
|
||||
</FormLabel>
|
||||
<div
|
||||
className={cn({
|
||||
'flex w-[calc(100%-13.5rem)] max-w-[calc(100%-13.5rem)] flex-col gap-2':
|
||||
inline,
|
||||
})}
|
||||
>
|
||||
<FormControl>
|
||||
<Input
|
||||
type={type}
|
||||
placeholder={placeholder}
|
||||
onChange={handleOnChange}
|
||||
value={tValue}
|
||||
{...fieldProps}
|
||||
ref={mergeRefs([field.ref, ref])}
|
||||
className={cn(inputClasses, className)}
|
||||
wrapperClassName={cn({ 'w-full': !inline })}
|
||||
/>
|
||||
</FormControl>
|
||||
{!!helperText && (
|
||||
<FormDescription className="break-all px-[1px]">
|
||||
{helperText}
|
||||
</FormDescription>
|
||||
)}
|
||||
<FormMessage />
|
||||
</div>
|
||||
</FormItem>
|
||||
);
|
||||
}}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
const FormInput = forwardRef(InnerFormInput) as <
|
||||
TFieldValues extends FieldValues = FieldValues,
|
||||
TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>,
|
||||
>(
|
||||
props: FormInputProps<TFieldValues, TName> & {
|
||||
ref?: ForwardedRef<HTMLInputElement>;
|
||||
},
|
||||
) => ReturnType<typeof InnerFormInput>;
|
||||
|
||||
export default FormInput;
|
||||
|
||||
125
dashboard/src/components/form/FormSelect/FormSelect.tsx
Normal file
125
dashboard/src/components/form/FormSelect/FormSelect.tsx
Normal file
@@ -0,0 +1,125 @@
|
||||
import {
|
||||
FormControl,
|
||||
FormDescription,
|
||||
FormField,
|
||||
FormItem,
|
||||
FormLabel,
|
||||
FormMessage,
|
||||
} from '@/components/ui/v3/form';
|
||||
import {
|
||||
Select,
|
||||
SelectContent,
|
||||
SelectTrigger,
|
||||
SelectValue,
|
||||
} from '@/components/ui/v3/select';
|
||||
import { cn, isNotEmptyValue } from '@/lib/utils';
|
||||
import type { PropsWithChildren, ReactNode } from 'react';
|
||||
import type {
|
||||
Control,
|
||||
ControllerRenderProps,
|
||||
FieldPath,
|
||||
FieldValues,
|
||||
PathValue,
|
||||
} from 'react-hook-form';
|
||||
|
||||
interface FormSelectProps<
|
||||
TFieldValues extends FieldValues = FieldValues,
|
||||
TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>,
|
||||
> {
|
||||
control: Control<TFieldValues>;
|
||||
name: TName;
|
||||
label: ReactNode;
|
||||
placeholder?: string;
|
||||
className?: string;
|
||||
inline?: boolean;
|
||||
helperText?: string | null;
|
||||
transformValue?: (
|
||||
value: PathValue<TFieldValues, TName>,
|
||||
) => PathValue<TFieldValues, TName>;
|
||||
}
|
||||
|
||||
function FormSelect<
|
||||
TFieldValues extends FieldValues = FieldValues,
|
||||
TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>,
|
||||
>({
|
||||
control,
|
||||
name,
|
||||
label,
|
||||
placeholder,
|
||||
className = '',
|
||||
inline,
|
||||
helperText,
|
||||
children,
|
||||
transformValue,
|
||||
}: PropsWithChildren<FormSelectProps<TFieldValues, TName>>) {
|
||||
function getOnChangeHandlerAndValue(
|
||||
field: ControllerRenderProps<TFieldValues, TName>,
|
||||
): [string, (v: string) => void] {
|
||||
const { onChange, value } = field;
|
||||
|
||||
function handleOnChange(newValue: string) {
|
||||
const transformedNewValue = isNotEmptyValue(transformValue)
|
||||
? transformValue(newValue as PathValue<TFieldValues, TName>)
|
||||
: newValue;
|
||||
|
||||
onChange(transformedNewValue);
|
||||
}
|
||||
|
||||
const transformedValue: string = isNotEmptyValue(transformValue)
|
||||
? transformValue(value as PathValue<TFieldValues, TName>)
|
||||
: value;
|
||||
|
||||
return [transformedValue, handleOnChange];
|
||||
}
|
||||
return (
|
||||
<FormField
|
||||
control={control}
|
||||
name={name}
|
||||
render={({ field }) => {
|
||||
const { onChange, value, ...selectProps } = field;
|
||||
const [tValue, handleOnChange] = getOnChangeHandlerAndValue(field);
|
||||
return (
|
||||
<FormItem
|
||||
className={cn({ 'flex w-full items-center gap-4 py-3': inline })}
|
||||
>
|
||||
<FormLabel
|
||||
className={cn({
|
||||
'w-52 max-w-52 flex-shrink-0': inline,
|
||||
'mt-2 self-start': inline && !!helperText,
|
||||
})}
|
||||
>
|
||||
{label}
|
||||
</FormLabel>
|
||||
<div
|
||||
className={cn({
|
||||
'flex w-[calc(100%-13.5rem)] max-w-[calc(100%-13.5rem)] flex-col gap-2':
|
||||
inline,
|
||||
})}
|
||||
>
|
||||
<Select
|
||||
onValueChange={handleOnChange}
|
||||
value={tValue}
|
||||
{...selectProps}
|
||||
>
|
||||
<FormControl>
|
||||
<SelectTrigger className={className}>
|
||||
<SelectValue placeholder={placeholder} />
|
||||
</SelectTrigger>
|
||||
</FormControl>
|
||||
<SelectContent>{children}</SelectContent>
|
||||
</Select>
|
||||
{!!helperText && (
|
||||
<FormDescription className="break-all px-[1px]">
|
||||
{helperText}
|
||||
</FormDescription>
|
||||
)}
|
||||
<FormMessage />
|
||||
</div>
|
||||
</FormItem>
|
||||
);
|
||||
}}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
export default FormSelect;
|
||||
1
dashboard/src/components/form/FormSelect/index.ts
Normal file
1
dashboard/src/components/form/FormSelect/index.ts
Normal file
@@ -0,0 +1 @@
|
||||
export { default as FormSelect } from './FormSelect';
|
||||
97
dashboard/src/components/form/FormTextarea/FormTextarea.tsx
Normal file
97
dashboard/src/components/form/FormTextarea/FormTextarea.tsx
Normal file
@@ -0,0 +1,97 @@
|
||||
import {
|
||||
FormControl,
|
||||
FormDescription,
|
||||
FormField,
|
||||
FormItem,
|
||||
FormLabel,
|
||||
FormMessage,
|
||||
} from '@/components/ui/v3/form';
|
||||
import { Textarea } from '@/components/ui/v3/textarea';
|
||||
import { cn } from '@/lib/utils';
|
||||
import { forwardRef, type ForwardedRef, type ReactNode } from 'react';
|
||||
import type { Control, FieldPath, FieldValues } from 'react-hook-form';
|
||||
import { mergeRefs } from 'react-merge-refs';
|
||||
|
||||
const inputClasses =
|
||||
'!bg-transparent aria-[invalid=true]:border-red-500 aria-[invalid=true]:focus:border-red-500 aria-[invalid=true]:focus:ring-red-500';
|
||||
|
||||
interface FormTextareaProps<
|
||||
TFieldValues extends FieldValues = FieldValues,
|
||||
TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>,
|
||||
> {
|
||||
control: Control<TFieldValues>;
|
||||
name: TName;
|
||||
label: ReactNode;
|
||||
placeholder?: string;
|
||||
className?: string;
|
||||
inline?: boolean;
|
||||
helperText?: string | null;
|
||||
}
|
||||
|
||||
function InnerFormTextarea<
|
||||
TFieldValues extends FieldValues = FieldValues,
|
||||
TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>,
|
||||
>(
|
||||
{
|
||||
control,
|
||||
name,
|
||||
label,
|
||||
placeholder,
|
||||
className = '',
|
||||
inline,
|
||||
helperText,
|
||||
}: FormTextareaProps<TFieldValues, TName>,
|
||||
ref: ForwardedRef<HTMLTextAreaElement>,
|
||||
) {
|
||||
return (
|
||||
<FormField
|
||||
control={control}
|
||||
name={name}
|
||||
render={({ field }) => (
|
||||
<FormItem
|
||||
className={cn({ 'flex w-full items-center gap-4 py-3': inline })}
|
||||
>
|
||||
<FormLabel
|
||||
className={cn({
|
||||
'mt-2 w-52 max-w-52 flex-shrink-0 self-start': inline,
|
||||
})}
|
||||
>
|
||||
{label}
|
||||
</FormLabel>
|
||||
<div
|
||||
className={cn({
|
||||
'flex w-[calc(100%-13.5rem)] max-w-[calc(100%-13.5rem)] flex-col gap-2':
|
||||
inline,
|
||||
})}
|
||||
>
|
||||
<FormControl>
|
||||
<Textarea
|
||||
placeholder={placeholder}
|
||||
{...field}
|
||||
ref={mergeRefs([field.ref, ref])}
|
||||
className={cn(inputClasses, className)}
|
||||
/>
|
||||
</FormControl>
|
||||
{!!helperText && (
|
||||
<FormDescription className="break-all px-[1px]">
|
||||
{helperText}
|
||||
</FormDescription>
|
||||
)}
|
||||
<FormMessage />
|
||||
</div>
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
const FormTextarea = forwardRef(InnerFormTextarea) as <
|
||||
TFieldValues extends FieldValues = FieldValues,
|
||||
TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>,
|
||||
>(
|
||||
props: FormTextareaProps<TFieldValues, TName> & {
|
||||
ref: ForwardedRef<HTMLTextAreaElement>;
|
||||
},
|
||||
) => ReturnType<typeof InnerFormTextarea>;
|
||||
|
||||
export default FormTextarea;
|
||||
1
dashboard/src/components/form/FormTextarea/index.ts
Normal file
1
dashboard/src/components/form/FormTextarea/index.ts
Normal file
@@ -0,0 +1 @@
|
||||
export { default as FormTextarea } from './FormTextarea';
|
||||
@@ -127,14 +127,17 @@ export default function AuthenticatedLayout({
|
||||
className="relative flex h-full flex-row overflow-hidden"
|
||||
ref={setMainNavContainer}
|
||||
>
|
||||
{mainNavPinned && isMdOrLarger && <PinnedMainNav />}
|
||||
{withMainNav && mainNavPinned && isMdOrLarger && <PinnedMainNav />}
|
||||
|
||||
<div
|
||||
className={cn('relative flex h-full w-full flex-row bg-accent', {
|
||||
'overflow-x-auto': mainNavPinned && isMdOrLarger && withMainNav,
|
||||
})}
|
||||
className={cn(
|
||||
'bg-accent-background relative flex h-full w-full flex-row',
|
||||
{
|
||||
'overflow-x-auto': mainNavPinned && isMdOrLarger && withMainNav,
|
||||
},
|
||||
)}
|
||||
>
|
||||
{(!mainNavPinned || !isMdOrLarger) && (
|
||||
{withMainNav && (!mainNavPinned || !isMdOrLarger) && (
|
||||
<div className="flex h-full w-6 justify-center">
|
||||
<MainNav container={mainNavContainer} />
|
||||
</div>
|
||||
|
||||
@@ -482,9 +482,9 @@ export default function NavTree() {
|
||||
}
|
||||
}}
|
||||
className={cn(
|
||||
'flex h-8 w-full flex-row justify-start gap-1 bg-background px-1 text-foreground hover:bg-accent dark:hover:bg-muted',
|
||||
'flex h-8 w-full flex-row justify-start gap-1 bg-background px-1 text-foreground hover:bg-accent',
|
||||
{
|
||||
'bg-[#ebf3ff] hover:bg-[#ebf3ff] dark:bg-muted':
|
||||
'bg-[#ebf3ff] hover:bg-accent dark:bg-muted':
|
||||
context.isFocused,
|
||||
},
|
||||
item.data.disabled && 'pointer-events-none opacity-50',
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
import { Box } from '@/components/ui/v2/Box';
|
||||
import type { TextProps } from '@/components/ui/v2/Text';
|
||||
import { Text } from '@/components/ui/v2/Text';
|
||||
import type { DetailedHTMLProps, ForwardedRef, HTMLProps } from 'react';
|
||||
import { cn } from '@/lib/utils';
|
||||
import type {
|
||||
DetailedHTMLProps,
|
||||
ForwardedRef,
|
||||
HTMLAttributes,
|
||||
HTMLProps,
|
||||
} from 'react';
|
||||
import { forwardRef } from 'react';
|
||||
import { twMerge } from 'tailwind-merge';
|
||||
|
||||
export type ReadOnlyToggleProps = Omit<
|
||||
DetailedHTMLProps<HTMLProps<HTMLSpanElement>, HTMLSpanElement>,
|
||||
@@ -24,7 +26,7 @@ export type ReadOnlyToggleProps = Omit<
|
||||
/**
|
||||
* Props passed to the label.
|
||||
*/
|
||||
label?: TextProps;
|
||||
label?: HTMLAttributes<HTMLSpanElement>;
|
||||
};
|
||||
};
|
||||
|
||||
@@ -36,58 +38,44 @@ function ReadOnlyToggle(
|
||||
<span
|
||||
{...props}
|
||||
{...(slotProps?.root || {})}
|
||||
className={twMerge(
|
||||
className={cn(
|
||||
'inline-grid h-full w-full grid-flow-col items-center justify-start gap-1.5',
|
||||
slotProps?.root?.className,
|
||||
className,
|
||||
)}
|
||||
ref={ref}
|
||||
>
|
||||
<Box
|
||||
component="span"
|
||||
sx={{
|
||||
backgroundColor: (theme) => {
|
||||
if (checked) {
|
||||
return theme.palette.mode === 'dark' ? 'grey.400' : 'grey.700';
|
||||
}
|
||||
|
||||
return 'transparent';
|
||||
<span
|
||||
className={cn(
|
||||
'box-border inline-grid h-3 w-5 items-center rounded-full border-1 border-primary-text bg-transparent px-0.5',
|
||||
checked && 'justify-end',
|
||||
{
|
||||
'border-transparent bg-primary-text px-0.5 dark:bg-[#363a43]':
|
||||
checked,
|
||||
},
|
||||
borderColor: checked ? 'transparent' : 'grey.700',
|
||||
}}
|
||||
className={twMerge(
|
||||
'box-border inline-grid h-3 w-5 items-center rounded-full border-1 px-0.5',
|
||||
checked === true && 'justify-end',
|
||||
)}
|
||||
>
|
||||
<Box
|
||||
component="span"
|
||||
sx={{
|
||||
backgroundColor: (theme) => {
|
||||
if (checked) {
|
||||
return theme.palette.mode === 'dark' ? 'grey.700' : 'grey.200';
|
||||
}
|
||||
|
||||
return 'grey.700';
|
||||
<span
|
||||
className={cn(
|
||||
'inline-block h-2 w-2 rounded-full border-primary-text bg-primary-text',
|
||||
{
|
||||
'border-transparent bg-data-cell-bg px-0.5 dark:bg-[#f4f7f9]':
|
||||
checked,
|
||||
'my-px h-px justify-self-center': checked === null,
|
||||
},
|
||||
}}
|
||||
className={twMerge(
|
||||
'inline-block h-2 w-2 rounded-full',
|
||||
checked === null && 'my-px h-px justify-self-center',
|
||||
)}
|
||||
/>
|
||||
</Box>
|
||||
</span>
|
||||
|
||||
<Text
|
||||
<span
|
||||
{...(slotProps?.label || {})}
|
||||
component="span"
|
||||
className={twMerge(
|
||||
className={cn(
|
||||
'truncate !text-xs font-normal',
|
||||
slotProps?.label?.className,
|
||||
)}
|
||||
>
|
||||
{String(checked)}
|
||||
</Text>
|
||||
</span>
|
||||
</span>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,32 +0,0 @@
|
||||
import type { IconProps } from '@/components/ui/v2/icons';
|
||||
import { SvgIcon } from '@/components/ui/v2/icons/SvgIcon';
|
||||
|
||||
function KeyIcon(props: IconProps) {
|
||||
return (
|
||||
<SvgIcon
|
||||
width="16"
|
||||
height="16"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
viewBox="0 0 16 16"
|
||||
aria-label="Key"
|
||||
{...props}
|
||||
>
|
||||
<path
|
||||
d="M5.823 7.677a4.496 4.496 0 1 1 2.5 2.5L7.5 11H6v1.5H4.5V14H2v-2.5l3.823-3.823Z"
|
||||
stroke="currentColor"
|
||||
fill="none"
|
||||
strokeWidth="1.5"
|
||||
strokeLinejoin="round"
|
||||
/>
|
||||
|
||||
<path
|
||||
d="M10.5 7a1.5 1.5 0 1 0 0-3 1.5 1.5 0 0 0 0 3Z"
|
||||
fill="currentColor"
|
||||
/>
|
||||
</SvgIcon>
|
||||
);
|
||||
}
|
||||
|
||||
KeyIcon.displayName = 'NhostKeyIcon';
|
||||
|
||||
export default KeyIcon;
|
||||
@@ -1 +0,0 @@
|
||||
export { default as KeyIcon } from './KeyIcon';
|
||||
@@ -11,7 +11,7 @@ const badgeVariants = cva(
|
||||
default:
|
||||
'border-transparent bg-primary text-primary-foreground hover:bg-primary/80 dark:text-white',
|
||||
secondary:
|
||||
'border-transparent bg-secondary text-secondary-foreground hover:bg-secondary/80',
|
||||
'border-transparent bg-card text-secondary-foreground hover:bg-secondary/80',
|
||||
destructive:
|
||||
'border-transparent bg-destructive text-destructive-foreground hover:bg-destructive/80',
|
||||
outline: 'text-foreground',
|
||||
|
||||
83
dashboard/src/components/ui/v3/button-group.tsx
Normal file
83
dashboard/src/components/ui/v3/button-group.tsx
Normal file
@@ -0,0 +1,83 @@
|
||||
import { Slot } from "@radix-ui/react-slot"
|
||||
import { cva, type VariantProps } from "class-variance-authority"
|
||||
|
||||
import { cn } from "@/lib/utils"
|
||||
import { Separator } from "@/components/ui/v3/separator"
|
||||
|
||||
const buttonGroupVariants = cva(
|
||||
"flex w-fit items-stretch has-[>[data-slot=button-group]]:gap-2 [&>*]:focus-visible:relative [&>*]:focus-visible:z-10 has-[select[aria-hidden=true]:last-child]:[&>[data-slot=select-trigger]:last-of-type]:rounded-r-md [&>[data-slot=select-trigger]:not([class*='w-'])]:w-fit [&>input]:flex-1",
|
||||
{
|
||||
variants: {
|
||||
orientation: {
|
||||
horizontal:
|
||||
"[&>*:not(:first-child)]:rounded-l-none [&>*:not(:first-child)]:border-l-0 [&>*:not(:last-child)]:rounded-r-none",
|
||||
vertical:
|
||||
"flex-col [&>*:not(:first-child)]:rounded-t-none [&>*:not(:first-child)]:border-t-0 [&>*:not(:last-child)]:rounded-b-none",
|
||||
},
|
||||
},
|
||||
defaultVariants: {
|
||||
orientation: "horizontal",
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
function ButtonGroup({
|
||||
className,
|
||||
orientation,
|
||||
...props
|
||||
}: React.ComponentProps<"div"> & VariantProps<typeof buttonGroupVariants>) {
|
||||
return (
|
||||
<div
|
||||
role="group"
|
||||
data-slot="button-group"
|
||||
data-orientation={orientation}
|
||||
className={cn(buttonGroupVariants({ orientation }), className)}
|
||||
{...props}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
function ButtonGroupText({
|
||||
className,
|
||||
asChild = false,
|
||||
...props
|
||||
}: React.ComponentProps<"div"> & {
|
||||
asChild?: boolean
|
||||
}) {
|
||||
const Comp = asChild ? Slot : "div"
|
||||
|
||||
return (
|
||||
<Comp
|
||||
className={cn(
|
||||
"bg-muted shadow-xs flex items-center gap-2 rounded-md border px-4 text-sm font-medium [&_svg:not([class*='size-'])]:size-4 [&_svg]:pointer-events-none",
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
function ButtonGroupSeparator({
|
||||
className,
|
||||
orientation = "vertical",
|
||||
...props
|
||||
}: React.ComponentProps<typeof Separator>) {
|
||||
return (
|
||||
<Separator
|
||||
data-slot="button-group-separator"
|
||||
orientation={orientation}
|
||||
className={cn(
|
||||
"bg-input relative !m-0 self-stretch data-[orientation=vertical]:h-auto",
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
export {
|
||||
ButtonGroup,
|
||||
ButtonGroupSeparator,
|
||||
ButtonGroupText,
|
||||
buttonGroupVariants,
|
||||
}
|
||||
@@ -16,8 +16,8 @@ const buttonVariants = cva(
|
||||
outline:
|
||||
'border bg-background hover:bg-accent hover:text-accent-foreground',
|
||||
secondary:
|
||||
'bg-secondary text-secondary-foreground hover:bg-secondary/80',
|
||||
ghost: 'hover:bg-accent hover:text-accent-foreground',
|
||||
'bg-secondary text-secondary-foreground hover:bg-secondary-hover',
|
||||
ghost: 'hover:bg-accent text-accent-foreground',
|
||||
link: 'text-primary underline-offset-4 hover:underline',
|
||||
},
|
||||
size: {
|
||||
|
||||
@@ -11,15 +11,15 @@ const Checkbox = React.forwardRef<
|
||||
<CheckboxPrimitive.Root
|
||||
ref={ref}
|
||||
className={cn(
|
||||
'peer h-4 w-4 shrink-0 rounded-sm border border-primary ring-offset-background focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 data-[state=checked]:bg-primary data-[state=checked]:text-primary-foreground',
|
||||
'peer h-4 w-4 shrink-0 rounded-sm border border-primary ring-offset-background focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:border-disabled disabled:bg-disabled disabled:opacity-50 data-[state=checked]:bg-primary data-[state=checked]:text-primary-foreground',
|
||||
className,
|
||||
)}
|
||||
{...props}
|
||||
>
|
||||
<CheckboxPrimitive.Indicator
|
||||
className={cn('flex items-center justify-center text-current')}
|
||||
className={cn('flex items-center justify-center text-white')}
|
||||
>
|
||||
<Check className="h-4 w-4" />
|
||||
<Check width={16} height={16} strokeWidth={3} />
|
||||
</CheckboxPrimitive.Indicator>
|
||||
</CheckboxPrimitive.Root>
|
||||
));
|
||||
|
||||
@@ -31,6 +31,7 @@ interface DialogContentProps
|
||||
extends React.ComponentPropsWithoutRef<typeof DialogPrimitive.Content> {
|
||||
disableOutsideClick?: boolean;
|
||||
hideCloseButton?: boolean;
|
||||
closeButtonClassName?: string;
|
||||
}
|
||||
|
||||
const DialogContent = React.forwardRef<
|
||||
@@ -38,7 +39,14 @@ const DialogContent = React.forwardRef<
|
||||
DialogContentProps
|
||||
>(
|
||||
(
|
||||
{ className, children, disableOutsideClick, hideCloseButton, ...props },
|
||||
{
|
||||
className,
|
||||
children,
|
||||
disableOutsideClick,
|
||||
hideCloseButton,
|
||||
closeButtonClassName,
|
||||
...props
|
||||
},
|
||||
ref,
|
||||
) => (
|
||||
<DialogPortal>
|
||||
@@ -58,7 +66,12 @@ const DialogContent = React.forwardRef<
|
||||
>
|
||||
{children}
|
||||
{!hideCloseButton && (
|
||||
<DialogPrimitive.Close className="absolute right-4 top-4 rounded-sm opacity-70 ring-offset-background transition-opacity hover:opacity-100 focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:pointer-events-none data-[state=open]:bg-accent data-[state=open]:text-muted-foreground">
|
||||
<DialogPrimitive.Close
|
||||
className={cn(
|
||||
'absolute right-4 top-4 rounded-sm opacity-70 ring-offset-background transition-opacity hover:opacity-100 focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:pointer-events-none data-[state=open]:bg-accent-background data-[state=open]:text-muted-foreground',
|
||||
closeButtonClassName,
|
||||
)}
|
||||
>
|
||||
<X className="h-4 w-4" />
|
||||
<span className="sr-only">Close</span>
|
||||
</DialogPrimitive.Close>
|
||||
|
||||
@@ -5,11 +5,11 @@ export function InlineCode({
|
||||
children,
|
||||
className,
|
||||
...props
|
||||
}: PropsWithChildren<{ className?: string }>) {
|
||||
}: PropsWithChildren<React.HTMLAttributes<HTMLElement>>) {
|
||||
return (
|
||||
<code
|
||||
className={cn(
|
||||
'relative rounded bg-[#eaedf0] px-1 font-mono text-[11px] dark:bg-[#2f363d]',
|
||||
'relative max-w-xs truncate rounded bg-[#eaedf0] px-1 font-mono text-[11px] dark:bg-[#2f363d]',
|
||||
className,
|
||||
)}
|
||||
{...props}
|
||||
|
||||
@@ -5,12 +5,13 @@ import { cn } from '@/lib/utils';
|
||||
export interface InputProps
|
||||
extends Omit<React.InputHTMLAttributes<HTMLInputElement>, 'prefix'> {
|
||||
prefix?: React.ReactNode;
|
||||
wrapperClassName?: string;
|
||||
}
|
||||
|
||||
const Input = React.forwardRef<HTMLInputElement, InputProps>(
|
||||
({ className, type, prefix, ...props }, ref) => {
|
||||
({ className, type, prefix, wrapperClassName, ...props }, ref) => {
|
||||
return (
|
||||
<div className="relative flex items-center">
|
||||
<div className={cn('relative flex items-center', wrapperClassName)}>
|
||||
{prefix && (
|
||||
<span className="pointer-events-none absolute left-3 flex items-center text-muted-foreground">
|
||||
{prefix}
|
||||
@@ -19,7 +20,7 @@ const Input = React.forwardRef<HTMLInputElement, InputProps>(
|
||||
<input
|
||||
type={type}
|
||||
className={cn(
|
||||
'flex h-10 w-full rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background file:border-0 file:bg-transparent file:text-sm file:font-medium placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring focus-visible:ring-offset-0 disabled:cursor-not-allowed disabled:opacity-50 dark:bg-accent',
|
||||
'flex h-10 w-full rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background file:border-0 file:bg-transparent file:text-sm file:font-medium placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring focus-visible:ring-offset-0 disabled:cursor-not-allowed disabled:opacity-50 dark:bg-accent-background',
|
||||
{ 'pl-6': prefix },
|
||||
className,
|
||||
)}
|
||||
|
||||
@@ -54,6 +54,7 @@ interface SheetContentProps
|
||||
VariantProps<typeof sheetVariants> {
|
||||
container?: HTMLElement | null;
|
||||
hideCloseButton?: boolean;
|
||||
showOverlay?: boolean;
|
||||
}
|
||||
|
||||
const SheetContent = React.forwardRef<
|
||||
@@ -67,11 +68,13 @@ const SheetContent = React.forwardRef<
|
||||
container = null,
|
||||
hideCloseButton,
|
||||
children,
|
||||
showOverlay = false,
|
||||
...props
|
||||
},
|
||||
ref,
|
||||
) => (
|
||||
<SheetPortal container={container}>
|
||||
{showOverlay && <SheetOverlay />}
|
||||
<SheetPrimitive.Content
|
||||
ref={ref}
|
||||
className={cn(sheetVariants({ side }), className)}
|
||||
|
||||
@@ -33,6 +33,7 @@ interface SpinnerContentProps
|
||||
VariantProps<typeof loaderVariants> {
|
||||
className?: string;
|
||||
children?: React.ReactNode;
|
||||
wrapperClassName?: string;
|
||||
}
|
||||
|
||||
export function Spinner({
|
||||
@@ -40,10 +41,12 @@ export function Spinner({
|
||||
show,
|
||||
children,
|
||||
className,
|
||||
wrapperClassName,
|
||||
}: SpinnerContentProps) {
|
||||
return (
|
||||
<span className={spinnerVariants({ show })}>
|
||||
<span className={cn(spinnerVariants({ show }), wrapperClassName)}>
|
||||
<Loader2
|
||||
role="progressbar"
|
||||
className={cn(
|
||||
loaderVariants({ size }),
|
||||
className,
|
||||
|
||||
@@ -9,7 +9,7 @@ const Textarea = React.forwardRef<
|
||||
return (
|
||||
<textarea
|
||||
className={cn(
|
||||
'flex min-h-[80px] w-full rounded-md border border-input bg-background px-3 py-2 text-base ring-offset-background placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 md:text-sm',
|
||||
'flex min-h-[80px] w-full rounded-md border border-input bg-background px-3 py-2 text-base ring-offset-background placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-0 focus-visible:ring-ring focus-visible:ring-offset-0 disabled:cursor-not-allowed disabled:opacity-50 md:text-sm',
|
||||
className,
|
||||
)}
|
||||
ref={ref}
|
||||
|
||||
@@ -23,7 +23,7 @@ export default function SocialProvidersSettings() {
|
||||
if (typeof window !== 'undefined') {
|
||||
return nhost.auth.signInProviderURL('github', {
|
||||
connect: token,
|
||||
redirectTo: `${window.location.origin}/account`,
|
||||
redirectTo: `${window.location.origin}/account?signinProvider=github`,
|
||||
});
|
||||
}
|
||||
return '';
|
||||
|
||||
@@ -3,18 +3,21 @@ import {
|
||||
useGithubAuthentication,
|
||||
type UseGithubAuthenticationHookProps,
|
||||
} from '@/features/auth/AuthProviders/Github/hooks/useGithubAuthentication';
|
||||
import { cn } from '@/lib/utils';
|
||||
import { SiGithub } from '@icons-pack/react-simple-icons';
|
||||
|
||||
interface Props extends UseGithubAuthenticationHookProps {
|
||||
buttonText?: string;
|
||||
withAnonId?: boolean;
|
||||
redirectTo?: string;
|
||||
className?: string;
|
||||
}
|
||||
|
||||
function GithubAuthButton({
|
||||
buttonText = 'Continue with GitHub',
|
||||
withAnonId = false,
|
||||
redirectTo,
|
||||
className,
|
||||
}: Props) {
|
||||
const { mutate: signInWithGithub, isLoading } = useGithubAuthentication({
|
||||
withAnonId,
|
||||
@@ -22,7 +25,10 @@ function GithubAuthButton({
|
||||
});
|
||||
return (
|
||||
<Button
|
||||
className="gap-2 !bg-white text-sm+ !text-black hover:ring-2 hover:ring-white hover:ring-opacity-50 disabled:!text-black disabled:!text-opacity-60"
|
||||
className={cn(
|
||||
'gap-2 !bg-white text-sm+ !text-black hover:ring-2 hover:ring-white hover:ring-opacity-50 disabled:!text-black disabled:!text-opacity-60',
|
||||
className,
|
||||
)}
|
||||
disabled={isLoading}
|
||||
loading={isLoading}
|
||||
onClick={() => signInWithGithub()}
|
||||
|
||||
@@ -30,8 +30,8 @@ function useGithubAuthentication({
|
||||
};
|
||||
}
|
||||
|
||||
const redirectURl = nhost.auth.signInProviderURL('github', options);
|
||||
window.location.href = redirectURl;
|
||||
const redirectURL = nhost.auth.signInProviderURL('github', options);
|
||||
window.location.href = redirectURL;
|
||||
},
|
||||
{
|
||||
onError: () => {
|
||||
|
||||
@@ -24,12 +24,14 @@ function SignInWithEmailAndPassword({ onSubmit, isLoading }: Props) {
|
||||
label="Email"
|
||||
name="email"
|
||||
type="email"
|
||||
placeholder="Email"
|
||||
/>
|
||||
<FormInput
|
||||
control={form.control}
|
||||
label="Password"
|
||||
name="password"
|
||||
type="password"
|
||||
placeholder="Password"
|
||||
/>
|
||||
<NextLink
|
||||
href="/password/new"
|
||||
|
||||
@@ -2,7 +2,7 @@ import { GithubAuthButton } from '@/features/auth/AuthProviders/Github/component
|
||||
import { useHostName } from '@/features/orgs/projects/common/hooks/useHostName';
|
||||
|
||||
function SignInWithGithub() {
|
||||
const redirectTo = useHostName();
|
||||
const redirectTo = `${useHostName()}?signinProvider=github`;
|
||||
return (
|
||||
<GithubAuthButton
|
||||
redirectTo={redirectTo}
|
||||
|
||||
@@ -22,18 +22,25 @@ function SignUpWithEmailAndPasswordForm() {
|
||||
onSubmit={form.handleSubmit(onSignUpWithPassword)}
|
||||
className="grid grid-flow-row gap-4 bg-transparent"
|
||||
>
|
||||
<FormInput control={form.control} label="Name" name="displayName" />
|
||||
<FormInput
|
||||
control={form.control}
|
||||
label="Name"
|
||||
name="displayName"
|
||||
placeholder="Name"
|
||||
/>
|
||||
<FormInput
|
||||
control={form.control}
|
||||
label="Email"
|
||||
name="email"
|
||||
type="email"
|
||||
placeholder="Email"
|
||||
/>
|
||||
<FormInput
|
||||
control={form.control}
|
||||
label="Password"
|
||||
name="password"
|
||||
type="password"
|
||||
placeholder="Password"
|
||||
/>
|
||||
<FormField
|
||||
control={form.control}
|
||||
|
||||
@@ -22,12 +22,18 @@ function SignUpWithSecurityKeyForm() {
|
||||
onSubmit={form.handleSubmit(onSignUpWithSecurityKey)}
|
||||
className="grid grid-flow-row gap-4 bg-transparent"
|
||||
>
|
||||
<FormInput control={form.control} label="Name" name="displayName" />
|
||||
<FormInput
|
||||
control={form.control}
|
||||
label="Name"
|
||||
name="displayName"
|
||||
placeholder="Name"
|
||||
/>
|
||||
<FormInput
|
||||
control={form.control}
|
||||
label="Email"
|
||||
name="email"
|
||||
type="email"
|
||||
placeholder="Email"
|
||||
/>
|
||||
<FormField
|
||||
control={form.control}
|
||||
|
||||
@@ -1,8 +1,11 @@
|
||||
import { GithubAuthButton } from '@/features/auth/AuthProviders/Github/components/GithubAuthButton';
|
||||
import { useHostName } from '@/features/orgs/projects/common/hooks/useHostName';
|
||||
|
||||
function SignUpWithGithub() {
|
||||
const redirectTo = `${useHostName()}?signinProvider=github`;
|
||||
return (
|
||||
<GithubAuthButton
|
||||
redirectTo={redirectTo}
|
||||
buttonText="Sign Up with GitHub"
|
||||
errorText="An error occurred while trying to sign up using GitHub. Please try again."
|
||||
/>
|
||||
|
||||
@@ -52,7 +52,7 @@ export default function BillingDetails() {
|
||||
<AccordionContent className="border-t-1 pb-0">
|
||||
<div className="rounded-md">
|
||||
<Table>
|
||||
<TableHeader className="w-full bg-accent">
|
||||
<TableHeader className="w-full bg-accent-background">
|
||||
<TableRow>
|
||||
<TableHead colSpan={3} className="w-full rounded-tl-md">
|
||||
Item
|
||||
@@ -72,7 +72,7 @@ export default function BillingDetails() {
|
||||
</TableRow>
|
||||
))}
|
||||
</TableBody>
|
||||
<TableFooter className="bg-accent">
|
||||
<TableFooter className="bg-accent-background">
|
||||
<TableRow>
|
||||
<TableCell colSpan={3} className="rounded-bl-md">
|
||||
Total
|
||||
|
||||
@@ -62,7 +62,7 @@ export default function ProjectsGrid({ projects }: ProjectGridProps) {
|
||||
);
|
||||
|
||||
return (
|
||||
<div className="mx-auto h-full overflow-auto bg-accent">
|
||||
<div className="mx-auto h-full overflow-auto bg-accent-background">
|
||||
<div className="flex w-full flex-shrink-0 flex-row items-center justify-between gap-2 border-b bg-background p-2">
|
||||
<Input
|
||||
placeholder="Find Project"
|
||||
@@ -85,7 +85,6 @@ export default function ProjectsGrid({ projects }: ProjectGridProps) {
|
||||
</Link>
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
<div className="grid grid-cols-1 gap-4 p-4 sm:grid-cols-2 md:grid-cols-1 lg:grid-cols-2 xl:grid-cols-3 2xl:grid-cols-4">
|
||||
{filteredProjects.map((project) => (
|
||||
<ProjectCard key={project.id} project={project} />
|
||||
|
||||
@@ -176,7 +176,7 @@ export default function AppleProviderSettings() {
|
||||
loading: formState.isSubmitting,
|
||||
},
|
||||
}}
|
||||
docsLink="https://docs.nhost.io/products/auth/social/sign-in-apple"
|
||||
docsLink="https://docs.nhost.io/products/auth/providers/sign-in-apple"
|
||||
docsTitle="how to sign in users with Apple"
|
||||
icon={
|
||||
theme.palette.mode === 'dark'
|
||||
|
||||
@@ -141,7 +141,7 @@ export default function DiscordProviderSettings() {
|
||||
loading: formState.isSubmitting,
|
||||
},
|
||||
}}
|
||||
docsLink="https://docs.nhost.io/products/auth/social/sign-in-discord"
|
||||
docsLink="https://docs.nhost.io/products/auth/providers/sign-in-discord"
|
||||
docsTitle="how to sign in users with Discord"
|
||||
icon="/assets/brands/discord.svg"
|
||||
switchId="enabled"
|
||||
|
||||
@@ -142,7 +142,7 @@ export default function FacebookProviderSettings() {
|
||||
loading: formState.isSubmitting,
|
||||
},
|
||||
}}
|
||||
docsLink="https://docs.nhost.io/products/auth/social/sign-in-facebook"
|
||||
docsLink="https://docs.nhost.io/products/auth/providers/sign-in-facebook"
|
||||
docsTitle="how to sign in users with Facebook"
|
||||
icon="/assets/brands/facebook.svg"
|
||||
switchId="enabled"
|
||||
|
||||
@@ -144,7 +144,7 @@ export default function GitHubProviderSettings() {
|
||||
loading: formState.isSubmitting,
|
||||
},
|
||||
}}
|
||||
docsLink="https://docs.nhost.io/products/auth/social/sign-in-github"
|
||||
docsLink="https://docs.nhost.io/products/auth/providers/sign-in-github"
|
||||
docsTitle="how to sign in users with GitHub"
|
||||
icon={
|
||||
theme.palette.mode === 'dark'
|
||||
|
||||
@@ -162,7 +162,7 @@ export default function GoogleProviderSettings() {
|
||||
loading: formState.isSubmitting,
|
||||
},
|
||||
}}
|
||||
docsLink="https://docs.nhost.io/products/auth/social/sign-in-google"
|
||||
docsLink="https://docs.nhost.io/products/auth/providers/sign-in-google"
|
||||
docsTitle="how to sign in users with Google"
|
||||
icon="/assets/brands/google.svg"
|
||||
switchId="enabled"
|
||||
|
||||
@@ -142,7 +142,7 @@ export default function LinkedInProviderSettings() {
|
||||
loading: formState.isSubmitting,
|
||||
},
|
||||
}}
|
||||
docsLink="https://docs.nhost.io/products/auth/social/sign-in-linkedin"
|
||||
docsLink="https://docs.nhost.io/products/auth/providers/sign-in-linkedin"
|
||||
docsTitle="how to sign in users with LinkedIn"
|
||||
icon="/assets/brands/linkedin.svg"
|
||||
switchId="enabled"
|
||||
|
||||
@@ -142,7 +142,7 @@ export default function SpotifyProviderSettings() {
|
||||
loading: formState.isSubmitting,
|
||||
},
|
||||
}}
|
||||
docsLink="https://docs.nhost.io/products/auth/social/sign-in-spotify"
|
||||
docsLink="https://docs.nhost.io/products/auth/providers/sign-in-spotify"
|
||||
docsTitle="how to sign in users with Spotify"
|
||||
icon="/assets/brands/spotify.svg"
|
||||
switchId="enabled"
|
||||
|
||||
@@ -144,7 +144,7 @@ export default function TwitchProviderSettings() {
|
||||
loading: formState.isSubmitting,
|
||||
},
|
||||
}}
|
||||
docsLink="https://docs.nhost.io/products/auth/social/sign-in-twitch"
|
||||
docsLink="https://docs.nhost.io/products/auth/providers/sign-in-twitch"
|
||||
docsTitle="how to sign in users with Twitch"
|
||||
icon={
|
||||
theme.palette.mode === 'dark'
|
||||
|
||||
@@ -177,7 +177,7 @@ export default function WorkOsProviderSettings() {
|
||||
loading: formState.isSubmitting,
|
||||
},
|
||||
}}
|
||||
docsLink="https://docs.nhost.io/products/auth/social/sign-in-workos"
|
||||
docsLink="https://docs.nhost.io/products/auth/providers/sign-in-workos"
|
||||
docsTitle="how to sign in users with WorkOS"
|
||||
icon="/assets/brands/workos.svg"
|
||||
switchId="enabled"
|
||||
|
||||
@@ -0,0 +1,75 @@
|
||||
import { DragAndDropList } from '@/components/common/DragAndDropList';
|
||||
|
||||
import { isEmptyValue } from '@/lib/utils';
|
||||
import type { DropResult } from '@hello-pangea/dnd';
|
||||
import type { ColumnInstance } from 'react-table';
|
||||
import ColumnCustomizerRow from './ColumnCustomizerRow';
|
||||
import ShowHideAllColumnsButtons from './ShowHideAllColumnsButtons';
|
||||
|
||||
type ColumnCustomizerProps = {
|
||||
columns: ColumnInstance[];
|
||||
onDragEnd: (columnsOrder: string[]) => void;
|
||||
onReset: () => void;
|
||||
onShowAllColumns: () => void;
|
||||
onHideAllColumns: () => void;
|
||||
};
|
||||
|
||||
function reorder(list: ColumnInstance[], startIndex: number, endIndex: number) {
|
||||
const result = Array.from(list);
|
||||
const [removed] = result.splice(startIndex, 1);
|
||||
result.splice(endIndex, 0, removed);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
function ColumnCustomizer({
|
||||
columns,
|
||||
onDragEnd,
|
||||
onReset,
|
||||
onShowAllColumns,
|
||||
onHideAllColumns,
|
||||
}: ColumnCustomizerProps) {
|
||||
function handleDragEnd(result: DropResult) {
|
||||
if (isEmptyValue(result.destination)) {
|
||||
return;
|
||||
}
|
||||
const reordered = reorder(
|
||||
columns,
|
||||
result.source.index,
|
||||
result.destination!.index,
|
||||
).map(({ id }) => id);
|
||||
|
||||
onDragEnd(reordered);
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="flex max-h-[calc(100%-15rem)] flex-col gap-8">
|
||||
<div className="flex flex-col gap-4">
|
||||
<h4 className="font-medium leading-none">Column Settings</h4>
|
||||
<p className="text-sm text-muted-foreground">
|
||||
Reorder columns by dragging or show/hide them with checkboxes.
|
||||
</p>
|
||||
</div>
|
||||
<div className="self-center">
|
||||
<ShowHideAllColumnsButtons
|
||||
onShowAll={onShowAllColumns}
|
||||
onHideAll={onHideAllColumns}
|
||||
onReset={onReset}
|
||||
/>
|
||||
</div>
|
||||
<div className="overflow-scroll">
|
||||
<DragAndDropList droppableId="columnOrder" onDragEnd={handleDragEnd}>
|
||||
{columns.map((column, index) => (
|
||||
<ColumnCustomizerRow
|
||||
key={column.id}
|
||||
column={column}
|
||||
index={index}
|
||||
/>
|
||||
))}
|
||||
</DragAndDropList>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default ColumnCustomizer;
|
||||
@@ -0,0 +1,49 @@
|
||||
import {
|
||||
DraggableItem,
|
||||
type DraggableItemProps,
|
||||
} from '@/components/common/DragAndDropList';
|
||||
import { Checkbox } from '@/components/ui/v3/checkbox';
|
||||
import { useTablePath } from '@/features/orgs/projects/database/common/hooks/useTablePath';
|
||||
import PersistenDataTableConfigurationStorage from '@/features/orgs/projects/storage/dataGrid/utils/PersistenDataTableConfigurationStorage';
|
||||
import { cn } from '@/lib/utils';
|
||||
import { GripVertical } from 'lucide-react';
|
||||
import type { ColumnInstance } from 'react-table';
|
||||
|
||||
type ColumnCustomizerProps = {
|
||||
column: ColumnInstance;
|
||||
} & Omit<DraggableItemProps, 'draggableId'>;
|
||||
|
||||
function ColumnCustomizerRow({ column, index }: ColumnCustomizerProps) {
|
||||
const tablePath = useTablePath();
|
||||
|
||||
function handleVisibilityChange() {
|
||||
PersistenDataTableConfigurationStorage.toggleColumnVisibility(
|
||||
tablePath,
|
||||
column.id,
|
||||
);
|
||||
column.toggleHidden();
|
||||
}
|
||||
|
||||
return (
|
||||
<DraggableItem draggableId={column.id} index={index} className="mb-3">
|
||||
<div
|
||||
className={cn(
|
||||
'flex w-full items-center justify-between rounded-md bg-accent p-2',
|
||||
{ 'opacity-70': !column.isVisible },
|
||||
)}
|
||||
>
|
||||
<div className="flex items-center gap-5">
|
||||
<Checkbox
|
||||
checked={column.isVisible}
|
||||
className="h-[1.125rem] w-[1.125rem] border-[#21324b] data-[state=checked]:!border-transparent dark:border-[#dfecf5]"
|
||||
onCheckedChange={handleVisibilityChange}
|
||||
/>
|
||||
<span>{column.id}</span>
|
||||
</div>
|
||||
<GripVertical />
|
||||
</div>
|
||||
</DraggableItem>
|
||||
);
|
||||
}
|
||||
|
||||
export default ColumnCustomizerRow;
|
||||
@@ -0,0 +1,30 @@
|
||||
import { Button } from '@/components/ui/v3/button';
|
||||
import { ButtonGroup } from '@/components/ui/v3/button-group';
|
||||
|
||||
type ShowHideAllColumnsToggleProps = {
|
||||
onShowAll: () => void;
|
||||
onHideAll: () => void;
|
||||
onReset: () => void;
|
||||
};
|
||||
|
||||
function ShowHideAllColumnsButtons({
|
||||
onShowAll,
|
||||
onHideAll,
|
||||
onReset,
|
||||
}: ShowHideAllColumnsToggleProps) {
|
||||
return (
|
||||
<ButtonGroup className="w-full">
|
||||
<Button variant="outline" className="flex-1" onClick={onShowAll}>
|
||||
Show all columns
|
||||
</Button>
|
||||
<Button variant="outline" className="flex-1" onClick={onHideAll}>
|
||||
Hide all columns
|
||||
</Button>
|
||||
<Button variant="outline" className="flex-1" onClick={onReset}>
|
||||
Reset
|
||||
</Button>
|
||||
</ButtonGroup>
|
||||
);
|
||||
}
|
||||
|
||||
export default ShowHideAllColumnsButtons;
|
||||
@@ -0,0 +1 @@
|
||||
export { default as ColumnCustomizer } from './ColumnCustomizer';
|
||||
@@ -0,0 +1,81 @@
|
||||
import {
|
||||
Sheet,
|
||||
SheetContent,
|
||||
SheetDescription,
|
||||
SheetHeader,
|
||||
SheetTitle,
|
||||
SheetTrigger,
|
||||
} from '@/components/ui/v3/sheet';
|
||||
import { useTablePath } from '@/features/orgs/projects/database/common/hooks/useTablePath';
|
||||
import { useDataGridConfig } from '@/features/orgs/projects/storage/dataGrid/components/DataGridConfigProvider';
|
||||
import PersistenDataTableConfigurationStorage from '@/features/orgs/projects/storage/dataGrid/utils/PersistenDataTableConfigurationStorage';
|
||||
import { ColumnCustomizer } from './ColumnCustomizer';
|
||||
import { useDataGridCustomizerOpenStateContext } from './DataGridCustomizerOpenStateProvider';
|
||||
import DataGridCustomizerTrigger from './DataGridCustomizerTrigger';
|
||||
import RowDensityCustomizer from './RowDensityCustomizer';
|
||||
|
||||
function DataGridCustomizerControls() {
|
||||
const { allColumns, setColumnOrder, setHiddenColumns } = useDataGridConfig();
|
||||
const tablePath = useTablePath();
|
||||
const { open, setOpen } = useDataGridCustomizerOpenStateContext();
|
||||
|
||||
const columns = allColumns.filter(({ id }) => id !== 'selection-column');
|
||||
|
||||
function saveHiddenCols(cols: string[]) {
|
||||
setHiddenColumns(cols);
|
||||
PersistenDataTableConfigurationStorage.saveHiddenColumns(tablePath, cols);
|
||||
}
|
||||
|
||||
function showOriginalOrder() {
|
||||
setColumnOrder([]);
|
||||
PersistenDataTableConfigurationStorage.saveColumnOrder(tablePath, []);
|
||||
}
|
||||
|
||||
function handleReset() {
|
||||
showOriginalOrder();
|
||||
saveHiddenCols([]);
|
||||
}
|
||||
|
||||
function handleDragEnd(newOrder: string[]) {
|
||||
setColumnOrder(newOrder);
|
||||
PersistenDataTableConfigurationStorage.saveColumnOrder(tablePath, newOrder);
|
||||
}
|
||||
|
||||
function hideAllColumns() {
|
||||
const allColumnsId = columns.map(({ id }) => id);
|
||||
saveHiddenCols(allColumnsId);
|
||||
}
|
||||
|
||||
return (
|
||||
<Sheet open={open} onOpenChange={setOpen}>
|
||||
<SheetTrigger asChild>
|
||||
<DataGridCustomizerTrigger />
|
||||
</SheetTrigger>
|
||||
|
||||
<SheetContent
|
||||
className="box flex w-full flex-col rounded-none md:w-[26rem] md:max-w-[26rem]"
|
||||
onInteractOutside={() => setOpen(false)}
|
||||
showOverlay
|
||||
>
|
||||
<SheetHeader>
|
||||
<SheetTitle>Customize Table View</SheetTitle>
|
||||
<SheetDescription className="sr-only">
|
||||
Customize columns
|
||||
</SheetDescription>
|
||||
</SheetHeader>
|
||||
<div className="flex h-full flex-col gap-8">
|
||||
<RowDensityCustomizer />
|
||||
<ColumnCustomizer
|
||||
columns={columns}
|
||||
onDragEnd={handleDragEnd}
|
||||
onReset={handleReset}
|
||||
onShowAllColumns={() => saveHiddenCols([])}
|
||||
onHideAllColumns={hideAllColumns}
|
||||
/>
|
||||
</div>
|
||||
</SheetContent>
|
||||
</Sheet>
|
||||
);
|
||||
}
|
||||
|
||||
export default DataGridCustomizerControls;
|
||||
@@ -0,0 +1,43 @@
|
||||
import {
|
||||
createContext,
|
||||
type Dispatch,
|
||||
type PropsWithChildren,
|
||||
type SetStateAction,
|
||||
useContext,
|
||||
useMemo,
|
||||
useState,
|
||||
} from 'react';
|
||||
|
||||
type DataGridCustomizerOpenStateContextProps = {
|
||||
open: boolean;
|
||||
setOpen: Dispatch<SetStateAction<boolean>>;
|
||||
};
|
||||
|
||||
const DataGridCustomizerOpenStateContext =
|
||||
createContext<DataGridCustomizerOpenStateContextProps>({
|
||||
open: false,
|
||||
setOpen: () => {},
|
||||
});
|
||||
|
||||
function DataGridCustomizerOpenStateProvider({ children }: PropsWithChildren) {
|
||||
const [open, setOpen] = useState(false);
|
||||
const value = useMemo(
|
||||
() => ({
|
||||
open,
|
||||
setOpen,
|
||||
}),
|
||||
[open],
|
||||
);
|
||||
return (
|
||||
<DataGridCustomizerOpenStateContext.Provider value={value}>
|
||||
{children}
|
||||
</DataGridCustomizerOpenStateContext.Provider>
|
||||
);
|
||||
}
|
||||
|
||||
export function useDataGridCustomizerOpenStateContext() {
|
||||
const context = useContext(DataGridCustomizerOpenStateContext);
|
||||
return context;
|
||||
}
|
||||
|
||||
export default DataGridCustomizerOpenStateProvider;
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user