Compare commits

...

134 Commits

Author SHA1 Message Date
Romeo Van Snick
c4f410fe2e Fix more types 2026-03-18 16:31:41 +11:00
Romeo Van Snick
2032155e01 Fix types 2026-03-18 16:31:41 +11:00
Romeo Van Snick
bab2613614 Fix types 2026-03-18 16:31:41 +11:00
Romeo Van Snick
cda59efae8 Convert query_builder selectors to ts 2026-03-18 16:31:40 +11:00
Romeo Van Snick
bf8eff4b81 Convert query_builder reducers to js 2026-03-11 16:11:07 +11:00
Romeo Van Snick
820c4a3526 Convert native editor mocks to ts 2026-03-11 14:20:55 +11:00
Romeo Van Snick
efda4aa47e Convert dataref to ts 2026-03-11 14:20:55 +11:00
Romeo Van Snick
4614779a95 Move query_builder/analytics 2026-03-11 14:20:27 +11:00
mendral-app[bot]
ce8660f161 Use env vars for embedding workflow (#70614)
fix: prevent script injection via PR title in embedding-sdk workflow

Move user-controlled PR context values (title, number, URL) and secrets
from direct GitHub Actions expression interpolation into env vars.
This prevents a crafted PR title from breaking out of the shell string
and executing arbitrary commands on the runner.

Co-authored-by: mendral-app[bot] <233154221+mendral-app[bot]@users.noreply.github.com>
2026-03-10 06:51:16 +04:00
Denis Berezin
dcf260f4c9 Fix broken e2e test for #68998 (#70585) 2026-03-10 03:24:04 +03:00
Aleksandr Lesnenko
4897452a08 Metrics Explorer (#68961)
Co-authored-by: Edward Paget <ed.paget@gmail.com>
Co-authored-by: Alexander Polyankin <alexander.polyankin@metabase.com>
Co-authored-by: John Swanson <john.swanson@metabase.com>
Co-authored-by: Nick Fitzpatrick <nick@metabase.com>
Co-authored-by: Edward Paget <edpaget@users.noreply.github.com>
Co-authored-by: Kevin Kelleher <kevin.kelleher@metabase.com>
Co-authored-by: Maz Ameli <maz@metabase.com>
2026-03-09 20:18:15 -04:00
dpsutton
c87ad18e21 quarantined driver notifications (#70612)
* quarantined driver notifications

* temp on push to bot-testing channel

* prettier

* more compact

* add back a bit of emphasis

* remove push edge and restore channel
2026-03-09 18:14:56 -05:00
Fraser
78a8c59d71 Move expandable string to where it's used (#70559) 2026-03-10 12:08:58 +13:00
Fraser
336c2a8b1a Convert OnClickOutsideWrapper to TypeScript (DEV-1496) (#69418)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-10 11:50:54 +13:00
Rodrigo López Dato
567bbd68bb Clarify that SSO provisioning also allows reactivating accounts (#67524)
* Clarify that SSO provisioning also allows reactivating accounts

* Update wording in docs

* ditto LDAP

* Use radio buttons instead of a toggle

* lint/wording

* lint

* Revert changes to autogenerated docs

* Fix eslint rule + improve wording

* Make OIDC provisioning setting consistent with other providers

* Add detailed descriptions only to env var docs, not UI

* Fix E2E test

* fix: update ESLint configuration file path from .eslintrc.js to eslint.config.mjs

* run lint when we change component tests specs

* fixing linting

* ignore linting issue in embedding test

---------

Co-authored-by: Nicolò Pretto <info@npretto.com>
Co-authored-by: Nick Fitzpatrick <nickfitz.582@gmail.com>
2026-03-09 18:09:00 -03:00
Braden Shepherdson
ba6895665f [MBQL lib] Ignore inherited-temporal-unit on bucketed columns (#70512)
Fixes QUE2-394.

This issue was caused by losing the thread of a column between stages in
the case where it has a different `:inherited-temporal-unit` than its
proper `:temporal-unit`.

`lib.equality/=` was checking the `:temporal-unit`s, which match, and
then returning `false` because only one column had
`:inherited-temporal-unit` for a different, finer unit. That shouldn't
fail the match, since the `:inherited-temporal-unit` is obsolete when
the column has just been bucketed differently.
2026-03-09 21:02:10 +00:00
Ben Grabow
09c04d91bb Remove minimally useful semantic search log messages (#70524) 2026-03-09 21:01:38 +00:00
Jeff Bruemmer
8977542307 docs - remote sync limitations (#70598)
* branch limitations

* edits

* link

* Apply suggestions from code review

Co-authored-by: Alex Yarosh <alexandra@metabase.com>

---------

Co-authored-by: Alex Yarosh <alexandra@metabase.com>
2026-03-09 20:51:35 +00:00
Ben Grabow
ec678a17fc Uxw 1070/fail early if unsupported appdb version is detected (#70402) 2026-03-09 15:33:16 -05:00
Chris Truter
6eda44fc53 Fix reflection warnings in tests + add linter (#70551) 2026-03-09 13:29:04 -06:00
metamben
4219500b7a Preserve expression names when fixing bad field refs (#70530)
Closes QUE2-397
2026-03-09 21:48:51 +03:00
Will Bryant
2f2ab17ebb Fix race condition in FormattingWidget initialization (#69777) (#69778)
Although there was an early return if isLoading is true, the useState had already run, and set the state to the DEFAULT_FORMATTING_SETTINGS. This would then not get replaced when isLoading became false.

Instead, use the same idiom as SessionTimeoutSetting - install a useEffect hook that depends on the setting value and applies that setting value to the local state.
2026-03-09 11:43:20 -07:00
Maksym Yakubych
89c1712267 fix: Metabot not receiving transform errors from transforms (#70462) 2026-03-09 15:54:48 +00:00
Nicolò Pretto
ba03f8d368 remove ThemeProvider from sdk component test (#70568) 2026-03-09 16:51:29 +01:00
Edward Paget
6d84d80c06 fix: allow dashboard caching in read-only mode (#70511)
* fix: allow dashboard caching in read-only mode

* fix: split out cache permissions from can-write?

We were denying changing caching policy for dashboards on read-only
remote-synced instances because we set can-write? to false for
dashboards when we are in read-only mode.

we also need to create a new boolean flag we can return to the frontend
to indicate that caching is still allowed even when editing a dashboard
is otherwise disabled.

* fixup! PR feedback
2026-03-09 10:37:16 -05:00
Denis Berezin
b130d0d812 Pivot Table shows a blank card when rendered on a dashboard (#70385) 2026-03-09 18:18:37 +03:00
Riley Thompson
caafceff99 Upgrade clickhouse to 0.9.7 with pinned dependencies (#70448)
* upgrade clickhouse jdbc to 0.9.7

* clean up todos

* update deps
2026-03-09 11:12:36 -04:00
Jakub Chodorowicz
5fe95dbbae fix self-heal openapi job and update openapi.json (#70499) 2026-03-09 15:42:44 +01:00
Nicolò Pretto
65d9029a55 fix: update ESLint configuration file path for eslint config (#70507)
* fix: update ESLint configuration file path from .eslintrc.js to eslint.config.mjs

* run lint when we change component tests specs
2026-03-09 13:32:17 +00:00
github-automation-metabase
e4ec44c4af Auto-update documentation for master (#70560)
Update generated docs (master)

Co-authored-by: github-actions <github-actions@github.com>
2026-03-09 09:28:12 -04:00
Uladzimir Havenchyk
0e9fd4c48c add transform-basic feature flag for transforms (#70442)
* add another feature flag for transforms

* fix linting error from master

* add debug info

* enable-transforms-basic -> enable-basic-transforms

* remove logs
2026-03-09 15:08:51 +03:00
Phoomparin Mano
cd32f3b89c Integration branch for embedding onboarding improvements (#69456)
* Add "configure data permissions and enable tenants" skeleton for onboarding (#68895)

* use onboarding stepper

* add TODO for EMB-1266

* add e2e test for skeleton

* use gap=sm for steppers

* align with design

* Add completion checks for data segregation and tenants (#68890)

* add completion information for segregation and tenants

* add data segregation checks

* add data segregation config test

* add the combined data-permissions-and-enable-tenants step

* separate main and sub checklist

* explain the purely ui step

* add schema for checklist response

* update checklist completion states

* add test cases

* address review on test permutations and using is_active for tests

* remove stale configure data permissions unit test

* remove stale test on user strategy card

* Add enable tenants and create shared collection button (#69131)

Add enable tenants and create shared collection button (#69131)

* Add data segregation strategy selection step for embedding onboarding (#69127)

Add data segregation strategy selection step for embedding onboarding (#69127)

* Lock steps 2 to 5 in data permissions setup checklist (#69135)

Lock steps 2 to 5 in data permissions setup checklist (#69135)

* Add link to documentation for database routing in the onboarding step (#69138)

Add link to documentation for database routing in the onboarding step (#69138)

* Add tenant creation and tenant summary step for tenants onboarding (#69454)

Add tenant creation and tenant summary step for tenants onboarding (#69454)

use index as key instead

update failing unit test

refactor: use slugify instead

add assertion on configure data permissions step should be done

cleanup summary components

adjust font size

use related setting card for summary

refactor: cleanup card components

add e2e test verifying tenant errors are shown

add e2e test verifying tenants are created

fix: prevent going to previous incomplete step

fix: skip locked steps

fix: consider locked steps when auto-advancing

fix: failing e2e by enabling tenants via ui

refactor: cleanup tenants import

add fallback logic for tenants listing

refactor: move onboarding step to tenants plugin

scaffold tenant summary step

scaffold tenant creation step

use paper from mantine-ui instead

scaffold tenant creation step

* Onboarding stepper should navigate to next steps correctly even when all steps are done (#69653)

Onboarding stepper should navigate to next steps correctly even when all steps are done (#69653)

cleanup: remove redundant test

fix: cleanup broken tests

remove inapplicable test case

apply onboarding stepper fixes

* Add row and column level security step for onboarding (#69622)

fix failing e2e tests

wait for permission graphs to update before checking error toasts

add test assertion on hiding selected tables

hide tables that are selected by other cards

add unit test for building permissions graph

address review on type-safe sandbox policy

extract error and success toasts into UI consumer

add clarification on why we assert GTAP

extract MiniPicker hard-coded margins to the data picker call site

address review on using design system units and rem

address review on "All tenant users" permission update hook

Add row and column level security step for onboarding

revert all changes to OnboardingStepper

update the permission graph as well

refactor: renamings

lock step "Select data to make available" if strategy not chosen

cleanup: remove button

use metabase/ui for select style

refactor: extract table column card

simplify trigger styles

revert MiniPicker change

undo test name change

refactor: simplify stepper

update e2e test assertions

add step completion assertion to e2e tests

refactor: extract to step components

allow going to next step

fix onboarding stepper re-rendering

chore: cleanup sandboxing creation test

add e2e tests

add sandbox on clicking next

clicking next on rls selector should advance to next step

refactor: rename to selections and onSelectionsChange

display options on the bottom

position dropdown directly below the trigger

fix: trigger height

fix: do not hide title on RLS step

do not collapse current step when all steps are complete

make it clearer what is goToNextIncompleteStep

simplify logic for going to next incomplete step

add data selector for row and column security

* Create a multi-select database selector component (#69635)

Create a multi-select database selector component (#69635)

chore: remove fluff tests

allow disabling rightSection with null

add data fetching to DatabaseMultiSelect

use multi autocomplete

add storybook story and unit test for disabled options

allow disabling database options

update multi select tests

chore: formatting

cleanup dropdown style

show placeholder always

apply brand focus color

remove inline-end

limit combo box width

update styles to match figma design

update option icon

scaffold database multi select

* Add connection impersonation onboarding step (#69644)

Add connection impersonation onboarding step (#69644)

add permission graph and impersonation assertion

add e2e test

use useUpdateTenantGroupPermissions for permission updates

add connection impersonation creation hook

add edge case for database does not support impersonation

disable dbs without connection impersonation

scaffold ui for connection impersonation

* Add JWT authentication onboarding for embedding hub (#69823)

test: e2e fail due to lock icons found in related settings section

replace e2e test on jwt completion

update e2e tests

scaffold e2e tests

refactor: cleanup sso stepper component

add help url and complete step button

scaffold "Test that JWT authentication is working correctly" step

scaffold "Add a new endpoint to your app" step

add ui to configure identity provider

scaffold sso setup

* Mark get embed snippet step as done when guest embed is published (#69889)

* mark guest embedding onboarding test step as done

* add e2e test for guest embed

* simplify e2e test

* fix invalid imports due to merge conflicts

* fix guest embed snippet copy incorrectly marking production embed step as done

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>

* Embed wizard should default to newly created dashboards (#69907)

Embed wizard should default to newly created dashboards (#69907)

scaffold defaulting to newly created dashboards

add a comment on why newly created dashboards are prioritized

chore: update inline comments

de-duplicate recent items at call site

refactor: cleanup implementation

add created_at time filter

address review feedback on variable naming

address review by going through actual x-ray flow

remove invalid unit test

update duplicated and failing tests

fix failing tests

fix failing select-embed-experience e2e test

fix failing select-embed-entity e2e test

* Remove create models step from embedding onboarding checklist (#70256)

remove create models step

* Show tenant_identifier autocompletion from column values in RLS (#69829)

Show tenant_identifier autocompletion from column values in RLS (#69829)

scaffold basic tenant_identifier autocompletion

make placeholder dynamic to tenant identifier input

fix: update broken types

document why we use ad-hoc query

refactor: small cleanup

cleanup docstring

chore: update hook tests

add e2e tests for autocompletion

explicitly pass tenant attributes

simplify CreateTenantInput

Suppress ad-hoc query errors in tenant identifier autocomplete

Autocomplete suggestions are best-effort during onboarding. Query
failures (permissions, timeout, etc.) should not surface global
error UI noise.



Make attributes optional in CreateTenantInput to match API contract

The backend marks attributes as optional; the frontend type was
overly strict and forced callers to always send attributes: {}.



Derive selectedFieldIds from sandboxedTables, not tableColumnSelections

Previously, field IDs were extracted from all tableColumnSelections,
including entries skipped because the table failed to fetch. Now we
only include IDs from policies that were actually applied, deduplicated.



Use stable placeholder and aria-label in TenantIdentifierInput

The old dynamic placeholder (first suggestion value) looked pre-selected
to users. Now prefix with "e.g." using c().t for localization context,
falling back to "e.g. acme-corp" when no suggestions are loaded. Also
adds aria-label for accessible and stable test targeting.



Update E2E tests to use "e.g. 1" placeholder for tenant_identifier input

The placeholder is now prefixed with "e.g." to clarify it's an example.
This also implicitly validates that autocomplete suggestions were fetched
successfully, since the placeholder is dynamic when data is available.

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>

* Tenant creation should differ the data isolation field by strategy (#70258)

Tenant creation should differ the data isolation field by strategy (#70258)

scaffold implementation on tenant isolation fields

refactor: use ts-pattern for isolation field config and label lookups

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

update checklist endpoint to return checklist separate from isolation strategy field

refactor: use dataIsolationFieldValue field for creating tenants

fix: use activeStrategy for reload-aware strategy picker and step content

On page reload, selectedStrategy is null but activeStrategy is populated
from the backend. Switch the data segregation picker value, select-data
step lock condition, title hide flag, and match expression to use
activeStrategy so the correct state is reflected on reload.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

tweak tenant name styling

always require data isolation strategy field value to create tenants

update embedding hub checklist backend test

add e2e tests for reload and isolation strategy

fix: remove hard-coded string in tenant identifier input

refactor: move DataSegregationStrategy type to embedding-hub types module

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

refactor: remove single-letter variables

* Show segregation strategy specific data permissions in tenant summary (#70268)

Show segregation strategy specific data permissions in tenant summary (#70268)

show segregation strategy specific summary

test: add unit tests for getDataPermissionsDescription

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

fix: add selectedFieldIds to TenantsSummaryOnboardingStep plugin interface

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

add e2e test assertions and test cases

simplify row-level security summary logic

fix rls imports

update data permission description span

add bold text to description summaries

fix failing e2e tests

fix starter test failing

remove focused test

update comment on the rls e2e test

fix: use singular 'table' for single-table RLS data permissions description

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

add a comment on why RLS needs the same column

use conjunct method for string formatting

simplify textFromReactNode

simplify getDataPermissionsDescription unit test

chore: code formatting

remove route title

fix: failing test due to placeholder update

remove the starter test as it does not apply

fix: reset hiddenParameters when switching from guest to SSO embed mode for dashboards

When recentlyCreatedDashboards pre-populates the dashboardId, the resource loads
in guest mode and initializes hiddenParameters with all parameters as disabled.
Switching to SSO now resets hiddenParameters to [] for dashboard embeds, matching
the existing behavior for question embeds.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

fix ignore_error flag

fix: incorrect test assertion for database selector

fix: incorrect placeholder assertion

* Tenant users are unable to query database after onboarding flow (#70476)

Tenant users are unable to query database after onboarding flow (#70476)

fix(embedding): set create-queries permission for RLS tenant users

Tenant users with RLS could view dashboards but were unable to query
the database because the permissions graph only set `view-data` without
`create-queries`. Add `"create-queries": "query-builder"` at the
database level for both sandboxed and impersonated configurations.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

fix: update unit tests on embed settings

fix failing tests due to parameters reset

* Polish tenant creation and SSO for embedding onboarding (#70477)

Polish tenant creation and SSO for embedding onboarding (#70477)

polish permissions setup and create tenants onboarding

update copy for tenant identifier

* fix(type): add rlsColumnName type to plugin defs

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-09 19:02:34 +07:00
Fraser
6d79bbc173 Stop using 2am in tests to avoid DST issues (#70562)
* Stop using 2am in tests to avoid DST issues

* Scope to table cell data
2026-03-09 07:41:57 +00:00
Eric Normand
7c8125d4bb Fix typo in self-dependency removal GHY-3198 (#70535)
There was a typo in a transducer where the cat and remove were swapped. The cat was meant to combine collections (`#{x})` and the remove was looking for `x`, but since it happened in the wrong order, it never removed them. This led to self-dependent entities, and therefore cycles which caused infinite loops.
2026-03-07 21:58:17 +00:00
Chris Truter
54439261a4 Fix case sensitiviy issues with workspace query execution (#69350) 2026-03-07 07:35:50 +00:00
Maz Ameli
18706c2456 Switch component improvements (#70520)
* fix toggle alignment

* reduce space above description

* change usage guidelines to recommend sm

* Update Loki Snapshots

---------

Co-authored-by: Metabase Automation <github-automation@metabase.com>
2026-03-06 22:57:08 +00:00
Chris Truter
3d5b673c9a Support template tags in Workspace transforms (#69561) 2026-03-06 21:21:37 +00:00
Chris Truter
0e1325ba1e Implement scoped authorization to limit API surface (#70372) 2026-03-06 23:01:36 +02:00
Jacob Joseph
9c801dfbd9 Fix numbered list for row and column security section (#70525) 2026-03-06 20:31:04 +00:00
Nick Fitzpatrick
c27eee3f51 ignore linting issue in embedding test (#70514) 2026-03-06 16:13:58 -04:00
Maksym Yakubych
1cfc71fed7 fix: NLQ profile incorrectly used for SQL editor requests (#70436)
* fix: NLQ profile incorrectly used for SQL editor requests

* fix: tests
2026-03-06 12:55:40 -06:00
Nathan Voxland
619f2b2be6 Add repro-bot github workflow (#70435) 2026-03-06 11:02:20 -06:00
Nick Fitzpatrick
64978428b8 fixing linting (#70504) 2026-03-06 16:55:14 +00:00
dpsutton
58d2cd37b6 bump c3p0 to 0.12.0 (#70494) 2026-03-06 09:36:34 -06:00
Nicolò Pretto
6901847ed2 remove noisy logs from sdk component tests (#70416)
* should fix clj files imported from sdk component tests

* reduce noise when not finding the sdk package

* remove mantine from tests that don't need it

* eslint rule
2026-03-06 16:32:49 +01:00
Nicolò Pretto
10286754ee feat(sdk): speed up the embedding sdk loading time: do auth flow in parallel with bundle loading and split the bundle in chunks (#70015)
* test ci

* fix

* fix e2e

* make linters happy?

* more ci fixes

* more ci fixes

* maybe fix flake

* more ci things?

* more things including a test that we do fallback to old auth

* remove un-needed changes

* more cleaning

* make tests more stable

* clean up debug comments

* remove ! that was not needed

* fix broken build

* cleanup

* more cleaning up

* more cleanup

* clean up consts

* more cleaning up and saml bail out tests + logic

* revert uneeded change in copy js plugin

* better comments and renamed chunk auth function

* merge test files, fix double auth requests done due to missing redux dispatch

* fix typo in backend comment

* fixed version of renaming param to useLegacyMonolithicBundle

* remove cy wait

* remove wait + fix matcher on request for dev mode to not match map file

* clean up tests

* remove empty lines from gitignore

* remove unrelated gitignore change

* r emove imports

* cleanup tests from redundant tests

* remove other un-needed code

* comments

* add date to a TODO as suggested by Kelvin

* Apply suggestion from @Copilot

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* rename checkForAuthConfig -> checkForAuthConfigAndStartAuth

* startAuth -> startJwtAuth

* use new URL to construct baseUrl

* use shared auth  logic

* use the real version as we can actually

* add comment on numTestsKeptInMemory usage

* add test about path traversal

---------

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2026-03-06 14:51:25 +00:00
Nicola Mometto
8f1606adc5 Allow loading of 58 serialized tables in 59+ (#70486)
* fix: allow importing 58 serialized data-layer values

* add test
2026-03-06 14:13:16 +00:00
Ngoc Khuat
5b6e3071ac Fix duplicate alerts/subscriptions firing in multi-pod clusters (#70474)
* Fix duplicate alerts/subscriptions firing in multi-pod clusters

Set acquireTriggersWithinLock=true to force pessimistic locking during
trigger acquisition. Without this, Quartz uses an optimistic UPDATE that
is vulnerable to an ABA race condition where multiple cluster nodes can
acquire and fire the same trigger simultaneously.

* Add *warn-on-reflection* to custom_migrations/util

Fixes clj-kondo warning triggered by Java interop (System/setProperty,
System/clearProperty) added in the acquireTriggersWithinLock fix.
2026-03-06 10:35:46 -03:00
Edward Paget
76e96af834 fix: only skip deleting commonpy not pushing it (#70439)
* fix: only skip deleting commonpy not pushing it

* fixup! kondos
2026-03-06 07:16:39 -06:00
Sébastien
92017bab3f fixed table width in guest embed (#70418)
* fixed table width in guest embed

* fixed test
2026-03-06 14:10:57 +01:00
Ngoc Khuat
c86caa092e Unifying source tables transform format (#70298) 2026-03-06 18:48:41 +07:00
Jakub Chodorowicz
29590b8e09 Fix TS failure - duplicated selectors (#70480)
remove duplicated selectors
2026-03-06 10:07:41 +00:00
Ngoc Khuat
e822288497 GDGT-1872: Change transform metering to tier-based keys (#70366) 2026-03-06 05:46:42 +00:00
Noah Moss
a6c90cc7ff Filter out inactive tables for metabot (#70440)
* Filter out inactive tables for metabot

* fix another spot
2026-03-05 23:02:01 +00:00
Riley Thompson
1571e58188 Data migration to fix clickhouse upload dbs with missing schema (#70363)
* testing

* add migration

* add test

* reorder test

* improve migration

* improve test

* add comment explanation

* fmt
2026-03-05 17:05:33 -05:00
Fraser
ae1e0d6311 Convert admin/people/selectors to TypeScript (#69431)
* Convert `admin/people/selectors` to TypeScript

Part of the Accelerate TypeScript Migration project.

Closes DEV-1509

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* Add people property to AdminState type

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-06 10:57:15 +13:00
Fraser
3f547462c9 Convert linked-filters to ts (#70045) 2026-03-06 10:57:01 +13:00
Jeff Bruemmer
05aaad4f3a README - updates (#70460) 2026-03-05 16:02:15 -05:00
Ben Grabow
92ec0df7b1 Ignore some generated files (#70454) 2026-03-05 14:56:22 -06:00
metamben
35b542b651 Fix column-metadata->field-ref-source-alias-test (#70458) 2026-03-05 20:21:57 +00:00
Cam Saul
ab7e4712b1 Omit pivot-grouping from window function OVER PARTITION BY and ORDER BY expressions (#70273)
* Experimental fix for #70088

* cljfmt

* Document the new key

* Cleanup
2026-03-05 10:31:07 -08:00
Maksym Yakubych
47471f9518 fix: metabot returns null for pasted question references (#70388) 2026-03-05 12:23:16 -06:00
Eric Normand
86868639b4 test: mutation tests for column-metadata->field-ref (#69342)
* [Mutation Testing] Add tests for metabase.lib.field/fieldable-columns

* test: mutation tests for column-metadata->field-ref source-alias propagation

Tests the MEGA HACK source-alias-to-join-alias propagation in column-metadata->field-ref:
- Verifies source-alias becomes :join-alias for table-default columns
- Verifies inherited columns do not propagate source-alias
- Verifies inherited columns do not get non-inherited propagated keys

Kills 6 more mutations (51/60 total, 9 unkillable due to schema constraints).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-05 12:23:21 -05:00
Eric Normand
c61c93e825 test: mutation tests for add/remove field operations (#69329)
* [Mutation Testing] Add tests for metabase.lib.field/fieldable-columns

* test: mutation tests for add-field, add-field-to-join, remove-field, remove-field-from-join

Adds tests that kill surviving mutations:
- add-field: expression column with explicit :fields (kills :source/expressions mutation)
- add-field-to-join: join with :none fields (kills 5 mutations)
- remove-field: expression column removal (kills :source/expressions mutation)
- remove-field-from-join: join with :none fields (kills 4 mutations)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-05 10:44:10 -06:00
Filipe Silva
6dfde80586 rfct: remove superfluous comments (#69099)
Fix https://github.com/metabase/metabase/pull/68478#discussion_r2760627013
2026-03-05 15:48:59 +00:00
Nemanja Glumac
009911d60a Fix incomplete URL substring sanitization in LeafletMap (#70428)
The previous check used `.includes("openstreetmap.org")` which could be
bypassed by malicious domains like `openstreetmap.org.evil.com` or
`fake-openstreetmap.org`.

This fix validates that the hostname is either exactly `openstreetmap.org`
or a legitimate subdomain ending with `.openstreetmap.org`.

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
2026-03-05 14:40:14 +00:00
Braden Shepherdson
237bbe2919 [MBQL lib] Unexport lib.options namespace (#70276)
Fixes QUE2-351.

I added a new exported function `lib/ignore-case`, since some drivers,
test, and Metabot were using `lib.options/update-options` to set
`:case-sensitive false` on `:contains` et al clauses.

`lib.options` is only used by friends now (mostly QP).
2026-03-05 14:28:44 +00:00
Oleksandr Solovyov
c8b1767e66 Semantic search speedup (#70317)
* do not put embeddings in metadata json for semantic search
* semantic search: filter personal_owner_id right in the database
* simplify batch-update code
2026-03-05 15:18:13 +02:00
Uladzimir Havenchyk
18e327042f chore: drop unnecessary react imports (#70415) 2026-03-05 16:00:30 +03:00
Alberto Perdomo
f02d26aa14 EMB-1329: update embed wizard terms copy and add link (#69856)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: Phoomparin Mano <poom@metabase.com>
Co-authored-by: Nicolò Pretto <info@npretto.com>

closes #69302
Closes linear.app/metabase/issue/EMB-1329/embedding-tooltip-directs-you-to-read-license-text-linked-above-no
2026-03-05 11:58:06 +00:00
Timofey Kachalov
8056c1835a fix(sdk): Fix the empty container detection in SDK question layouts (#70389) 2026-03-05 15:40:13 +04:00
Kevin Kelleher
04055423f0 Admin TS conversions (#69825) 2026-03-05 06:37:33 -05:00
Uladzimir Havenchyk
4e7d009a53 chore: convert Text visualization to typescript (#70364)
* chore: convert Text visualization to typescript

* fixup
2026-03-05 10:28:55 +03:00
Romeo Van Snick
a41303a180 Wrap buttons and title on smaller screens (#67681)
* Wrap title and buttons earlier when nav bar is open

* Wrap title in header at wider breakpoint

* Left align ad-hoc questions too

* Add gap when question title collapses

* Increase breakpoint

* Fix padding on ViewSection

* Use container query for query builder breakpoints

* Make padding more consistent with other headers on small screens

* Tweak question action buttons on small screens

* Add separator for actions

* Fix padding on filter panel

* Fix padding on back button

* Fix padding to match header

* Break sooner

* Do not break subheader as soon

* Fix test

* Remove reliance on query-builder from FilterPanel component

* Remove spurious margin

* Fix gap between header items

* Move container to header and footer
2026-03-05 15:02:09 +11:00
Fraser
8474a8f7f5 Convert metabase-lib utils to ts (#70044) 2026-03-05 16:24:06 +13:00
Anderson
2b61cce77b Don't call trial check EE endpoint in OSS for Remote Sync upsell (#70349) 2026-03-04 21:16:03 -05:00
Riley Thompson
0a0625d163 Revert "Upgrade clickhouse jdbc driver to 0.9.7" (#70403)
Revert "Upgrade clickhouse jdbc driver to 0.9.7 (#70387)"

This reverts commit 3a69ad8f49.
2026-03-04 16:50:23 -08:00
Jeff Bruemmer
bb42762372 docs - keys to data studio (#70405)
* keys to data studio

* link
2026-03-04 18:04:50 -05:00
Alexander Polyankin
420c4e27e0 Add writable-connection feature flag (#70287) 2026-03-04 15:54:40 -07:00
Romeo Van Snick
7d8f3849bf Polish transform template tag frontend (#70095)
* Rename confusingly named setParameterAttribute

* Remove unnecessary check

* Add options to disable parameter settings

* Disable parameters settings in transform sidebar

* Add e2e test for parameter field settings

* Rename disableParamaterSettings to parametersAreUserVisible

* Make parametersAreUserVisible configurable all the way up to QueryEditor

* Update copy when parameters aren't visible to user

* Fix test
2026-03-04 13:37:06 -08:00
Denis Berezin
def46a7c0c Update jspdf to fix security issues (#70393) 2026-03-04 23:28:10 +03:00
Riley Thompson
3a69ad8f49 Upgrade clickhouse jdbc driver to 0.9.7 (#70387)
* upgrade clickhouse jdbc to 0.9.7

* clean up todos
2026-03-04 19:22:08 +00:00
metamben
3a62030c09 Generate different column group names for joins to the same table (#70119)
* Generate different column group names for joins to the same table

Closes QUE2-180
2026-03-04 18:52:17 +00:00
metamben
8a93fb4fcd Make excluded-datetime return integers for days too (#69915)
* Make excluded-datetime return integers for days too

Closes QUE2-254
2026-03-04 18:24:04 +00:00
Egor Grushin
483117981c DEV-1599 DEV-1598 fix flakiness (#70166) 2026-03-04 17:51:33 +00:00
Nicola Mometto
88f48ce996 Restrict notification schema and allowed template values (#70261)
* fix: restrict channel renderer to hbs files in the template path

* restricted api schemas

* explicit validation

* chore: tests

* fix: test
2026-03-04 15:23:35 +00:00
Rodrigo López Dato
7eb9d27107 Conceal JWT signing secret by default (#70329) 2026-03-04 11:50:29 -03:00
Nemanja Glumac
c5b8eef4d9 Add cache restore keys for M2 and Node modules (#70370) 2026-03-04 14:17:36 +00:00
Chris Truter
9c44b33887 Add malli typing for transform execution methods (#70250) 2026-03-04 13:23:12 +00:00
Nicola Mometto
3b030bcd58 fix test after out-of-order merge (#70368) 2026-03-04 13:01:13 +00:00
Nicola Mometto
4b9c2e7720 support multiple join conditions in join-analysis lens (#70247)
* fix: count on the condition rather than trying to extract field, generalized for multiple join conditions

* chore: tests

* fix: inline
2026-03-04 11:59:29 +00:00
Chris Truter
57586f2427 Extract non-appdb module out of transforms (attempt #3) (#70245) 2026-03-04 09:50:35 +00:00
Stas Gavrylov
d813be6b09 GDGT-1755: Migrate AdHocQuestionLoader, Breadcrumbs, QuestionLoader, QuestionResultLoader, SavedQuestionLoader to TS (#70106)
* Migrate AdHocQuestionLoader component to TS

* Migrate Breadcrumbs to TS

* Migrate QuestionLoader, QuestionResultLoader, SavedQuestionLoader to TS

* GDGT-1755: Add type guards for Breadcrumbs

* GDGT-1755: Restore comments

* GDGT-1755: Address review comments

* GDGT-1755: Fix tests

* GDGT-1755: Rename type
2026-03-04 11:30:20 +02:00
Chris Truter
ccd3e61ff0 Fix clickhouse transform flake, hopefully (#70316) 2026-03-04 08:49:54 +00:00
Ben Grabow
5e647df5be Add bgrabow (#70347) 2026-03-03 22:18:36 +00:00
Braden Shepherdson
04a5c90dab [MBQL lib] Move lib.util/join-strings-with-conjunction to util.i18n (#70270)
Fixes QUE2-371.

This function has nothing to do with lib, and only depends on
`clojure.string`.
2026-03-03 22:13:40 +00:00
Nathan Voxland
bbc00a8677 Don't fail on unknown settings when calling set-many (#70282) 2026-03-03 15:57:10 -06:00
Nemanja Glumac
a43d62a505 Disable scheduled cloverage reports (#70313) 2026-03-03 22:39:11 +01:00
Ben Grabow
693ac2a9ce Make a mage task to generate resolve-as XML from clj-kondo lint-as data (#70342) 2026-03-03 15:33:17 -06:00
Alex Yarosh
d4a888c2ec docs: a lot of updates (#70176)
* oops

* links

* more links

* Update docs/configuring-metabase/appearance.md

* Apply suggestions from code review

Co-authored-by: Jeff Bruemmer <jeff.bruemmer@gmail.com>

* Apply suggestions from code review

Co-authored-by: Jeff Bruemmer <jeff.bruemmer@gmail.com>

---------

Co-authored-by: Jeff Bruemmer <jeff.bruemmer@gmail.com>
2026-03-03 20:39:03 +00:00
Alex Yarosh
73a53fd72d docs: update default target branch for docs autogen (#70334)
Update default target branch to release-x.59.x
2026-03-03 20:04:50 +00:00
Abed Habli
7a88dfba69 Docs V59: Adding profile icon for non-admin nav paths (#69969)
adding profile icon for non-admin nav paths
2026-03-03 14:30:32 -05:00
Alex Yarosh
b6b44f3cd6 docs: transform screenshots (#70225)
* transform updates

* more transform

* Optimized 11 images, saved 1015.9 KB (45.3% smaller)

* screenshot typo

---------

Co-authored-by: Metabase Automation <github-automation@metabase.com>
2026-03-03 14:19:42 -05:00
Jeff Bruemmer
e586b78513 docs - embedded Metabot (#70275) 2026-03-03 18:44:55 +00:00
John Swanson
330fb2727e SSO users can reset password if provider disabled (#70219)
Previously, password-reset-disabled? blocked password reset for all
SSO users unconditionally (except Google when SSO was globally
disabled). After a license downgrade, EE SSO users were locked out —
they couldn't use SSO (no license) and couldn't reset their password
either.

Introduce sso-source-enabled? which checks whether a user's specific
SSO provider is currently active, using setting/get to respect the
:feature guards on EE settings. password-reset-disabled? now delegates
to this function, so password reset is only blocked when the provider
is actually usable.
2026-03-03 10:42:00 -08:00
Maksym Yakubych
ea89a862ec feat: improve mention menu in metabot (#69650) 2026-03-03 17:33:32 +00:00
Alex Yarosh
0e6915287b docs: start redirect (#70323)
start redirect
2026-03-03 12:25:40 -05:00
Jakub Chodorowicz
d0ffa5115d Gdgt 1801 visualization typescript conversions leafletmap.tsx (#70248) 2026-03-03 17:26:53 +01:00
dpsutton
86dcec8883 Set team.json and assign modules: (#70309)
team:

```javascript
    {
      "name": "Graphy",
      "label": ".Team/Graphy",
      "members": [
        "ranquild",    // alex p
        "romeovs",     // romeo
        "ericnormand", // eric
        "galdre",      // timothy
        "dpsutton",    // dan
        "escherize",   // bryan
        "bgrabow"      // ben
      ]
    }
```

Modules:
- analyze
- graph
- sync
- enterprise/dependencies
2026-03-03 09:45:28 -06:00
Rodrigo López Dato
b2c736e4ca Missing space + log4j capitalization (#70271)
* Missing space + log4j capitalization

* Don't make changes in autogenerated MD files
2026-03-03 11:56:20 -03:00
Dan Stone
4a3e155ac9 Reenable bigquery incremental test (#70252)
Was toggled off individually due to issues with write consistency:
https://github.com/metabase/metabase/pull/69753
2026-03-03 14:44:16 +00:00
Braden Shepherdson
0f687a4a6b [MBQL lib] Prefer calling exported versions of several lib.util fns (#70269)
Fixes QUE2-352.

- `lib.util/strip-id` is newly exported with the more self-documenting
  name `lib/display-name-without-id`.
- `lib.util/clause?` and `clause-of-type?` were already exported
- `lib.util/source-card-id` (and `source-table-id`) are exported as
  `lib/primary-source-card-id` (and likewise for tables).

This isn't all the escaped usages of `lib.util` functions, but other PRs
will handle those.
2026-03-03 09:25:08 -05:00
Jakub Chodorowicz
5274ca8dcb Remove obsolete LeafletHeatMap and leaflet.heat (#70301) 2026-03-03 15:18:29 +01:00
github-automation-metabase
e0123c6246 Auto-update documentation for master (#70289)
Update generated docs (master)

Co-authored-by: github-actions <github-actions@github.com>
2026-03-03 09:03:48 -05:00
Anderson
4301a00c1b Add snowplow events when creating measures and segments (#70218)
* Add snowplow events when creating measures

* Track also from the table measures page

* Add tracking events when creating segments

* Fix e2e
2026-03-03 13:47:37 +00:00
Kamil Mielnik
7dc0929cc1 GDGT-1834 Visualization Typescript Conversions - lib/settings/ (#69893) 2026-03-03 19:39:50 +07:00
Nicolò Pretto
cf40c24b36 set fail-fast to false in sdk host/sample apps tests (#70260)
disable fail-fast on sdk tests
2026-03-03 09:20:37 +01:00
Uladzimir Havenchyk
5c4c8753d7 chore: convert viz tests and helpers to typescript (#70059)
* chore: convert viz tests to typescript

* convert more tests

* more tests

* more tests

* more tests

* use global helpers

* more tests

* more tests

* convert settings definition

* more files to typescript

* more files to typescript

* fixup

* fixup

* Update v59 sample Examples visualizations and dashboard. (#70075)

Adds Box Plot viz and a Scalar viz with conditional colors to the Example dashboard.
The resources/sample-content.edn was regenerated from the live instance content.

* Pin patched libraries to their patched version (#70143)

* address review

* add a guard

---------

Co-authored-by: Katya Voropaieva <110612633+KorowkaMu@users.noreply.github.com>
Co-authored-by: Nemanja Glumac <31325167+nemanjaglumac@users.noreply.github.com>
2026-03-03 11:14:29 +03:00
Anderson
d6540d2d62 Add snowplow events when creating a metric (#69990)
* Add snowplow events when creating a metric

* Fix tests in data-studio-metrics.cy.spec.ts

* Fix prettier
2026-03-03 01:09:31 -05:00
Nathan Voxland
d7f7d8285f Use the search cluster lock for both init indexing and re-indexing (#70272) 2026-03-02 18:07:55 -06:00
Jeff Bruemmer
cd68964a13 docs - fix summary formatting in users-roles-privileges.md (#70277)
Fix summary formatting in users-roles-privileges.md
2026-03-02 21:49:38 +00:00
Cam Saul
5e35a33837 Track whether column is :lib/from-model? (#70128)
* Track whether column is `:lib/from-model?`

* Additional fix 🔧

* Fix GH issue number

* (Try an evil hacc)

* Explain the HACC
2026-03-02 12:56:49 -08:00
Eric Normand
1734750c21 [Mutation Testing] Kill mutations in metabase.lib.field/fieldable-columns (#69321)
[Mutation Testing] Add tests for metabase.lib.field/fieldable-columns
2026-03-02 13:56:24 -06:00
Fraser
bb7604b53e Convert hoc-utils to ts (#70046) 2026-03-03 08:53:39 +13:00
Fraser
ea43ff2816 Convert Legend components to TypeScript (DEV-1502) (#69427)
* Convert Legend components to TypeScript (DEV-1502)

Convert Legend, LegendItem, LegendItemDot, and LegendLayout.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-03 08:53:24 +13:00
Alex Yarosh
e8c624b479 docs: update plans for writeable connection (#70264)
* 😑

* remove blockquotes

* Update docs/databases/users-roles-privileges.md

Co-authored-by: Jeff Bruemmer <jeff.bruemmer@gmail.com>

---------

Co-authored-by: Jeff Bruemmer <jeff.bruemmer@gmail.com>
2026-03-02 19:06:42 +00:00
metamben
97d10fee1c Preserve metadata edits for summary columns (#70235)
* Preserve metadata edits for summary columns

Closes QUE2-17
2026-03-02 21:50:22 +03:00
Stas Gavrylov
5c6250fe4d GDGT-1859: Fix enabling Advanced Transforms (#70183)
* GDGT-1859: Fix Python transforms not enabled after adding to the trial

* GDGT-1859: Add page refresh after enabling Advanced Transforms

* GDGT-1859: Update unit tests
2026-03-02 13:42:27 -05:00
Nicolò Pretto
21a620c6e8 fix stress tests for sdk component tests (#70253) 2026-03-02 17:30:51 +01:00
Braden Shepherdson
1e3b836a7b [MBQL lib] Improve the docstrings for lib.computed (#70207)
The high-level docs in this namespace were lacking, and I got asked for a tour of it, so I improved the docs as well.
2026-03-02 10:25:52 -05:00
Dan Stone
a6ae573321 Turn on snowflake/bq tests for transforms (#70199)
They seem to be working ok https://github.com/metabase/metabase/actions/runs/22575305288
2026-03-02 14:21:42 +00:00
Egor Grushin
14740891cd GDGT-1785 Load cards in batches in the Transform Inspector (#70129) 2026-03-02 11:54:30 +00:00
Uladzimir Havenchyk
908ca1a1d6 chore: split into components and hooks ClickMappings (#70097)
* chore: convert dashcard related redux components to typescript

* fixup

* address review

* another review iteration

* add a missing import

* chore: split into components and hooks ClickMappings

* fix imports

* delete old file

* make hook code human readable
2026-03-02 12:11:53 +03:00
Oleksandr Solovyov
94309cd070 Add toggle to enable/disable the Metabot (#70111) 2026-03-02 10:38:59 +02:00
1525 changed files with 77403 additions and 17872 deletions

View File

@@ -422,6 +422,8 @@
ring.util.codec codec
ring.util.response response
saml20-clj.core saml
metabase.transforms-base.util transforms-base.u
metabase.transforms.util transforms.u
toucan2.core t2}}}
:lint-as

View File

@@ -133,7 +133,7 @@
version}}
analyze
{:team "Querying"
{:team "Graphy"
:api #{metabase.analyze.core
metabase.analyze.query-results}
:uses #{config
@@ -152,6 +152,7 @@
metabase.api.docs
metabase.api.init
metabase.api.macros
metabase.api.macros.scope
metabase.api.open-api
metabase.api.response
metabase.api.routes.common
@@ -275,6 +276,7 @@
config
events
models
permissions
premium-features
request
settings
@@ -548,7 +550,7 @@
metabase.driver.common.parameters
metabase.driver.common.parameters.parse
metabase.driver.connection
metabase.driver.connection.workspaces
metabase.driver.connection.workspaces
metabase.driver.ddl.interface
metabase.driver.h2
metabase.driver.impl
@@ -694,7 +696,7 @@
util}}
graph
{:team "Querying"
{:team "Graphy"
:api #{metabase.graph.core}
:uses #{util}}
@@ -741,7 +743,6 @@
metabase.lib.init
metabase.lib.metadata
metabase.lib.metadata.protocols
metabase.lib.options
metabase.lib.schema
metabase.lib.schema.actions
metabase.lib.schema.aggregation
@@ -786,6 +787,16 @@
settings
util}}
lib-metric
{:team "UX West"
:api #{metabase.lib-metric.core
metabase.lib-metric.schema}
:uses #{lib
lib-be
settings
types
util}}
llm
{:team "Metabot"
:api #{metabase.llm.api
@@ -835,12 +846,29 @@
events
lib
lib-be
metrics
models
permissions
remote-sync
search
util}}
metrics
{:team "UX West"
:api #{metabase.metrics.api
metabase.metrics.core}
:uses #{api
collections
lib
lib-be
lib-metric
models
parameters
query-processor
request
server
util}}
model-persistence
{:team "Querying"
:api #{metabase.model-persistence.api
@@ -870,6 +898,7 @@
metabase.models.interface
metabase.models.resolution
metabase.models.serialization
metabase.models.transforms.transform
metabase.models.util.spec-update
metabase.models.visualization-settings}
:uses #{api
@@ -886,6 +915,7 @@
search
settings
transforms
transforms-base
util}
:friends #{transforms}}
@@ -1112,6 +1142,7 @@
events
lib
lib-be
metrics
models
parameters
permissions
@@ -1468,7 +1499,7 @@
util}}
sync
{:team "Querying"
{:team "Graphy"
:api #{metabase.sync.api
metabase.sync.core
metabase.sync.init
@@ -1574,7 +1605,6 @@
:api #{metabase.transforms.core
metabase.transforms.feature-gating
metabase.transforms.init
metabase.transforms.interface
metabase.transforms.schema
metabase.transforms.util}
:uses #{analytics
@@ -1584,21 +1614,36 @@
driver
events
lib
lib-be
models
premium-features
queries
query-processor
revisions
settings
sync
task
task-history
transforms-base
util}
:friends #{models
enterprise/transforms-python
enterprise/workspaces}}
transforms-base
{:team "Querying"
:api #{metabase.transforms-base.init
metabase.transforms-base.interface
metabase.transforms-base.util}
:uses #{driver
events
lib
lib-be
query-processor
sync
util}
:friends #{transforms
enterprise/transforms-python
enterprise/workspaces}}
transforms-inspector
{:team "Gadget"
:api #{metabase.transforms-inspector.core
@@ -1608,7 +1653,7 @@
lib-be
query-processor
sql-tools
transforms
transforms-base
util}}
transforms-rest
@@ -1625,6 +1670,7 @@
server
sql-tools
transforms
transforms-base
transforms-inspector
util}}
@@ -2110,7 +2156,7 @@
warehouses}}
enterprise/dependencies
{:team "Querying"
{:team "Graphy"
:api #{metabase-enterprise.dependencies.api
metabase-enterprise.dependencies.core
metabase-enterprise.dependencies.init}
@@ -2136,6 +2182,7 @@
settings
task
transforms
transforms-base
util}}
enterprise/email
@@ -2253,6 +2300,7 @@
system
task
transforms
transforms-base
users
util
warehouses
@@ -2476,6 +2524,7 @@
query-processor
settings
transforms
transforms-base
util}}
enterprise/upload-management
@@ -2501,6 +2550,7 @@
lib
lib-be
models
premium-features
queries
;; NOTE: we will remove this once we get "pure transforms" module.
query-processor
@@ -2509,8 +2559,14 @@
sql-tools
system
transforms
transforms-base
util
enterprise/transforms-python}}}
enterprise/transforms-python}}
enterprise/writable-connection
{:team "Querying"
:api #{}
:uses #{premium-features}}}
;; namespaces matching these patterns (with `re-find`) are excluded from the module linter. Since regex literals
;; aren't allowed in EDN just used the `(str <regex>)` version i.e. two slashes instead of one.

View File

@@ -55,7 +55,6 @@
help-link-custom-destination
instance-creation
is-hosted?
is-metabot-enabled
jdbc-data-warehouse-max-connection-pool-size
jdbc-data-warehouse-unreturned-connection-timeout-seconds
jwt-attribute-email

View File

@@ -7,9 +7,15 @@ outputs:
m2-cache-key:
description: "The cache key for the Maven cache."
value: ${{ steps.keys-factory.outputs.m2-cache-key }}
m2-restore-key:
description: "The fallback restore key prefix for the Maven cache."
value: ${{ steps.keys-factory.outputs.m2-restore-key }}
node-cache-key:
description: "The cache key for the Node.js cache."
value: ${{ steps.keys-factory.outputs.node-cache-key }}
node-restore-key:
description: "The fallback restore key prefix for the Node.js cache."
value: ${{ steps.keys-factory.outputs.node-restore-key }}
eslint-cache-key:
description: "The cache key for Eslint cache"
value: ${{ steps.keys-factory.outputs.eslint-cache-key }}
@@ -31,7 +37,9 @@ runs:
CACHE_SUFFIX="${{ runner.os }}-$WEEK_OF_YEAR"
echo "m2-cache-key=$M2_CACHE_PREFIX-$CACHE_SUFFIX" >> $GITHUB_OUTPUT
echo "m2-restore-key=$M2_CACHE_PREFIX-" >> $GITHUB_OUTPUT
echo "node-cache-key=$NODE_CACHE_PREFIX-$CACHE_SUFFIX" >> $GITHUB_OUTPUT
echo "node-restore-key=$NODE_CACHE_PREFIX-" >> $GITHUB_OUTPUT
echo "eslint-cache-key=$ESLINT_CACHE_PREFIX-$CACHE_SUFFIX" >> $GITHUB_OUTPUT
echo "cypress-cache-key=$CYPRESS_CACHE_PREFIX-$CACHE_SUFFIX" >> $GITHUB_OUTPUT
shell: bash

View File

@@ -42,3 +42,5 @@ runs:
~/.m2
~/.gitlibs
key: ${{ steps.get-cache-keys.outputs.m2-cache-key }}
restore-keys: |
${{ steps.get-cache-keys.outputs.m2-restore-key }}

View File

@@ -11,17 +11,10 @@ inputs:
runs:
using: "composite"
steps:
- name: Prepare Node.js
uses: actions/setup-node@v4
- name: Prepare Node + Bun environment
uses: ./.github/actions/prepare-node-bun
with:
node-version: ${{ inputs.node-version }} # this overrides, if present
node-version-file: ".nvmrc"
- name: Install bun
uses: oven-sh/setup-bun@v2
with:
bun-version: "1.3.7"
token: ${{ github.token }}
node-version: ${{ inputs.node-version }}
- name: Get cache keys
uses: ./.github/actions/get-cache-keys
@@ -34,6 +27,8 @@ runs:
~/.m2
~/.gitlibs
key: ${{ steps.get-cache-keys.outputs.m2-cache-key }}
restore-keys: |
${{ steps.get-cache-keys.outputs.m2-restore-key }}
- name: Get bun cache directory
id: bun-cache
@@ -51,6 +46,8 @@ runs:
${{ steps.bun-cache.outputs.dir }}
node_modules
key: ${{ steps.get-cache-keys.outputs.node-cache-key }}
restore-keys: |
${{ steps.get-cache-keys.outputs.node-restore-key }}
# postinstall lifecycle hook can be dangerous in CI so we only run it locally (see package.json)
# If a job wants to patch packages, it does so explicitly in the CI. This setting is opt-out.

View File

@@ -0,0 +1,20 @@
name: Prepare Node + Bun environment
description: "Set up Node.js and Bun for CI jobs"
inputs:
node-version:
description: "The version of Node.js to use, overriding .nvmrc"
required: false
runs:
using: "composite"
steps:
- name: Prepare Node.js
uses: actions/setup-node@v4
with:
node-version: ${{ inputs.node-version }}
node-version-file: ".nvmrc"
- name: Install bun
uses: oven-sh/setup-bun@v2
with:
bun-version: "1.3.7"
token: ${{ github.token }}

View File

@@ -35,9 +35,22 @@ runs:
with:
name: metabase-${{ inputs.edition }}-${{ github.event.pull_request.head.sha || github.sha }}-uberjar
path: temp/current-uberjar
- name: Extract embedding-sdk.js from current uberjar
- name: Extract embedding-sdk bundles from current uberjar
shell: bash
run: unzip -j temp/current-uberjar/target/uberjar/metabase.jar frontend_client/app/embedding-sdk.js -d temp/current-bundle
run: |
# Try new layout first (app/embedding-sdk/legacy/), fall back to old layout (app/embedding-sdk.js)
unzip -j temp/current-uberjar/target/uberjar/metabase.jar \
"frontend_client/app/embedding-sdk/legacy/embedding-sdk.js" \
-d temp/current-bundle 2>/dev/null || \
unzip -j temp/current-uberjar/target/uberjar/metabase.jar \
"frontend_client/app/embedding-sdk.js" \
-d temp/current-bundle
# Extract chunks directory if it exists (new layout only)
mkdir -p temp/current-chunks
unzip -j temp/current-uberjar/target/uberjar/metabase.jar \
"frontend_client/app/embedding-sdk/chunks/*" \
-d temp/current-chunks 2>/dev/null || true
- name: Checkout base ref
uses: actions/checkout@v4
with:
@@ -53,13 +66,21 @@ runs:
id: compare
shell: bash
run: |
# --- Legacy (monolithic) bundle comparison ---
current_size=$(wc -c < temp/current-bundle/embedding-sdk.js) || { echo "::error::Failed to read current bundle"; exit 1; }
base_ref_size=$(wc -c < temp/base-ref-src/resources/frontend_client/app/embedding-sdk.js) || { echo "::error::Failed to read base-ref bundle"; exit 1; }
# Base ref: try new layout first, fall back to old
if [ -f "temp/base-ref-src/resources/frontend_client/app/embedding-sdk/legacy/embedding-sdk.js" ]; then
base_ref_size=$(wc -c < "temp/base-ref-src/resources/frontend_client/app/embedding-sdk/legacy/embedding-sdk.js")
else
base_ref_size=$(wc -c < "temp/base-ref-src/resources/frontend_client/app/embedding-sdk.js")
fi
[ "$current_size" -gt 0 ] && [ "$base_ref_size" -gt 0 ] || { echo "::error::Bundle file is empty"; exit 1; }
diff=$((current_size - base_ref_size))
percent=$(( diff * 100 / base_ref_size ))
echo "=== Legacy (monolithic) bundle ==="
echo "Current size: $current_size bytes"
echo "Base ref size: $base_ref_size bytes"
echo "Difference: $diff bytes ($percent%)"
@@ -75,3 +96,15 @@ runs:
echo "status=$status" >> $GITHUB_OUTPUT
echo "size_change_percent=$percent" >> $GITHUB_OUTPUT
# --- Chunked bundle (informational) ---
if ls temp/current-chunks/*.js 1>/dev/null 2>&1; then
chunks_size=$(cat temp/current-chunks/*.js | wc -c)
echo ""
echo "=== Chunked bundle (bootstrap + chunks) ==="
echo "Total chunked size: $chunks_size bytes"
echo "chunks_size=$chunks_size" >> $GITHUB_OUTPUT
else
echo ""
echo "No chunked bundle found (expected on master)"
fi

View File

@@ -30,7 +30,7 @@ frontend_configs: &frontend_configs
- "**/tsconfig*.json"
- "package.json"
- "babel.config.json"
- ".eslintrc.js"
- "eslint.config.mjs"
- "postcss.config.js"
- "rspack.config.js"
- "rspack.main.config.js"

20
.github/team.json vendored
View File

@@ -4,14 +4,23 @@
"name": "Querying",
"label": ".Team/Querying",
"members": [
"ranquild",
"romeovs",
"bshepherdson",
"metamben",
"wzimrin",
"rileythomp",
"camsual"
]
},
{
"name": "Graphy",
"label": ".Team/Graphy",
"members": [
"ranquild",
"romeovs",
"ericnormand",
"galdre",
"rileythomp"
"dpsutton",
"escherize",
"bgrabow"
]
},
{
@@ -36,9 +45,6 @@
"name": "DevEx",
"label": ".Team/DevEx",
"members": [
"camsaul",
"dpsutton",
"escherize",
"fraserdrops",
"nemanjaglumac"
]

View File

@@ -11,8 +11,9 @@ name: Backend-Cloverage
on:
workflow_dispatch:
schedule:
- cron: '0 10 * * 1-5' # every weekday at 5am US eastern time
# re-enable once we figure out the correctness of the reports in DEV-1104
# schedule:
# - cron: '0 10 * * 1-5' # every weekday at 5am US eastern time
jobs:
setup-oss:

View File

@@ -36,6 +36,18 @@ jobs:
- run: clojure -X:dev:ee:ee-dev:drivers:drivers-dev:test:eastwood
name: Run Eastwood linter
be-linter-eastwood-test:
if: ${{ !inputs.skip }}
runs-on: ubuntu-22.04
timeout-minutes: 20
name: Eastwood (test)
steps:
- uses: actions/checkout@v4
- name: Prepare back-end environment
uses: ./.github/actions/prepare-backend
- run: clojure -X:dev:ee:ee-dev:drivers:drivers-dev:test:eastwood/test
name: Run Eastwood linter on tests
be-tests:
if: ${{ !inputs.skip }}
runs-on: ubuntu-22.04
@@ -184,6 +196,7 @@ jobs:
be-tests-result:
needs:
- be-linter-eastwood
- be-linter-eastwood-test
- be-linter-clj-kondo
- be-cljfmt
- be-check

View File

@@ -0,0 +1,79 @@
name: Disabled Drivers Slack Notification
on:
workflow_dispatch:
schedule:
- cron: "0 9 * * 1" # every Monday at 9:00 UTC
jobs:
notify-disabled-drivers:
runs-on: ubuntu-latest
timeout-minutes: 5
steps:
- uses: actions/setup-node@v4
with:
node-version: lts/Jod
- name: Install Slack SDK
run: npm install @slack/web-api
- name: Check disabled drivers and notify Slack
uses: actions/github-script@v7
env:
SLACK_BOT_TOKEN: ${{ secrets.SLACK_BOT_TOKEN }}
with:
script: |
const { WebClient } = require('@slack/web-api');
// Fetch the config
const response = await fetch('https://raw.githubusercontent.com/metabase/ci-test-config/refs/heads/master/ci-test-config.json');
const config = await response.json();
const drivers = config.ignored?.drivers || [];
const lastUpdated = config.metadata?.last_updated || 'unknown';
const reason = config.metadata?.reason || 'No reason provided';
if (drivers.length === 0) {
console.log('No drivers are currently disabled. Skipping Slack notification.');
return;
}
if (!process.env.SLACK_BOT_TOKEN) {
throw new Error('SLACK_BOT_TOKEN is required');
}
const slack = new WebClient(process.env.SLACK_BOT_TOKEN);
await slack.chat.postMessage({
channel: 'engineering-ci',
text: 'CI Disabled Drivers Report',
blocks: [
{
type: 'section',
text: {
type: 'mrkdwn',
text: `:no_entry: *CI Disabled Drivers*\n${drivers.map(d => `\`${d}\``).join(' ')}`
},
accessory: {
type: 'button',
text: {
type: 'plain_text',
text: 'View Config',
emoji: true
},
url: 'https://github.com/metabase/ci-test-config/blob/master/ci-test-config.json'
}
},
{
type: 'context',
elements: [
{
type: 'mrkdwn',
text: `${reason} · :clock1: *${lastUpdated}*`
}
]
}
]
});
console.log('Slack notification sent successfully');

View File

@@ -8,7 +8,7 @@ on:
target_branch:
description: "Target branch for documentation update"
required: false
default: "release-x.58.x"
default: "release-x.59.x"
type: string
jobs:
@@ -16,6 +16,6 @@ jobs:
name: Call documentation update for release branch
uses: ./.github/workflows/docs-generate-base.yml
with:
target_branch: ${{ inputs.target_branch || 'release-x.58.x' }}
target_branch: ${{ inputs.target_branch || 'release-x.59.x' }}
secrets:
automation_token: ${{ secrets.METABASE_AUTOMATION_USER_TOKEN }}

View File

@@ -151,11 +151,10 @@ jobs:
:only-tags [:mb/driver-tests]
:exclude-tags [:mb/transforms-python-test]
:fail-fast? true
# DS 2025-09-26 temporarily disabled while we diagnose flakes
# - name: Transforms Python Tests
# test-args: >-
# :only-tags [:mb/transforms-python-test]
# needs-python-runner: true
- name: Transforms Python Tests
test-args: >-
:only-tags [:mb/transforms-python-test]
needs-python-runner: true
env:
CI: 'true'
DRIVERS: bigquery-cloud-sdk
@@ -1278,12 +1277,10 @@ jobs:
:only-tags [:mb/driver-tests]
:exclude-tags [:mb/transforms-python-test]
:fail-fast? true
# DS 2025-09-26 temporarily disabled while we diagnose flakes
# - name: Transforms Python Tests
# test-args: >-
# :only-tags [:mb/transforms-python-test]
# needs-python-runner: true
- name: Transforms Python Tests
test-args: >-
:only-tags [:mb/transforms-python-test]
needs-python-runner: true
env:
CI: 'true'
DRIVERS: snowflake

View File

@@ -88,6 +88,7 @@ jobs:
e2e-sample-apps-tests:
needs: [get-sample-apps-data]
strategy:
fail-fast: false
matrix:
test_suite: ${{ fromJSON(needs.get-sample-apps-data.outputs.matrix) }}
environment: ["production", "development"]
@@ -194,6 +195,7 @@ jobs:
e2e-shoppy-tests:
needs: [get-sample-apps-data]
strategy:
fail-fast: false
matrix:
environment: ["production", "development"]
if: |
@@ -342,6 +344,7 @@ jobs:
# For more details see `Embedding SDK integration tests with Host Apps` in `enterprise/frontend/src/embedding-sdk-package/dev.md`
e2e-host-apps-tests:
strategy:
fail-fast: false
matrix:
test_suite:
[

View File

@@ -156,11 +156,18 @@ jobs:
- name: Send notification to Slack via Zapier
if: success() && steps.compare.outputs.status == 'increased'
shell: bash
env:
ZAPIER_WEBHOOK_URL: ${{ secrets.EMBEDDING_ZAPIER_WEBHOOK_URL }}
SIZE_CHANGE_PERCENT: ${{ steps.compare.outputs.size_change_percent }}
BUNDLE_SIZE_THRESHOLD_PERCENT: ${{ env.BUNDLE_SIZE_THRESHOLD_PERCENT }}
PR_NUMBER: ${{ github.event.pull_request.number }}
PR_TITLE: ${{ github.event.pull_request.title }}
PR_URL: ${{ github.event.pull_request.html_url }}
run: |
curl -s -X POST "${{ secrets.EMBEDDING_ZAPIER_WEBHOOK_URL }}" \
-d '⚠️ Embedding SDK bundle size increased by ${{ steps.compare.outputs.size_change_percent }}% (threshold: ${{ env.BUNDLE_SIZE_THRESHOLD_PERCENT }}%)
curl -s -X POST "$ZAPIER_WEBHOOK_URL" \
-d "⚠️ Embedding SDK bundle size increased by ${SIZE_CHANGE_PERCENT}% (threshold: ${BUNDLE_SIZE_THRESHOLD_PERCENT}%)
PR #${{ github.event.pull_request.number }} ${{ github.event.pull_request.title }} (${{ github.event.pull_request.html_url }})'
PR #${PR_NUMBER} ${PR_TITLE} (${PR_URL})"
- name: Comment on PR if bundle size has decreased
uses: ./.github/actions/notify-pull-request

View File

@@ -22,10 +22,8 @@ jobs:
token: ${{ secrets.METABASE_AUTOMATION_USER_TOKEN }}
# fetch full git history to allow fetching the latest base branch commit and comparing changes
fetch-depth: 0
- name: Setup Node.js 22
uses: actions/setup-node@v4
with:
node-version: 22.x
- name: Prepare Node + Bun environment
uses: ./.github/actions/prepare-node-bun
- name: Prepare back-end environment
uses: ./.github/actions/prepare-backend
- name: Generate version.properties

100
.github/workflows/repro-bot.yml vendored Normal file
View File

@@ -0,0 +1,100 @@
name: "Repro Bot"
on:
issues:
types:
- labeled
workflow_dispatch:
inputs:
issue_number:
description: "Issue number to reproduce"
required: true
type: string
jobs:
repro-bot:
runs-on: ubuntu-latest
timeout-minutes: 60
permissions:
contents: read
issues: read
id-token: write
if: |
(github.event_name == 'push') ||
(github.event_name == 'issues' && github.event.label.name == 'repro-bot' && github.event.issue.state == 'open') ||
(github.event_name == 'workflow_dispatch')
steps:
- name: Get issue number
id: issue
run: |
if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then
echo "number=${{ github.event.inputs.issue_number }}" >> $GITHUB_OUTPUT
elif [ "${{ github.event_name }}" = "push" ]; then
echo "number=70292" >> $GITHUB_OUTPUT
else
echo "number=${{ github.event.issue.number }}" >> $GITHUB_OUTPUT
fi
- name: Checkout repro-bot
uses: actions/checkout@v4
with:
repository: metabase/repro-bot
ref: ci-support
token: ${{ secrets.METABASE_AUTOMATION_USER_TOKEN }}
- name: Pre-clone metabase bare git repo
run: git clone --bare https://github.com/metabase/metabase.git git/metabase
- name: Set up Java
uses: actions/setup-java@v4
with:
distribution: 'temurin'
java-version: '21'
- name: Set up Python (uv)
uses: astral-sh/setup-uv@v4
- name: Install playwright-cli
run: |
npm install -g @playwright/cli@latest
playwright-cli install --skills
- name: Generate GitHub App Token
uses: actions/create-github-app-token@v1
id: claude-app-token
with:
app-id: ${{ secrets.METABASE_BOT_APP_ID }}
private-key: ${{ secrets.METABASE_BOT_APP_PRIVATE_KEY }}
- name: Run repro-bot with Claude Code
uses: anthropics/claude-code-action@v1
env:
MB_PREMIUM_EMBEDDING_TOKEN: ${{ secrets.PR_ENV_MB_PREMIUM_EMBEDDING_TOKEN }}
LINEAR_API_KEY: ${{ secrets.LINEAR_API_KEY }}
GITHUB_ACTIONS_RUN_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}
with:
anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }}
github_token: ${{ steps.claude-app-token.outputs.token }}
plugins: |
@anthropic/plugin-productivity-linear
prompt: |
Read and follow the instructions in .claude/commands/repro.md to investigate this GitHub issue:
https://github.com/${{ github.repository }}/issues/${{ steps.issue.outputs.number }}
## CI Environment Notes
- The bare git repo has been pre-cloned at git/metabase. The master worktree still needs setup via setup_master_worktree().
- The GITHUB_ACTIONS_RUN_URL environment variable is set. If any phase fails catastrophically, follow the CI error handling in repro.md to post the error to Linear with the action run URL.
- Docker is available for appdb (Postgres/MySQL/MariaDB) if needed.
- Java 21 and Python/uv are pre-installed.
claude_args: |
--allowedTools "Bash(playwright-cli*),Bash(gh *),Bash(jq*),Bash(find*),Bash(ls*),Bash(grep*),Bash(cat*),Bash(base64*),Bash(git*),Bash(npx*),Bash(docker*),Bash(kill*),Bash(curl*),Write,Read,Glob,Grep,Edit,MultiEdit,WebFetch,mcp__metabase_repro__*,mcp__plugin_productivity_linear__*"
--disallowedTools "Bash(git push*),Bash(rm -rf /*)"
- name: Upload SUGGESTIONS.md artifact
uses: actions/upload-artifact@v4
if: always()
with:
name: repro-suggestions
path: repro/*/SUGGESTIONS.md
if-no-files-found: ignore

View File

@@ -81,7 +81,7 @@ jobs:
secrets: inherit
with:
skip: ${{ needs.files-changed.outputs.frontend_all != 'true' }}
skip-lint: ${{ needs.files-changed.outputs.frontend_all != 'true' && needs.files-changed.outputs.e2e_specs != 'true' }}
skip-lint: ${{ needs.files-changed.outputs.frontend_all != 'true' && needs.files-changed.outputs.e2e_all != 'true' }}
e2e-tests:
needs: [files-changed, uberjar]

16
.gitignore vendored
View File

@@ -65,6 +65,7 @@ cypress.env.json
/resources/frontend_client/app/embed.js
/resources/frontend_client/app/embedding-sdk.js
/resources/frontend_client/app/embedding-sdk.js.map
/resources/frontend_client/app/embedding-sdk/
/resources/frontend_client/tmp-*/
/resources/frontend_client/embed.html
/resources/frontend_client/embed-sdk.html
@@ -75,6 +76,7 @@ cypress.env.json
/resources/instance_analytics.zip
/resources/license-backend-third-party.txt
/resources/license-frontend-third-party.txt
/resources/metabase/config/modules.edn
/resources/namespaces.edn
/resources/sample-dataset.db.trace.db
/resources/version.properties
@@ -123,13 +125,13 @@ modules/drivers/*/.lsp/*
**/.clj-kondo/.cache
# clj-kondo: ignore all except our defined config
.clj-kondo/*
!.clj-kondo/README.md
!.clj-kondo/config.edn
!.clj-kondo/config/
!.clj-kondo/src/
!.clj-kondo/test/
!.clj-kondo/macros/
**/.clj-kondo/*
!**/.clj-kondo/README.md
!**/.clj-kondo/config.edn
!**/.clj-kondo/config/
!**/.clj-kondo/src/
!**/.clj-kondo/test/
!**/.clj-kondo/macros/
# Editor- or environment-specific local files
*.code-workspace

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 201 KiB

After

Width:  |  Height:  |  Size: 204 KiB

View File

@@ -10,20 +10,24 @@
## Get started
The easiest way to get started with Metabase is to sign up for a free trial of [Metabase Cloud](https://store.metabase.com/checkout). You get support, backups, upgrades, an SMTP server, SSL certificate, SoC2 Type 2 security auditing, and more (plus your money goes toward improving Metabase). Check out our quick overview of [cloud vs self-hosting](https://www.metabase.com/docs/latest/cloud/cloud-vs-self-hosting). If you need to, you can always switch to [self-hosting](https://www.metabase.com/docs/latest/installation-and-operation/installing-metabase) Metabase at any time (or vice versa).
The easiest way to get started with Metabase is to sign up for a free trial of [Metabase Cloud](https://store.metabase.com/checkout).
You get expert support, backups, upgrades, an SMTP server, SSL certificate, SoC2 Type 2 security auditing, and more (plus your money goes toward improving a major open-source project). Check out our quick overview of [cloud vs self-hosting](https://www.metabase.com/docs/latest/cloud/cloud-vs-self-hosting). If you need to, you can always switch to [self-hosting](https://www.metabase.com/docs/latest/installation-and-operation/installing-metabase) Metabase at any time (or vice versa).
## Key Features
- [Set up in five minutes](https://www.metabase.com/docs/latest/configuring-metabase/setting-up-metabase) (we're not kidding).
- [Set up in five minutes](https://www.metabase.com/docs/latest/configuring-metabase/setting-up-metabase) (we're not kidding), or have us [host Metabase for you](https://www.metabase.com/cloud/) so you don't even need to think about it.
- Let anyone on your team [ask questions](https://www.metabase.com/docs/latest/questions/introduction) without knowing SQL.
- Use the [SQL editor](https://www.metabase.com/docs/latest/questions/native-editor/writing-sql) for more complex queries.
- Build handsome, interactive [dashboards](https://www.metabase.com/docs/latest/dashboards/introduction) with filters, auto-refresh, fullscreen, and custom click behavior.
- Create [models](https://www.metabase.com/learn/metabase-basics/getting-started/models) that clean up, annotate, and/or combine raw tables.
- Define canonical [segments and metrics](https://www.metabase.com/docs/latest/data-modeling/metrics) for your team to use.
- Send data to Slack or email on a schedule with [dashboard subscriptions](https://www.metabase.com/docs/latest/dashboards/subscriptions).
- Set up [alerts](https://www.metabase.com/docs/latest/questions/alerts) to have Metabase notify you when your data changes.
- [Embed charts and dashboards](https://www.metabase.com/docs/latest/embedding/introduction) in your app, or even [your entire Metabase](https://www.metabase.com/docs/latest/embedding/interactive-embedding).
- Build with the [Embedded Analytics SDK for React](https://www.metabase.com/docs/latest/embedding/sdk/introduction) to embed standalone components with custom styling that matches your app's design.
- Ask AI: [Metabot](https://www.metabase.com/docs/latest/ai/metabot) gives you answers you can trust, helps you write queries, and more. Or build your own [AI agent](https://www.metabase.com/docs/latest/ai/agent-api) to query your data.
- Build handsome, interactive [dashboards](https://www.metabase.com/docs/latest/dashboards/introduction) with filters, auto-refresh, fullscreen, custom click behavior, and more.
- Use [documents](https://www.metabase.com/docs/latest/documents/introduction) for long-form data analysis, and invite people to comment.
- [Transform](https://www.metabase.com/docs/latest/data-studio/transforms/transforms-overview) raw data into analytics-ready tables, track down broken dependencies, and define canonical metrics in Metabase's [Data Studio](https://www.metabase.com/docs/latest/data-studio/overview).
- Set up [alerts on your data](https://www.metabase.com/docs/latest/questions/alerts), or schedule [dashboard subscriptions](https://www.metabase.com/docs/latest/dashboards/subscriptions) to email, Slack, or even a webhook.
- Curate content in a [Library](https://www.metabase.com/docs/latest/data-studio/library), and [version your work with Git](https://www.metabase.com/docs/latest/installation-and-operation/remote-sync).
- [Embed Metabase in your app](https://www.metabase.com/docs/latest/embedding/introduction), with components for charts, dashboards, data browser, AI chat, and more. You can even put [an entire Metabase](https://www.metabase.com/docs/latest/embedding/interactive-embedding) in your app.
- Set granular [permissions](https://www.metabase.com/docs/latest/permissions/introduction) that work for both internal teams and embedded analytics, whether you co-locate your customer data, or give each customer their own database.
- Dark mode, content translations, and way more stuff than we can list here.
Take a [tour of Metabase](https://www.metabase.com/learn/metabase-basics/overview/tour-of-metabase).
@@ -36,57 +40,22 @@ Take a [tour of Metabase](https://www.metabase.com/learn/metabase-basics/overvie
Metabase can be run just about anywhere. Check out our [Installation Guides](https://www.metabase.com/docs/latest/installation-and-operation/installing-metabase).
## Documentation
The [Metabase handbook](https://www.metabase.com/docs/latest/).
## Contributing
## Quick Setup: Dev environment
To contribute to Metabase, see our [Developer docs](./docs/developers-guide/start.md).
In order to spin up a development environment, you need to start the front end and the backend as follows:
## Extending Metabase
### Frontend quick setup
The following command will install the JavaScript dependencies:
```bash
bun install
```
To build and run without watching changes:
```bash
bun run build
```
To build and run with hot-reload:
```bash
bun run build-hot
```
### Backend quick setup
To run the backend, you'll need to build the drivers first, and then start the backend:
```bash
./bin/build-drivers.sh
clojure -M:run
```
For a more detailed setup of a dev environment for Metabase, check out our [Developers Guide](./docs/developers-guide/start.md).
Hit our API to integrate analytics. Check out our guide, [Working with the Metabase API](https://www.metabase.com/learn/metabase-basics/administration/administration-and-operation/metabase-api).
## Internationalization
We want Metabase to be available in as many languages as possible. See which translations are available and help contribute to internationalization using our project over at [Crowdin](https://crowdin.com/project/metabase-i18n). You can also check out our [policies on translations](https://www.metabase.com/docs/latest/administration-guide/localization.html).
## Extending Metabase
Hit our Query API from JavaScript to integrate analytics. Metabase enables your application to:
- Build moderation interfaces.
- Export subsets of your users to third party marketing automation software.
- Provide a custom customer lookup application for the people in your company.
Check out our guide, [Working with the Metabase API](https://www.metabase.com/learn/metabase-basics/administration/administration-and-operation/metabase-api).
## Security Disclosure
See [SECURITY.md](./SECURITY.md) for details.

10
bb.edn
View File

@@ -247,6 +247,14 @@
:requires [[mage.util :as u]]
:task (task! (u/print-tasks parsed))}
generate-cursive-resolve-as
{:doc "Generate XML configuration for Cursive's symbol resolution based on the current clj-kondo lint-as configuration."
:examples [["./bin/mage generate-cursive-resolve-as" "Generate resolve-as XML configuration"]
["./bin/mage generate-cursive-resolve-as > /Users/bgrabow/Library/Application\\ Support/JetBrains/IntelliJIdea2025.3/options/ClojureResolveSettings.xml"
"Generate resolve-as XML configuration and install it in your global editor configuration"]]
:requires [[mage.cursive-resolve-as :as cursive-resolve-as]]
:task (task! (cursive-resolve-as/do-it))}
analytics:setup
{:doc "Set up usage analytics development mode"
:examples [["./bin/mage analytics:setup" "Enable usage analytics dev mode and import content"]]
@@ -302,7 +310,7 @@
"If you see 'gh: command not found' or auth errors, run: gh auth login"))
:requires [[mage.ci-report :as ci-report]]
:task (task! (ci-report/generate-report! parsed))}
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Private Tasks:
;; These tasks are more for internal tooling, e.g. for use from git hooks etc.

135
bun.lock
View File

@@ -112,11 +112,10 @@
"js-cookie": "^2.1.2",
"js-yaml": "^4.1.1",
"json5": "2.2.2",
"jspdf": "^4.1.0",
"jspdf": "^4.2.0",
"kbar": "0.1.0-beta.45",
"leaflet": "^1.2.0",
"leaflet-draw": "^0.4.9",
"leaflet.heat": "^0.2.0",
"lodash.debounce": "^4.0.8",
"lodash.orderby": "^4.6.0",
"merge-refs": "^1.3.0",
@@ -153,7 +152,7 @@
"redux-actions": "^2.0.1",
"redux-auth-wrapper": "2.1.0",
"redux-undo": "^1.1.0",
"rehype-external-links": "^2.0.1",
"rehype-external-links": "^3.0.0",
"remark-gfm": "^4.0.0",
"reselect": "^5.1.0",
"resize-observer-polyfill": "^1.5.1",
@@ -370,7 +369,7 @@
"react-refresh": "^0.14.2",
"reg-cli": "^0.17.7",
"semver": "^7.6.3",
"shadow-cljs": "^2.28.20",
"shadow-cljs": "^3.3.5",
"source-map-loader": "^4.0.1",
"storybook": "^8.6.15",
"storybook-addon-pseudo-states": "^4.0.2",
@@ -1929,7 +1928,7 @@
"@uiw/react-codemirror": ["@uiw/react-codemirror@4.23.8", "", { "dependencies": { "@babel/runtime": "^7.18.6", "@codemirror/commands": "^6.1.0", "@codemirror/state": "^6.1.1", "@codemirror/theme-one-dark": "^6.0.0", "@uiw/codemirror-extensions-basic-setup": "4.23.8", "codemirror": "^6.0.0" } }, "sha512-/NA5Pj4MmXkLSlmlUm4yfEmRLntrNq5TkQKBSINn7TukXQ4fc+C6Bk0U60Qa4rkvCSgwzZdQ2exyP0t0+2GtqA=="],
"@ungap/structured-clone": ["@ungap/structured-clone@1.2.0", "", {}, "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ=="],
"@ungap/structured-clone": ["@ungap/structured-clone@1.3.0", "", {}, "sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g=="],
"@unrs/resolver-binding-android-arm-eabi": ["@unrs/resolver-binding-android-arm-eabi@1.11.1", "", { "os": "android", "cpu": "arm" }, "sha512-ppLRUgHVaGRWUx0R0Ut06Mjo9gBaBkg3v/8AxusGLhsIotbBLuRk51rAzqLC8gq6NyyAojEXglNjzf6R948DNw=="],
@@ -3215,6 +3214,8 @@
"hast-util-from-parse5": ["hast-util-from-parse5@8.0.1", "", { "dependencies": { "@types/hast": "^3.0.0", "@types/unist": "^3.0.0", "devlop": "^1.0.0", "hastscript": "^8.0.0", "property-information": "^6.0.0", "vfile": "^6.0.0", "vfile-location": "^5.0.0", "web-namespaces": "^2.0.0" } }, "sha512-Er/Iixbc7IEa7r/XLtuG52zoqn/b3Xng/w6aZQ0xGVxzhw5xUFxcRqdPzP6yFi/4HBYRaifaI5fQ1RH8n0ZeOQ=="],
"hast-util-is-element": ["hast-util-is-element@3.0.0", "", { "dependencies": { "@types/hast": "^3.0.0" } }, "sha512-Val9mnv2IWpLbNPqc/pUem+a7Ipj2aHacCwgNfTiK0vJKl0LF+4Ba4+v1oPHFpf3bLYmreq0/l3Gud9S5OH42g=="],
"hast-util-parse-selector": ["hast-util-parse-selector@4.0.0", "", { "dependencies": { "@types/hast": "^3.0.0" } }, "sha512-wkQCkSYoOGCRKERFWcxMVMOcYE2K1AaNLU8DXS9arxnLOUEWbOXKXiJUNzEpqZ3JOKpnha3jkFrumEjVliDe7A=="],
"hast-util-raw": ["hast-util-raw@9.0.2", "", { "dependencies": { "@types/hast": "^3.0.0", "@types/unist": "^3.0.0", "@ungap/structured-clone": "^1.0.0", "hast-util-from-parse5": "^8.0.0", "hast-util-to-parse5": "^8.0.0", "html-void-elements": "^3.0.0", "mdast-util-to-hast": "^13.0.0", "parse5": "^7.0.0", "unist-util-position": "^5.0.0", "unist-util-visit": "^5.0.0", "vfile": "^6.0.0", "web-namespaces": "^2.0.0", "zwitch": "^2.0.0" } }, "sha512-PldBy71wO9Uq1kyaMch9AHIghtQvIwxBUkv823pKmkTM3oV1JxtsTNYdevMxvUHqcnOAuO65JKU2+0NOxc2ksA=="],
@@ -3497,7 +3498,7 @@
"isarray": ["isarray@2.0.5", "", {}, "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw=="],
"isexe": ["isexe@2.0.0", "", {}, "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw=="],
"isexe": ["isexe@3.1.5", "", {}, "sha512-6B3tLtFqtQS4ekarvLVMZ+X+VlvQekbe4taUkf/rhVO3d/h0M2rfARm/pXLcPEsjjMsFgrFgSrhQIxcSVrBz8w=="],
"isobject": ["isobject@3.0.1", "", {}, "sha1-TkMekrEalzFjaqH5yNHMvP2reN8="],
@@ -3635,7 +3636,7 @@
"jsonwebtoken": ["jsonwebtoken@9.0.3", "", { "dependencies": { "jws": "^4.0.1", "lodash.includes": "^4.3.0", "lodash.isboolean": "^3.0.3", "lodash.isinteger": "^4.0.4", "lodash.isnumber": "^3.0.3", "lodash.isplainobject": "^4.0.6", "lodash.isstring": "^4.0.1", "lodash.once": "^4.0.0", "ms": "^2.1.1", "semver": "^7.5.4" } }, "sha512-MT/xP0CrubFRNLNKvxJ2BYfy53Zkm++5bX9dtuPbqAeQpTVe0MQTFhao8+Cp//EmJp244xt6Drw/GVEGCUj40g=="],
"jspdf": ["jspdf@4.1.0", "", { "dependencies": { "@babel/runtime": "^7.28.4", "fast-png": "^6.2.0", "fflate": "^0.8.1" }, "optionalDependencies": { "canvg": "^3.0.11", "core-js": "^3.6.0", "dompurify": "^3.3.1", "html2canvas": "^1.0.0-rc.5" } }, "sha512-xd1d/XRkwqnsq6FP3zH1Q+Ejqn2ULIJeDZ+FTKpaabVpZREjsJKRJwuokTNgdqOU+fl55KgbvgZ1pRTSWCP2kQ=="],
"jspdf": ["jspdf@4.2.0", "", { "dependencies": { "@babel/runtime": "^7.28.6", "fast-png": "^6.2.0", "fflate": "^0.8.1" }, "optionalDependencies": { "canvg": "^3.0.11", "core-js": "^3.6.0", "dompurify": "^3.3.1", "html2canvas": "^1.0.0-rc.5" } }, "sha512-hR/hnRevAXXlrjeqU5oahOE+Ln9ORJUB5brLHHqH67A+RBQZuFr5GkbI9XQI8OUFSEezKegsi45QRpc4bGj75Q=="],
"jsprim": ["jsprim@2.0.2", "", { "dependencies": { "assert-plus": "1.0.0", "extsprintf": "1.3.0", "json-schema": "0.4.0", "verror": "1.10.0" } }, "sha512-gqXddjPqQ6G40VdnI6T6yObEC+pDNvyP95wdQhkWkg7crHH3km5qP1FsOXEkzEQwnz6gz5qGTn1c2Y52wP3OyQ=="],
@@ -3669,8 +3670,6 @@
"leaflet-draw": ["leaflet-draw@0.4.14", "", {}, "sha512-O99KSPjyHNMDE+uD/fpdPydvQfTE8QruaG7ylEEtKCIaSSb60mCWoDdGUqGEHU9PGPu2JxbEfkGTXY9eYv7aEw=="],
"leaflet.heat": ["leaflet.heat@0.2.0", "", {}, "sha1-EJ2M9Ybwre5B8Fr/Ax4np3/swik="],
"less": ["less@4.2.2", "", { "dependencies": { "copy-anything": "^2.0.1", "parse-node-version": "^1.0.1", "tslib": "^2.3.0" }, "optionalDependencies": { "errno": "^0.1.1", "graceful-fs": "^4.1.2", "image-size": "~0.5.0", "make-dir": "^2.1.0", "mime": "^1.4.1", "needle": "^3.1.0", "source-map": "~0.6.0" }, "bin": { "lessc": "bin/lessc" } }, "sha512-tkuLHQlvWUTeQ3doAqnHbNn8T6WX1KA8yvbKG9x4VtKtIjHsVKQZCH11zRgAfbDAXC2UNIg/K9BYAAcEzUIrNg=="],
"leven": ["leven@3.1.0", "", {}, "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A=="],
@@ -4023,8 +4022,6 @@
"node-int64": ["node-int64@0.4.0", "", {}, "sha1-h6kGXNs1XTGC2PlM4RGIuCXGijs="],
"node-libs-browser": ["node-libs-browser@2.2.1", "", { "dependencies": { "assert": "^1.1.1", "browserify-zlib": "^0.2.0", "buffer": "^4.3.0", "console-browserify": "^1.1.0", "constants-browserify": "^1.0.0", "crypto-browserify": "^3.11.0", "domain-browser": "^1.1.1", "events": "^3.0.0", "https-browserify": "^1.0.0", "os-browserify": "^0.3.0", "path-browserify": "0.0.1", "process": "^0.11.10", "punycode": "^1.2.4", "querystring-es3": "^0.2.0", "readable-stream": "^2.3.3", "stream-browserify": "^2.0.1", "stream-http": "^2.7.2", "string_decoder": "^1.0.0", "timers-browserify": "^2.0.4", "tty-browserify": "0.0.0", "url": "^0.11.0", "util": "^0.11.0", "vm-browserify": "^1.0.1" } }, "sha512-h/zcD8H9kaDZ9ALUWwlBUDo6TKF8a7qBSCSEGfjTVIYeqsioSKaAX+BN7NgiMGp6iSIXZ3PxgCu8KS3b71YK5Q=="],
"node-notifier": ["node-notifier@9.0.1", "", { "dependencies": { "growly": "^1.3.0", "is-wsl": "^2.2.0", "semver": "^7.3.2", "shellwords": "^0.1.1", "uuid": "^8.3.0", "which": "^2.0.2" } }, "sha512-fPNFIp2hF/Dq7qLDzSg4vZ0J4e9v60gJR+Qx7RbjbWqzPDdEqeVpEx5CFeDAELIl+A/woaaNn1fQ5nEVerMxJg=="],
"node-polyfill-webpack-plugin": ["node-polyfill-webpack-plugin@4.0.0", "", { "dependencies": { "assert": "^2.1.0", "browserify-zlib": "^0.2.0", "buffer": "^6.0.3", "console-browserify": "^1.2.0", "constants-browserify": "^1.0.0", "crypto-browserify": "^3.12.0", "domain-browser": "^5.7.0", "events": "^3.3.0", "https-browserify": "^1.0.0", "os-browserify": "^0.3.0", "path-browserify": "^1.0.1", "process": "^0.11.10", "punycode": "^2.3.1", "querystring-es3": "^0.2.1", "readable-stream": "^4.5.2", "stream-browserify": "^3.0.0", "stream-http": "^3.2.0", "string_decoder": "^1.3.0", "timers-browserify": "^2.0.12", "tty-browserify": "^0.0.1", "type-fest": "^4.18.2", "url": "^0.11.3", "util": "^0.12.5", "vm-browserify": "^1.1.2" } }, "sha512-WLk77vLpbcpmTekRj6s6vYxk30XoyaY5MDZ4+9g8OaKoG3Ij+TjOqhpQjVUlfDZBPBgpNATDltaQkzuXSnnkwg=="],
@@ -4621,7 +4618,7 @@
"regjsparser": ["regjsparser@0.13.0", "", { "dependencies": { "jsesc": "~3.1.0" }, "bin": { "regjsparser": "bin/parser" } }, "sha512-NZQZdC5wOE/H3UT28fVGL+ikOZcEzfMGk/c3iN9UGxzWHMa1op7274oyiUVrAG4B2EuFhus8SvkaYnhvW92p9Q=="],
"rehype-external-links": ["rehype-external-links@2.0.1", "", { "dependencies": { "@types/hast": "^2.0.0", "extend": "^3.0.0", "is-absolute-url": "^4.0.0", "space-separated-tokens": "^2.0.0", "unified": "^10.0.0", "unist-util-visit": "^4.0.0" } }, "sha512-u2dNypma+ps12SJWlS23zvbqwNx0Hl24t0YHXSM/6FCZj/pqWETCO3WyyrvALv4JYvRtuPjhiv2Lpen15ESqbA=="],
"rehype-external-links": ["rehype-external-links@3.0.0", "", { "dependencies": { "@types/hast": "^3.0.0", "@ungap/structured-clone": "^1.0.0", "hast-util-is-element": "^3.0.0", "is-absolute-url": "^4.0.0", "space-separated-tokens": "^2.0.0", "unist-util-visit": "^5.0.0" } }, "sha512-yp+e5N9V3C6bwBeAC4n796kc86M4gJCdlVhiMTxIrJG5UHDMh+PJANf9heqORJbt1nrCbDwIlAZKjANIaVBbvw=="],
"relateurl": ["relateurl@0.2.7", "", {}, "sha1-VNvzd+UUQKypCkzSdGANP/LYiKk="],
@@ -4783,7 +4780,7 @@
"sha1": ["sha1@1.1.1", "", { "dependencies": { "charenc": ">= 0.0.1", "crypt": ">= 0.0.1" } }, "sha1-rdqnqTFo85PxnrKxUJFhjicA+Eg="],
"shadow-cljs": ["shadow-cljs@2.28.20", "", { "dependencies": { "node-libs-browser": "^2.2.1", "readline-sync": "^1.4.7", "shadow-cljs-jar": "1.3.4", "source-map-support": "^0.4.15", "which": "^1.3.1", "ws": "^7.4.6" }, "bin": { "shadow-cljs": "cli/runner.js" } }, "sha512-Q9N+aw2suSUZ6vmWhZupl0rkyjoYrnpU1WbMrNrbuUiKE6XjvT1vcBkTUrqkMJEPraV7u+H9b5d/RcKnj8nbhg=="],
"shadow-cljs": ["shadow-cljs@3.3.6", "", { "dependencies": { "buffer": "^6.0.3", "process": "^0.11.10", "readline-sync": "^1.4.10", "shadow-cljs-jar": "1.3.4", "source-map-support": "^0.5.21", "which": "^5.0.0", "ws": "^8.18.1" }, "bin": { "shadow-cljs": "cli/runner.js" } }, "sha512-t5TBJmy77abwlkAY7UOXa1s9H/28nTHeDVckgzEVS8ONYtDvbNCHEuBYfS7wwV9wVZVybRNb7dILWNXISJL1Nw=="],
"shadow-cljs-jar": ["shadow-cljs-jar@1.3.4", "", {}, "sha512-cZB2pzVXBnhpJ6PQdsjO+j/MksR28mv4QD/hP/2y1fsIa9Z9RutYgh3N34FZ8Ktl4puAXaIGlct+gMCJ5BmwmA=="],
@@ -4849,7 +4846,7 @@
"source-map-loader": ["source-map-loader@4.0.1", "", { "dependencies": { "abab": "^2.0.6", "iconv-lite": "^0.6.3", "source-map-js": "^1.0.2" } }, "sha512-oqXpzDIByKONVY8g1NUPOTQhe0UTU5bWUl32GSkqK2LjJj0HmwTMVKxcUip0RgAYhY1mqgOxjbQM48a0mmeNfA=="],
"source-map-support": ["source-map-support@0.4.18", "", { "dependencies": { "source-map": "^0.5.6" } }, "sha512-try0/JqxPLF9nOjvSta7tVondkP5dwgyLDjVoyMDlmjugT2lRZ1OfsrYTkCd2hkDnJTKRbO/Rl3orm8vlsUzbA=="],
"source-map-support": ["source-map-support@0.5.21", "", { "dependencies": { "buffer-from": "^1.0.0", "source-map": "^0.6.0" } }, "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w=="],
"sourcemap-codec": ["sourcemap-codec@1.4.8", "", {}, "sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA=="],
@@ -5077,8 +5074,6 @@
"tmpl": ["tmpl@1.0.5", "", {}, "sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw=="],
"to-arraybuffer": ["to-arraybuffer@1.0.1", "", {}, "sha1-fSKbH8xjfkZsoIEYCDanqr/4P0M="],
"to-buffer": ["to-buffer@1.2.1", "", { "dependencies": { "isarray": "^2.0.5", "safe-buffer": "^5.2.1", "typed-array-buffer": "^1.0.3" } }, "sha512-tB82LpAIWjhLYbqjx3X4zEeHN6M8CiuOEy2JY8SEQVdYRe3CCHOFaqrBW1doLDrfpWhplcW7BL+bO3/6S3pcDQ=="],
"to-camel-case": ["to-camel-case@1.0.0", "", { "dependencies": { "to-space-case": "^1.0.0" } }, "sha512-nD8pQi5H34kyu1QDMFjzEIYqk0xa9Alt6ZfrdEMuHCFOfTLhDG5pgTu/aAM9Wt9lXILwlXmWP43b8sav0GNE8Q=="],
@@ -5345,7 +5340,7 @@
"whatwg-url": ["whatwg-url@5.0.0", "", { "dependencies": { "tr46": "~0.0.3", "webidl-conversions": "^3.0.0" } }, "sha1-lmRU6HZUYuN2RNNib2dCzotwll0="],
"which": ["which@1.3.1", "", { "dependencies": { "isexe": "^2.0.0" }, "bin": { "which": "./bin/which" } }, "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ=="],
"which": ["which@5.0.0", "", { "dependencies": { "isexe": "^3.1.1" }, "bin": { "node-which": "bin/which.js" } }, "sha512-JEdGzHwwkrbWoGOlIHqQ5gtprKGOenpDHpxE9zVR1bWbOtYRyPPHMe9FaP6x61CmNaTThSkb0DAJte5jD+DmzQ=="],
"which-boxed-primitive": ["which-boxed-primitive@1.0.2", "", { "dependencies": { "is-bigint": "^1.0.1", "is-boolean-object": "^1.1.0", "is-number-object": "^1.0.4", "is-string": "^1.0.5", "is-symbol": "^1.0.3" } }, "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg=="],
@@ -5375,7 +5370,7 @@
"write-file-atomic": ["write-file-atomic@5.0.1", "", { "dependencies": { "imurmurhash": "^0.1.4", "signal-exit": "^4.0.1" } }, "sha512-+QU2zd6OTD8XWIJCbffaiQeH9U73qIqafo1x6V1snCWYGJf6cVE0cDR4D8xRzcEnfI21IFrUPzPGtcPf8AC+Rw=="],
"ws": ["ws@7.5.10", "", {}, "sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ=="],
"ws": ["ws@8.18.3", "", {}, "sha512-PEIGCY5tSlUt50cqyMXfCzX+oOPqN0vuGqWzbcJ2xvnkzkq46oOpz7dQaTDBdfICb4N14+GARUDw2XV2N4tvzg=="],
"wsl-utils": ["wsl-utils@0.1.0", "", { "dependencies": { "is-wsl": "^3.1.0" } }, "sha512-h3Fbisa2nKGPxCpm89Hk33lBLsnaGBvctQopaBSOW/uIs6FTe1ATyAnKFJrzVs9vpGdsTe73WF3V4lIsk4Gacw=="],
@@ -5609,6 +5604,8 @@
"@loki/target-native-android-emulator/tempy": ["tempy@1.0.1", "", { "dependencies": { "del": "^6.0.0", "is-stream": "^2.0.0", "temp-dir": "^2.0.0", "type-fest": "^0.16.0", "unique-string": "^2.0.0" } }, "sha512-biM9brNqxSc04Ee71hzFbryD11nX7VPhQQY32AdDmjFvodsRFz/3ufeoTZ6uYkRFfGo188tENcASNs3vTdsM0w=="],
"@loki/target-native-core/ws": ["ws@7.5.10", "", {}, "sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ=="],
"@loki/target-native-ios-simulator/tempy": ["tempy@1.0.1", "", { "dependencies": { "del": "^6.0.0", "is-stream": "^2.0.0", "temp-dir": "^2.0.0", "type-fest": "^0.16.0", "unique-string": "^2.0.0" } }, "sha512-biM9brNqxSc04Ee71hzFbryD11nX7VPhQQY32AdDmjFvodsRFz/3ufeoTZ6uYkRFfGo188tENcASNs3vTdsM0w=="],
"@mantine/core/type-fest": ["type-fest@4.41.0", "", {}, "sha512-TeTSQ6H5YHvpqVwBRcnLDCBnDOHWYu7IvGbHT6N8AOymcr9PJGjc1GTtiWZTYg0NCgYwvnYWEkVChQAr9bjfwA=="],
@@ -5985,6 +5982,8 @@
"chrome-remote-interface/commander": ["commander@2.11.0", "", {}, "sha512-b0553uYA5YAEGgyYIGYROzKQ7X5RAqedkfjiZxwi0kL1g3bOaBNNZfYkzt/CL0umgD5wc9Jec2FbB98CjkMRvQ=="],
"chrome-remote-interface/ws": ["ws@7.5.10", "", {}, "sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ=="],
"cipher-base/safe-buffer": ["safe-buffer@5.2.1", "", {}, "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ=="],
"citty/consola": ["consola@3.4.2", "", {}, "sha512-5IKcdX0nnYavi6G7TtOhwkYzyjfJlatbjMjuLSfE2kYT5pMDOilZ4OvMhi637CcDICTmz3wARPoyhqyX1Y+XvA=="],
@@ -6275,6 +6274,8 @@
"global-prefix/ini": ["ini@1.3.8", "", {}, "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew=="],
"global-prefix/which": ["which@1.3.1", "", { "dependencies": { "isexe": "^2.0.0" }, "bin": { "which": "./bin/which" } }, "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ=="],
"globby/ignore": ["ignore@5.1.8", "", {}, "sha512-BMpfD7PpiETpBl/A6S498BaIJ6Y/ABT93ETbby2fP00v4EbvPBXWEoaR1UBPKs3iR53pJY7EtZk5KACI57i1Uw=="],
"globby/slash": ["slash@3.0.0", "", {}, "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q=="],
@@ -6295,6 +6296,8 @@
"hast-util-raw/@types/unist": ["@types/unist@3.0.2", "", {}, "sha512-dqId9J8K/vGi5Zr7oo212BGii5m3q5Hxlkwy3WpYuKPklmBEvsbMYYyLxAQpSffdLl/gdW0XUpKWFvYmyoWCoQ=="],
"hast-util-raw/@ungap/structured-clone": ["@ungap/structured-clone@1.2.0", "", {}, "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ=="],
"hast-util-to-html/@types/unist": ["@types/unist@3.0.2", "", {}, "sha512-dqId9J8K/vGi5Zr7oo212BGii5m3q5Hxlkwy3WpYuKPklmBEvsbMYYyLxAQpSffdLl/gdW0XUpKWFvYmyoWCoQ=="],
"hast-util-to-jsx-runtime/@types/estree": ["@types/estree@1.0.6", "", {}, "sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw=="],
@@ -6343,6 +6346,8 @@
"ink/wrap-ansi": ["wrap-ansi@6.2.0", "", { "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", "strip-ansi": "^6.0.0" } }, "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA=="],
"ink/ws": ["ws@7.5.10", "", {}, "sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ=="],
"inquirer-file-selector/chalk": ["chalk@5.3.0", "", {}, "sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w=="],
"inquirer-toggle/@inquirer/core": ["@inquirer/core@8.2.4", "", { "dependencies": { "@inquirer/figures": "^1.0.3", "@inquirer/type": "^1.3.3", "@types/mute-stream": "^0.0.4", "@types/node": "^20.14.9", "@types/wrap-ansi": "^3.0.0", "ansi-escapes": "^4.3.2", "cli-spinners": "^2.9.2", "cli-width": "^4.1.0", "mute-stream": "^1.0.0", "picocolors": "^1.0.1", "signal-exit": "^4.1.0", "strip-ansi": "^6.0.1", "wrap-ansi": "^6.2.0" } }, "sha512-7vsXSfxtrrbwMTirfaKwPcjqJy7pzeuF/bP62yo1NQrRJ5HjmMlrhZml/Ljm9ODc1RnbhJlTeSnCkjtFddKjwA=="],
@@ -6467,14 +6472,14 @@
"jsdom/whatwg-url": ["whatwg-url@14.2.0", "", { "dependencies": { "tr46": "^5.1.0", "webidl-conversions": "^7.0.0" } }, "sha512-De72GdQZzNTUBBChsXueQUnPKDkg/5A5zp7pFDuQAj5UFoENpiACU0wlCvzpAGnTkj++ihpKwKyYewn/XNUbKw=="],
"jsdom/ws": ["ws@8.18.3", "", {}, "sha512-PEIGCY5tSlUt50cqyMXfCzX+oOPqN0vuGqWzbcJ2xvnkzkq46oOpz7dQaTDBdfICb4N14+GARUDw2XV2N4tvzg=="],
"json-schema-to-ts/@types/json-schema": ["@types/json-schema@7.0.15", "", {}, "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA=="],
"json-stable-stringify/call-bind": ["call-bind@1.0.7", "", { "dependencies": { "es-define-property": "^1.0.0", "es-errors": "^1.3.0", "function-bind": "^1.1.2", "get-intrinsic": "^1.2.4", "set-function-length": "^1.2.1" } }, "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w=="],
"jsonwebtoken/semver": ["semver@7.5.4", "", { "dependencies": { "lru-cache": "^6.0.0" }, "bin": { "semver": "bin/semver.js" } }, "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA=="],
"jspdf/@babel/runtime": ["@babel/runtime@7.28.6", "", {}, "sha512-05WQkdpL9COIMz4LjTxGpPNCdlpyimKppYNoJ5Di5EUObifl8t4tuLuUBBZEpoLYOmfvIWrsp9fCl0HoPRVTdA=="],
"jsx-ast-utils/array-includes": ["array-includes@3.1.3", "", { "dependencies": { "call-bind": "^1.0.2", "define-properties": "^1.1.3", "es-abstract": "^1.18.0-next.2", "get-intrinsic": "^1.1.1", "is-string": "^1.0.5" } }, "sha512-gcem1KlBU7c9rB+Rq8/3PPKsK2kjqeEBa3bD5kkQo4nYlOHQCJqIJFqBXDEfwaRuYTT4E+FxA9xez7Gf/e3Q7A=="],
"jwa/safe-buffer": ["safe-buffer@5.2.1", "", {}, "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ=="],
@@ -6539,6 +6544,8 @@
"mdast-util-mdx-jsx/@types/unist": ["@types/unist@3.0.2", "", {}, "sha512-dqId9J8K/vGi5Zr7oo212BGii5m3q5Hxlkwy3WpYuKPklmBEvsbMYYyLxAQpSffdLl/gdW0XUpKWFvYmyoWCoQ=="],
"mdast-util-to-hast/@ungap/structured-clone": ["@ungap/structured-clone@1.2.0", "", {}, "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ=="],
"mdast-util-to-markdown/@types/unist": ["@types/unist@3.0.2", "", {}, "sha512-dqId9J8K/vGi5Zr7oo212BGii5m3q5Hxlkwy3WpYuKPklmBEvsbMYYyLxAQpSffdLl/gdW0XUpKWFvYmyoWCoQ=="],
"micromatch/picomatch": ["picomatch@2.3.1", "", {}, "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA=="],
@@ -6597,32 +6604,6 @@
"node-environment-flags/semver": ["semver@5.7.1", "", { "bin": { "semver": "./bin/semver" } }, "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ=="],
"node-libs-browser/assert": ["assert@1.5.0", "", { "dependencies": { "object-assign": "^4.1.1", "util": "0.10.3" } }, "sha512-EDsgawzwoun2CZkCgtxJbv392v4nbk9XDD06zI+kQYoBM/3RBWLlEyJARDOmhAAosBjWACEkKL6S+lIZtcAubA=="],
"node-libs-browser/buffer": ["buffer@4.9.2", "", { "dependencies": { "base64-js": "^1.0.2", "ieee754": "^1.1.4", "isarray": "^1.0.0" } }, "sha512-xq+q3SRMOxGivLhBNaUdC64hDTQwejJ+H0T/NB1XMtTVEwNTrfFF3gAxiyW0Bu/xWEGhjVKgUcMhCrUy2+uCWg=="],
"node-libs-browser/domain-browser": ["domain-browser@1.2.0", "", {}, "sha512-jnjyiM6eRyZl2H+W8Q/zLMA481hzi0eszAaBUzIVnmYVDBbnLxVNnfu1HgEBvCbL+71FrxMl3E6lpKH7Ge3OXA=="],
"node-libs-browser/events": ["events@3.2.0", "", {}, "sha512-/46HWwbfCX2xTawVfkKLGxMifJYQBWMwY1mjywRtb4c9x8l5NP3KoJtnIOiL1hfdRkIuYhETxQlo62IF8tcnlg=="],
"node-libs-browser/path-browserify": ["path-browserify@0.0.1", "", {}, "sha512-BapA40NHICOS+USX9SN4tyhq+A2RrN/Ws5F0Z5aMHDp98Fl86lX8Oti8B7uN93L4Ifv4fHOEA+pQw87gmMO/lQ=="],
"node-libs-browser/punycode": ["punycode@1.4.1", "", {}, "sha1-wNWmOycYgArY4esPpSachN1BhF4="],
"node-libs-browser/readable-stream": ["readable-stream@2.3.7", "", { "dependencies": { "core-util-is": "~1.0.0", "inherits": "~2.0.3", "isarray": "~1.0.0", "process-nextick-args": "~2.0.0", "safe-buffer": "~5.1.1", "string_decoder": "~1.1.1", "util-deprecate": "~1.0.1" } }, "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw=="],
"node-libs-browser/stream-browserify": ["stream-browserify@2.0.2", "", { "dependencies": { "inherits": "~2.0.1", "readable-stream": "^2.0.2" } }, "sha512-nX6hmklHs/gr2FuxYDltq8fJA1GDlxKQCz8O/IM4atRqBH8OORmBNgfvW5gG10GT/qQ9u0CzIvr2X5Pkt6ntqg=="],
"node-libs-browser/stream-http": ["stream-http@2.8.3", "", { "dependencies": { "builtin-status-codes": "^3.0.0", "inherits": "^2.0.1", "readable-stream": "^2.3.6", "to-arraybuffer": "^1.0.0", "xtend": "^4.0.0" } }, "sha512-+TSkfINHDo4J+ZobQLWiMouQYB+UVYFttRA94FpEzzJ7ZdqcL4uUUQ7WkdkI4DSozGmgBUE/a47L+38PenXhUw=="],
"node-libs-browser/timers-browserify": ["timers-browserify@2.0.11", "", { "dependencies": { "setimmediate": "^1.0.4" } }, "sha512-60aV6sgJ5YEbzUdn9c8kYGIqOubPoUdqQCul3SBAsRCZ40s6Y5cMcrW4dt3/k/EsbLVJNl9n6Vz3fTc+k2GeKQ=="],
"node-libs-browser/tty-browserify": ["tty-browserify@0.0.0", "", {}, "sha1-oVe6QC2iTpv5V/mqadUk7tQpAaY="],
"node-libs-browser/url": ["url@0.11.0", "", { "dependencies": { "punycode": "1.3.2", "querystring": "0.2.0" } }, "sha1-ODjpfPxgUh63PFJajlW/3Z4uKPE="],
"node-libs-browser/util": ["util@0.11.1", "", { "dependencies": { "inherits": "2.0.3" } }, "sha512-HShAsny+zS2TZfaXxD9tYj4HQGlBezXZMZuM/S5PKLLoZkShZiGk9o5CzukI1LVHZvjdvZ2Sj1aW/Ndn2NB/HQ=="],
"node-notifier/is-wsl": ["is-wsl@2.2.0", "", { "dependencies": { "is-docker": "^2.0.0" } }, "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww=="],
"node-notifier/semver": ["semver@7.5.4", "", { "dependencies": { "lru-cache": "^6.0.0" }, "bin": { "semver": "bin/semver.js" } }, "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA=="],
@@ -6763,6 +6744,8 @@
"rc/strip-json-comments": ["strip-json-comments@2.0.1", "", {}, "sha1-PFMZQukIwml8DsNEhYwobHygpgo="],
"react-devtools-core/ws": ["ws@7.5.10", "", {}, "sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ=="],
"react-dnd/dnd-core": ["dnd-core@4.0.5", "", { "dependencies": { "asap": "^2.0.6", "invariant": "^2.2.4", "lodash": "^4.17.10", "redux": "^4.0.0" } }, "sha512-GSyGmfGom9oyTFJ4Ll/95Dn3ZDvPkrgINwfeOd+gTI0RGIN1TcTGChrHnIHF3A3e1PymyEKZg+3ouN3w2uIJGQ=="],
"react-dnd/hoist-non-react-statics": ["hoist-non-react-statics@2.5.5", "", {}, "sha512-rqcy4pJo55FTTLWt+bU8ukscqHeE/e9KWvsOW2b/a3afxQZhwkQdT1rPPCJ0rYXdj4vNcasY8zHTH+jF/qStxw=="],
@@ -6841,12 +6824,6 @@
"reg-cli/yargs-parser": ["yargs-parser@21.1.1", "", {}, "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw=="],
"rehype-external-links/@types/hast": ["@types/hast@2.3.2", "", { "dependencies": { "@types/unist": "*" } }, "sha512-Op5W7jYgZI7AWKY5wQ0/QNMzQM7dGQPyW1rXKNiymVCy5iTfdPuGu4HhYNOM2sIv8gUfIuIdcYlXmAepwaowow=="],
"rehype-external-links/unified": ["unified@10.1.2", "", { "dependencies": { "@types/unist": "^2.0.0", "bail": "^2.0.0", "extend": "^3.0.0", "is-buffer": "^2.0.0", "is-plain-obj": "^4.0.0", "trough": "^2.0.0", "vfile": "^5.0.0" } }, "sha512-pUSWAi/RAnVy1Pif2kAoeWNBa3JVrx0MId2LASj8G+7AiHWoKZNTomq6LG326T68U7/e263X6fTdcXIy7XnF7Q=="],
"rehype-external-links/unist-util-visit": ["unist-util-visit@4.1.1", "", { "dependencies": { "@types/unist": "^2.0.0", "unist-util-is": "^5.0.0", "unist-util-visit-parents": "^5.1.1" } }, "sha512-n9KN3WV9k4h1DxYR1LoajgN93wpEi/7ZplVe02IoB4gH5ctI1AaF2670BLHQYbwj+pY83gFtyeySFiyMHJklrg=="],
"renderkid/css-select": ["css-select@4.1.3", "", { "dependencies": { "boolbase": "^1.0.0", "css-what": "^5.0.0", "domhandler": "^4.2.0", "domutils": "^2.6.0", "nth-check": "^2.0.0" } }, "sha512-gT3wBNd9Nj49rAbmtFHj1cljIAOLYSX1nZ8CB7TBO3INYckygm5B7LISU/szY//YmdiSLbJvDLOx9VnMVpMBxA=="],
"resolve/is-core-module": ["is-core-module@2.16.1", "", { "dependencies": { "hasown": "^2.0.2" } }, "sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w=="],
@@ -6883,10 +6860,14 @@
"simple-websocket/readable-stream": ["readable-stream@3.6.2", "", { "dependencies": { "inherits": "^2.0.3", "string_decoder": "^1.1.1", "util-deprecate": "^1.0.1" } }, "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA=="],
"simple-websocket/ws": ["ws@7.5.10", "", {}, "sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ=="],
"snake-case/tslib": ["tslib@2.2.0", "", {}, "sha512-gS9GVHRU+RGn5KQM2rllAlR3dU6m7AcpJKdtH8gFvQiC4Otgk98XnmMU+nZenHt/+VhnBPWwgrJsyrdcw6i23w=="],
"sockjs/uuid": ["uuid@8.3.2", "", { "bin": { "uuid": "dist/bin/uuid" } }, "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg=="],
"source-map-support/source-map": ["source-map@0.6.1", "", {}, "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="],
"spdy-transport/readable-stream": ["readable-stream@3.6.2", "", { "dependencies": { "inherits": "^2.0.3", "string_decoder": "^1.1.1", "util-deprecate": "^1.0.1" } }, "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA=="],
"sql-formatter/get-stdin": ["get-stdin@8.0.0", "", {}, "sha512-sY22aA6xchAzprjyqmSEQv4UbAAzRN0L2dQB0NlN5acTTK9Don6nhoc3eAbUnpZiCANAMfd/+40kVdKfFygohg=="],
@@ -7073,6 +7054,8 @@
"webpack-bundle-analyzer/commander": ["commander@7.2.0", "", {}, "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw=="],
"webpack-bundle-analyzer/ws": ["ws@7.5.10", "", {}, "sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ=="],
"webpack-cli/@discoveryjs/json-ext": ["@discoveryjs/json-ext@0.5.3", "", {}, "sha512-Fxt+AfXgjMoin2maPIYzFZnQjAXjAL0PHscM5pRTtatFqB+vZxAM9tLp2Optnuw3QOQC40jTNeGYFOMvyf7v9g=="],
"webpack-cli/colorette": ["colorette@2.0.16", "", {}, "sha512-hUewv7oMjCp+wkBv5Rm0v87eJhq4woh5rSR+42YSQJKecCqgIqNkZ6lAlQms/BwHPJA5NKMRlpxPRv0n8HQW6g=="],
@@ -7175,6 +7158,8 @@
"@ferocia-oss/osnap/execa/strip-final-newline": ["strip-final-newline@3.0.0", "", {}, "sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw=="],
"@ferocia-oss/osnap/which/isexe": ["isexe@2.0.0", "", {}, "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw=="],
"@inquirer/checkbox/ansi-escapes/type-fest": ["type-fest@0.21.3", "", {}, "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w=="],
"@inquirer/core/ansi-escapes/type-fest": ["type-fest@0.21.3", "", {}, "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w=="],
@@ -7207,8 +7192,6 @@
"@jest/reporters/glob/path-scurry": ["path-scurry@1.11.1", "", { "dependencies": { "lru-cache": "^10.2.0", "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" } }, "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA=="],
"@jest/reporters/jest-worker/@ungap/structured-clone": ["@ungap/structured-clone@1.3.0", "", {}, "sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g=="],
"@jest/reporters/jest-worker/supports-color": ["supports-color@8.1.1", "", { "dependencies": { "has-flag": "^4.0.0" } }, "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q=="],
"@jest/source-map/@jridgewell/trace-mapping/@jridgewell/resolve-uri": ["@jridgewell/resolve-uri@3.1.2", "", {}, "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw=="],
@@ -7281,6 +7264,8 @@
"@rspack/cli/webpack-bundle-analyzer/commander": ["commander@7.2.0", "", {}, "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw=="],
"@rspack/cli/webpack-bundle-analyzer/ws": ["ws@7.5.10", "", {}, "sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ=="],
"@rspack/cli/yargs/cliui": ["cliui@8.0.1", "", { "dependencies": { "string-width": "^4.2.0", "strip-ansi": "^6.0.1", "wrap-ansi": "^7.0.0" } }, "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ=="],
"@rspack/cli/yargs/yargs-parser": ["yargs-parser@21.1.1", "", {}, "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw=="],
@@ -7503,6 +7488,8 @@
"configstore/unique-string/crypto-random-string": ["crypto-random-string@2.0.0", "", {}, "sha512-v1plID3y9r/lPhviJ1wrXpLeyUIGAZ2SHNYTEapm7/8A9nLPoyvVp3RK/EPFqn5kEznyWgYZNsRtYYIWbuG8KA=="],
"cross-spawn/which/isexe": ["isexe@2.0.0", "", {}, "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw=="],
"css-loader/semver/lru-cache": ["lru-cache@6.0.0", "", { "dependencies": { "yallist": "^4.0.0" } }, "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA=="],
"csso/css-tree/mdn-data": ["mdn-data@2.0.28", "", {}, "sha512-aylIc7Z9y4yzHYAJNuESG3hfhC+0Ibp/MAMiaOZgNv4pmEdFyfZhhhny4MNiAfWdBQ1RQ2mfDWmM1x8SvGyp8g=="],
@@ -7629,6 +7616,8 @@
"fork-ts-checker-webpack-plugin/semver/lru-cache": ["lru-cache@6.0.0", "", { "dependencies": { "yallist": "^4.0.0" } }, "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA=="],
"global-prefix/which/isexe": ["isexe@2.0.0", "", {}, "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw=="],
"hpack.js/readable-stream/isarray": ["isarray@1.0.0", "", {}, "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE="],
"hpack.js/readable-stream/string_decoder": ["string_decoder@1.1.1", "", { "dependencies": { "safe-buffer": "~5.1.0" } }, "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg=="],
@@ -7785,8 +7774,6 @@
"jest-haste-map/anymatch/picomatch": ["picomatch@2.3.1", "", {}, "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA=="],
"jest-haste-map/jest-worker/@ungap/structured-clone": ["@ungap/structured-clone@1.3.0", "", {}, "sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g=="],
"jest-haste-map/jest-worker/supports-color": ["supports-color@8.1.1", "", { "dependencies": { "has-flag": "^4.0.0" } }, "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q=="],
"jest-haste-map/micromatch/picomatch": ["picomatch@2.3.1", "", {}, "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA=="],
@@ -7805,8 +7792,6 @@
"jest-message-util/pretty-format/react-is": ["react-is@18.3.1", "", {}, "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg=="],
"jest-runner/jest-worker/@ungap/structured-clone": ["@ungap/structured-clone@1.3.0", "", {}, "sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g=="],
"jest-runner/jest-worker/supports-color": ["supports-color@8.1.1", "", { "dependencies": { "has-flag": "^4.0.0" } }, "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q=="],
"jest-runner/source-map-support/source-map": ["source-map@0.6.1", "", {}, "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="],
@@ -7913,26 +7898,12 @@
"nano-css/css-tree/source-map": ["source-map@0.6.1", "", {}, "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="],
"node-libs-browser/assert/util": ["util@0.10.3", "", { "dependencies": { "inherits": "2.0.1" } }, "sha1-evsa/lCAUkZInj23/g7TeTNqwPk="],
"node-libs-browser/buffer/base64-js": ["base64-js@1.3.1", "", {}, "sha512-mLQ4i2QO1ytvGWFWmcngKO//JXAQueZvwEKtjgQFM4jIK0kU+ytMfplL8j+n5mspOfjHwoAg+9yhb7BwAHm36g=="],
"node-libs-browser/buffer/ieee754": ["ieee754@1.1.13", "", {}, "sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg=="],
"node-libs-browser/buffer/isarray": ["isarray@1.0.0", "", {}, "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE="],
"node-libs-browser/readable-stream/isarray": ["isarray@1.0.0", "", {}, "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE="],
"node-libs-browser/readable-stream/string_decoder": ["string_decoder@1.1.1", "", { "dependencies": { "safe-buffer": "~5.1.0" } }, "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg=="],
"node-libs-browser/url/punycode": ["punycode@1.3.2", "", {}, "sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0="],
"node-libs-browser/util/inherits": ["inherits@2.0.3", "", {}, "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4="],
"node-notifier/is-wsl/is-docker": ["is-docker@2.2.1", "", { "bin": { "is-docker": "cli.js" } }, "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ=="],
"node-notifier/semver/lru-cache": ["lru-cache@6.0.0", "", { "dependencies": { "yallist": "^4.0.0" } }, "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA=="],
"node-notifier/which/isexe": ["isexe@2.0.0", "", {}, "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw=="],
"oas-resolver/yargs/cliui": ["cliui@8.0.1", "", { "dependencies": { "string-width": "^4.2.0", "strip-ansi": "^6.0.1", "wrap-ansi": "^7.0.0" } }, "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ=="],
"oas-resolver/yargs/yargs-parser": ["yargs-parser@21.1.1", "", {}, "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw=="],
@@ -8093,16 +8064,6 @@
"reg-cli/meow/redent": ["redent@1.0.0", "", { "dependencies": { "indent-string": "^2.1.0", "strip-indent": "^1.0.1" } }, "sha512-qtW5hKzGQZqKoh6JNSD+4lfitfPKGz42e6QwiRmPM5mmKtR0N41AbJRYu0xJi7nhOJ4WDgRkKvAk6tw4WIwR4g=="],
"rehype-external-links/unified/is-buffer": ["is-buffer@2.0.5", "", {}, "sha512-i2R6zNFDwgEHJyQUtJEk0XFi1i0dPFn/oqjK3/vPCcDeJvW5NQ83V8QbicfF1SupOaB0h8ntgBC2YiE7dfyctQ=="],
"rehype-external-links/unified/is-plain-obj": ["is-plain-obj@4.1.0", "", {}, "sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg=="],
"rehype-external-links/unified/vfile": ["vfile@5.3.6", "", { "dependencies": { "@types/unist": "^2.0.0", "is-buffer": "^2.0.0", "unist-util-stringify-position": "^3.0.0", "vfile-message": "^3.0.0" } }, "sha512-ADBsmerdGBs2WYckrLBEmuETSPyTD4TuLxTrw0DvjirxW1ra4ZwkbzG8ndsv3Q57smvHxo677MHaQrY9yxH8cA=="],
"rehype-external-links/unist-util-visit/unist-util-is": ["unist-util-is@5.1.1", "", {}, "sha512-F5CZ68eYzuSvJjGhCLPL3cYx45IxkqXSetCcRgUXtbcm50X2L9oOWQlfUfDdAf+6Pd27YDblBfdtmsThXmwpbQ=="],
"rehype-external-links/unist-util-visit/unist-util-visit-parents": ["unist-util-visit-parents@5.1.1", "", { "dependencies": { "@types/unist": "^2.0.0", "unist-util-is": "^5.0.0" } }, "sha512-gks4baapT/kNRaWxuGkl5BIhoanZo7sC/cUT/JToSRNL1dYoXRFl75d++NkjYk4TAu2uv2Px+l8guMajogeuiw=="],
"renderkid/css-select/css-what": ["css-what@5.1.0", "", {}, "sha512-arSMRWIIFY0hV8pIxZMEfmMI47Wj3R/aWpZDDxWYCPEiOMv6tfOrnpDtgxBYPEQD4V0Y/958+1TdC3iWTFcUPw=="],
"renderkid/css-select/domhandler": ["domhandler@4.2.2", "", { "dependencies": { "domelementtype": "^2.2.0" } }, "sha512-PzE9aBMsdZO8TK4BnuJwH0QT41wgMbRzuZrHUcpYncEjmQazq8QEaBWgLG7ZyC/DAZKEgglpIA6j4Qn/HmxS3w=="],
@@ -8721,8 +8682,6 @@
"msw/@inquirer/confirm/@inquirer/core/wrap-ansi": ["wrap-ansi@6.2.0", "", { "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", "strip-ansi": "^6.0.0" } }, "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA=="],
"node-libs-browser/assert/util/inherits": ["inherits@2.0.1", "", {}, "sha1-sX0I0ya0Qj5Wjv9xn5GwscvfafE="],
"node-notifier/semver/lru-cache/yallist": ["yallist@4.0.0", "", {}, "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A=="],
"object-is/call-bind/get-intrinsic/has-proto": ["has-proto@1.0.1", "", {}, "sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg=="],
@@ -8839,10 +8798,6 @@
"reg-cli/meow/redent/strip-indent": ["strip-indent@1.0.1", "", { "dependencies": { "get-stdin": "^4.0.1" }, "bin": { "strip-indent": "cli.js" } }, "sha512-I5iQq6aFMM62fBEAIB/hXzwJD6EEZ0xEGCX2t7oXqaKPIRgt4WruAQ285BISgdkP+HLGWyeGmNJcpIwFeRYRUA=="],
"rehype-external-links/unified/vfile/unist-util-stringify-position": ["unist-util-stringify-position@3.0.2", "", { "dependencies": { "@types/unist": "^2.0.0" } }, "sha512-7A6eiDCs9UtjcwZOcCpM4aPII3bAAGv13E96IkawkOAW0OhH+yRxtY0lzo8KiHpzEMfH7Q+FizUmwp8Iqy5EWg=="],
"rehype-external-links/unified/vfile/vfile-message": ["vfile-message@3.1.3", "", { "dependencies": { "@types/unist": "^2.0.0", "unist-util-stringify-position": "^3.0.0" } }, "sha512-0yaU+rj2gKAyEk12ffdSbBfjnnj+b1zqTBv3OQCTn8yEB02bsPizwdBPrLJjHnK+cU9EMMcUnNv938XcZIkmdA=="],
"renderkid/css-select/domhandler/domelementtype": ["domelementtype@2.2.0", "", {}, "sha512-DtBMo82pv1dFtUmHyr48beiuq792Sxohr+8Hm9zoxklYPfa6n0Z3Byjj2IV7bmr2IyqClnqEQhfgHJJ5QF0R5A=="],
"renderkid/css-select/domutils/dom-serializer": ["dom-serializer@1.3.2", "", { "dependencies": { "domelementtype": "^2.0.1", "domhandler": "^4.2.0", "entities": "^2.0.0" } }, "sha512-5c54Bk5Dw4qAxNOI1pFEizPSjVsx5+bpJKmL2kPn8JhBUq2q09tTCa3mjijun2NfK78NMouDYNMBkOrPZiS+ig=="],

View File

@@ -53,7 +53,7 @@
{:mvn/version "2.1.214"} ; embedded SQL database
com.ibm.icu/icu4j {:mvn/version "78.1"} ; Used to transliterate Unicode characters into Latin characters
com.knuddels/jtokkit {:mvn/version "1.1.0"} ; Java tokenizer library for OpenAI models, used for token counting in semantic search
com.mchange/c3p0 {:mvn/version "0.11.2"} ; DB connection pool
com.mchange/c3p0 {:mvn/version "0.12.0"} ; DB connection pool
com.snowplowanalytics/snowplow-java-tracker ^:antq/exclude ; 2+ depend on apache httpclient 5.x, but saml and clj-http depend on 4.x
{:mvn/version "1.0.1"} ; Snowplow analytics
com.sun.mail/jakarta.mail ^:antq/exclude ; 2+ changes imports from javax.mail to jakarta.mail
@@ -111,14 +111,17 @@
net.sf.cssbox/cssbox {:mvn/version "5.0.2" ; HTML / CSS rendering
:exclusions [org.slf4j/slf4j-api
junit/junit]}
net.thisptr/jackson-jq {:mvn/version "1.6.0"} ; Java implementation of the JQ json query language
org.apache.commons/commons-compress {:mvn/version "1.28.0"} ; compression utils
org.apache.commons/commons-lang3 {:mvn/version "3.19.0"} ; helper methods for working with java.lang stuff
org.apache.logging.log4j/log4j-1.2-api {:mvn/version "2.25.3"} ; apache logging framework
org.apache.logging.log4j/log4j-api {:mvn/version "2.25.3"} ; add compatibility with log4j 1.2
org.apache.logging.log4j/log4j-core {:mvn/version "2.25.3"} ; apache logging framework
org.apache.logging.log4j/log4j-jcl {:mvn/version "2.25.3"} ; allows the commons-logging API to work with log4j 2
org.apache.logging.log4j/log4j-jul {:mvn/version "2.25.3"} ; java.util.logging (JUL) -> Log4j2 adapter
net.thisptr/jackson-jq {:mvn/version "1.6.0"} ; Java implementation of the JQ json query language
org.apache.commons/commons-compress {:mvn/version "1.28.0"} ; compression utils
org.apache.commons/commons-lang3 {:mvn/version "3.19.0"} ; helper methods for working with java.lang stuff
org.apache.httpcomponents.client5/httpclient5 {:mvn/version "5.4.4"} ; pinned: ClickHouse JDBC 0.9.7 needs httpcore5 5.3.4+; must pair with httpclient5 5.4.x
org.apache.httpcomponents.core5/httpcore5 {:mvn/version "5.3.4"} ; pinned: ClickHouse JDBC 0.9.7 requires URIBuilder.optimize() added in 5.3
org.apache.httpcomponents.core5/httpcore5-h2 {:mvn/version "5.3.4"} ; pinned: must match httpcore5 version
org.apache.logging.log4j/log4j-1.2-api {:mvn/version "2.25.3"} ; apache logging framework
org.apache.logging.log4j/log4j-api {:mvn/version "2.25.3"} ; add compatibility with log4j 1.2
org.apache.logging.log4j/log4j-core {:mvn/version "2.25.3"} ; apache logging framework
org.apache.logging.log4j/log4j-jcl {:mvn/version "2.25.3"} ; allows the commons-logging API to work with log4j 2
org.apache.logging.log4j/log4j-jul {:mvn/version "2.25.3"} ; java.util.logging (JUL) -> Log4j2 adapter
org.apache.logging.log4j/log4j-layout-template-json
{:mvn/version "2.25.2"} ; allows the custom json logging format
org.apache.logging.log4j/log4j-slf4j2-impl
@@ -445,9 +448,10 @@
com.lambdaisland/glogi {:mvn/version "1.3.169"}
io.github.metabase/hawk {:mvn/version "1.0.13"}
org.clojars.mmb90/cljs-cache {:mvn/version "0.1.4"}
org.clojure/clojurescript {:mvn/version "1.12.134"}
refactor-nrepl/refactor-nrepl {:mvn/version "3.11.0"}
;; keep it in sync with package.json
thheller/shadow-cljs {:mvn/version "3.2.1"}}}
thheller/shadow-cljs {:mvn/version "3.3.5"}}}
;; for local dev -- include the drivers locally with :dev:drivers
:drivers
@@ -631,6 +635,29 @@
;; and a simple reproduction repo can be found here https://github.com/metabase/snowplow-eastwood-issue
:exclude-namespaces [metabase.analytics.snowplow]}}
;; Test counterpart of :eastwood. Starts with :reflection only; add more linters as we fix other eastwood
;; issues in tests.
;;
;; clojure -X:dev:ee:ee-dev:drivers:drivers-dev:test:eastwood/test
:eastwood/test
{:exec-fn metabase.linters.eastwood/eastwood
:exec-args {:source-paths ["test"
"enterprise/backend/test"]
:linters [:reflection]
:exclude-namespaces
[;; byte/1 dispatch value trips up Eastwood's reader
metabase.test.http-client
;; Cookie/.getName qualified method trips up Eastwood's analyzer
metabase.server.middleware.settings-cache-test
;; .cljc syntax error during Eastwood's analyze+eval phase
metabase.lib.query-test
;; "count not supported on this type: Symbol" in Eastwood's analyzer
metabase.query-processor.parameters.temporal-units-test
;; Syntax error compiling fn* in Eastwood's analyzer
metabase.sql-tools.macaw.references-test
;; Method too large for Eastwood's analyzer
metabase.sql-tools.sqlglot.references-test]}}
;; clojure -T:whitespace-linter
:whitespace-linter
{:deps {com.github.camsaul/whitespace-linter {:sha "e35bc252ccf5cc74f7d543ef95ad8a3e5131f25b"}}

View File

@@ -30,13 +30,36 @@ For now, Metabot is only available for Metabase Cloud. Before you can set up Met
Once you've added Metabot AI in the Metabase store, you can log into your Metabase and configure it in _Admin > AI_.
## Metabot options
You can set options for Metabot, both for your internal Metabase, and (separately) for embedded Metabase contexts. That way you can, say, use Metabot in your Metabase, while not giving access to Metabot in your embedded Metabase.
- [Enable Metabot](#enable-metabot)
- [Verified content](#verified-content)
- [Collection Metabot can use](#collection-metabot-can-use)
## Enable Metabot
Toggle [Metabot](./metabot.md) on or off for your Metabase or embedded contexts. Both Metabot and Embedded Metabot are enabled by default.
### Internal Metabot
When enabled, Metabot is available to help people create questions, analyze data, and answer questions about your data. When disabled, the Metabot icon and keyboard shortcuts are hidden.
### Embedded Metabot
The toggle will turn embedded Metabot on or off. The toggle affects both full-app embeds and modular embeds.
- [Full-app embedding](../embedding/full-app-embedding.md): The Metabot icon and keyboard shortcuts are only available when Metabot is enabled. Turning off Embedded Metabot will hide these icons and disable the keyboard shortcuts.
- [Modular embedding](../embedding/modular-embedding.md) The toggle doesn't add Metabot anywhere; you have to explicitly include a chat component (like the SDK's [`MetabotQuestion`](../embedding/sdk/ai-chat.md)) in your application. If, however, you've added a component, and you turn off the Embedded Metabot toggle, your chat component will stop working, so you should also remove or hide the component in your application.
## Verified content
Admins on Pro and Enterprise plans can tell Metabot to only work with [models](../data-modeling/models.md) and [metrics](../data-modeling/metrics.md) that have been [verified](../exploration-and-organization/content-verification.md).
Restricting Metabot to verified models and metrics (and only models and metrics) helps Metabot produce more reliable answers, since you know someone has at least vetted the data Metabot can use.
## Collection for natural language querying
## Collection Metabot can use
Select a collection (including its subcollections) to limit which collections Metabot searches during [AI exploration](../ai/metabot.md#ai-exploration).
@@ -44,18 +67,6 @@ This setting only affects conversations started from **+ New → AI exploration*
People can still @-mention items outside of this collection when prompting in AI exploration. Metabot can also see the person's current context (for example, Metabot will know about the dashboard they're currently viewing, even if the dashboard is outside the selected collection).
## When embedding Metabot, you can pick a collection for Metabot to have access to
When embedding Metabot in your app, you can select a collection for Metabot:
2. Click **Embedded Metabot**.
3. In the **Collection Embedded Metabot can use** section, click **Pick a collection**.
4. Select the collection that contains the models and metrics you want Metabot to use.
Metabot will use the models and metrics in that collection to help answer questions and generate queries. You can change this collection at any time. To give Metabot access to all collections, you can set the collection to the root collection, called "Our Analytics" (the default).
Alternatively (or additionally), you can restrict Metabot to [verified content](#verified-content).
## Tips for making the most of Metabot
The best thing you can do to improve Metabot's performance is to prep your data like you would for onboarding a new (human) hire to your data. In practice, this means you should:

View File

@@ -5556,9 +5556,19 @@
"type" : "integer"
},
"source-tables" : {
"type" : "object",
"additionalProperties" : {
"type" : "integer"
"type" : "array",
"items" : {
"type" : "object",
"properties" : {
"alias" : {
"type" : "string",
"minLength" : 1
},
"table_id" : {
"type" : "integer"
}
},
"required" : [ "alias", "table_id" ]
}
},
"type" : {
@@ -6421,6 +6431,38 @@
"required" : [ "type", "subject", "body" ]
} ]
},
"metabase.channel.models.channel.ChannelTemplateEmailDetailsUserProvided" : {
"description" : "Email template details schema for API-provided templates. Only handlebars-text is allowed;\n handlebars-resource is restricted to internal use only.",
"type" : "object",
"properties" : {
"body" : {
"type" : "string"
},
"recipient-type" : {
"enum" : [ "cc", "bcc", "cc", "bcc" ]
},
"subject" : {
"type" : "string"
},
"type" : {
"enum" : [ "email/handlebars-text", "email/handlebars-text" ]
}
},
"required" : [ "type", "subject", "body" ]
},
"metabase.channel.models.channel.ChannelTemplateUserProvided" : {
"description" : "Channel Template schema for API-provided templates. Does not allow handlebars-resource.",
"oneOf" : [ {
"type" : "object",
"properties" : {
"channel_type" : { },
"details" : {
"$ref" : "#/components/schemas/metabase.channel.models.channel.ChannelTemplateEmailDetailsUserProvided"
}
},
"required" : [ "channel_type", "details" ]
}, { } ]
},
"metabase.collections-rest.api.DashboardQuestionCandidate" : {
"type" : "object",
"properties" : {
@@ -7202,6 +7244,13 @@
"metabase.legacy-mbql.schema..legacy-column-metadata.qualified-keys" : {
"type" : "object",
"properties" : {
"qp.pivot/pivot-grouping?" : {
"oneOf" : [ {
"type" : "boolean"
}, {
"type" : "null"
} ]
},
"metabase.lib.metadata.result-metadata/field-ref" : {
"oneOf" : [ {
"$ref" : "#/components/schemas/metabase.legacy-mbql.schema.Reference"
@@ -7280,6 +7329,13 @@
"type" : "null"
} ]
},
"lib/from-model?" : {
"oneOf" : [ {
"type" : "boolean"
}, {
"type" : "null"
} ]
},
"lib/card-id" : {
"oneOf" : [ {
"description" : "Valid Card ID",
@@ -7914,6 +7970,13 @@
"default" : { },
"type" : "object",
"properties" : {
"qp.pivot/pivot-grouping?" : {
"oneOf" : [ {
"type" : "boolean"
}, {
"type" : "null"
} ]
},
"binning" : {
"$ref" : "#/components/schemas/metabase.lib.schema.binning.binning"
},
@@ -8885,6 +8948,13 @@
"allOf" : [ {
"type" : "object",
"properties" : {
"qp.pivot/pivot-grouping?" : {
"oneOf" : [ {
"type" : "boolean"
}, {
"type" : "null"
} ]
},
"metabase.lib.metadata.result-metadata/field-ref" : {
"oneOf" : [ {
"$ref" : "#/components/schemas/metabase.legacy-mbql.schema.Reference"
@@ -8995,6 +9065,13 @@
"type" : "null"
} ]
},
"lib/from-model?" : {
"oneOf" : [ {
"type" : "boolean"
}, {
"type" : "null"
} ]
},
"name" : {
"type" : "string"
},
@@ -10719,6 +10796,13 @@
"type" : "null"
} ]
},
"qp.pivot/pivot-grouping?" : {
"oneOf" : [ {
"type" : "boolean"
}, {
"type" : "null"
} ]
},
"metabase.lib.metadata.result-metadata/field-ref" : {
"oneOf" : [ {
"$ref" : "#/components/schemas/metabase.legacy-mbql.schema.Reference"
@@ -10850,6 +10934,13 @@
"type" : "null"
} ]
},
"lib/from-model?" : {
"oneOf" : [ {
"type" : "boolean"
}, {
"type" : "null"
} ]
},
"name" : {
"type" : "string"
},
@@ -11216,6 +11307,13 @@
"type" : "null"
} ]
},
"qp.pivot/pivot-grouping?" : {
"oneOf" : [ {
"type" : "boolean"
}, {
"type" : "null"
} ]
},
"metabase.lib.metadata.result-metadata/field-ref" : {
"oneOf" : [ {
"$ref" : "#/components/schemas/metabase.legacy-mbql.schema.Reference"
@@ -11347,6 +11445,13 @@
"type" : "null"
} ]
},
"lib/from-model?" : {
"oneOf" : [ {
"type" : "boolean"
}, {
"type" : "null"
} ]
},
"name" : {
"type" : "string"
},
@@ -11892,6 +11997,13 @@
"default" : { },
"type" : "object",
"properties" : {
"qp.pivot/pivot-grouping?" : {
"oneOf" : [ {
"type" : "boolean"
}, {
"type" : "null"
} ]
},
"binning" : {
"$ref" : "#/components/schemas/metabase.lib.schema.binning.binning"
},
@@ -11974,6 +12086,13 @@
"default" : { },
"type" : "object",
"properties" : {
"qp.pivot/pivot-grouping?" : {
"oneOf" : [ {
"type" : "boolean"
}, {
"type" : "null"
} ]
},
"binning" : {
"$ref" : "#/components/schemas/metabase.lib.schema.binning.binning"
},
@@ -12519,6 +12638,532 @@
},
"required" : [ "id", "name", "table_id", "definition", "archived", "creator_id", "created_at", "updated_at" ]
},
"metabase.notification.api.notification.NotificationApiInput" : {
"description" : "Notification schema for API input. Like FullyHydratedNotification but restricts templates\n to user-provided types only (no handlebars-resource).",
"oneOf" : [ {
"oneOf" : [ {
"type" : "object",
"properties" : {
"creator" : {
"oneOf" : [ {
"type" : "object",
"properties" : { }
}, {
"type" : "null"
} ]
},
"handlers" : {
"type" : "array",
"items" : {
"type" : "object",
"properties" : {
"active" : {
"oneOf" : [ {
"type" : "boolean"
}, {
"type" : "null"
} ]
},
"channel" : {
"oneOf" : [ {
"$ref" : "#/components/schemas/metabase.channel.models.channel.Channel"
}, {
"type" : "null"
} ]
},
"channel_id" : {
"oneOf" : [ {
"description" : "value must be an integer greater than zero.",
"type" : "integer",
"minimum" : 1
}, {
"type" : "null"
} ]
},
"channel_type" : { },
"notification_id" : {
"description" : "value must be an integer greater than zero.",
"type" : "integer",
"minimum" : 1
},
"recipients" : {
"type" : "array",
"items" : {
"$ref" : "#/components/schemas/metabase.notification.models.NotificationRecipient"
}
},
"template" : {
"oneOf" : [ {
"$ref" : "#/components/schemas/metabase.channel.models.channel.ChannelTemplateUserProvided"
}, {
"type" : "null"
} ]
},
"template_id" : {
"oneOf" : [ {
"description" : "value must be an integer greater than zero.",
"type" : "integer",
"minimum" : 1
}, {
"type" : "null"
} ]
}
},
"required" : [ "channel_type" ]
}
},
"payload" : {
"$ref" : "#/components/schemas/metabase.notification.models.NotificationCard"
},
"payload_id" : {
"type" : "null"
},
"payload_type" : {
"type" : "string",
"enum" : [ "notification/dashboard", "notification/system-event", "notification/testing", "notification/card" ]
},
"subscriptions" : {
"type" : "array",
"items" : {
"$ref" : "#/components/schemas/metabase.notification.models.NotificationSubscription"
}
}
},
"required" : [ "payload_type", "payload" ]
}, {
"type" : "object",
"properties" : {
"creator" : {
"oneOf" : [ {
"type" : "object",
"properties" : { }
}, {
"type" : "null"
} ]
},
"handlers" : {
"type" : "array",
"items" : {
"type" : "object",
"properties" : {
"active" : {
"oneOf" : [ {
"type" : "boolean"
}, {
"type" : "null"
} ]
},
"channel" : {
"oneOf" : [ {
"$ref" : "#/components/schemas/metabase.channel.models.channel.Channel"
}, {
"type" : "null"
} ]
},
"channel_id" : {
"oneOf" : [ {
"description" : "value must be an integer greater than zero.",
"type" : "integer",
"minimum" : 1
}, {
"type" : "null"
} ]
},
"channel_type" : { },
"notification_id" : {
"description" : "value must be an integer greater than zero.",
"type" : "integer",
"minimum" : 1
},
"recipients" : {
"type" : "array",
"items" : {
"$ref" : "#/components/schemas/metabase.notification.models.NotificationRecipient"
}
},
"template" : {
"oneOf" : [ {
"$ref" : "#/components/schemas/metabase.channel.models.channel.ChannelTemplateUserProvided"
}, {
"type" : "null"
} ]
},
"template_id" : {
"oneOf" : [ {
"description" : "value must be an integer greater than zero.",
"type" : "integer",
"minimum" : 1
}, {
"type" : "null"
} ]
}
},
"required" : [ "channel_type" ]
}
},
"payload_id" : {
"type" : "null"
},
"payload_type" : {
"type" : "string",
"enum" : [ "notification/dashboard", "notification/system-event", "notification/testing", "notification/card" ]
},
"subscriptions" : {
"type" : "array",
"items" : {
"$ref" : "#/components/schemas/metabase.notification.models.NotificationSubscription"
}
}
},
"required" : [ "payload_type" ]
} ]
}, {
"oneOf" : [ {
"type" : "object",
"properties" : {
"creator" : {
"oneOf" : [ {
"type" : "object",
"properties" : { }
}, {
"type" : "null"
} ]
},
"creator_id" : {
"type" : "integer"
},
"handlers" : {
"type" : "array",
"items" : {
"type" : "object",
"properties" : {
"active" : {
"oneOf" : [ {
"type" : "boolean"
}, {
"type" : "null"
} ]
},
"channel" : {
"oneOf" : [ {
"$ref" : "#/components/schemas/metabase.channel.models.channel.Channel"
}, {
"type" : "null"
} ]
},
"channel_id" : {
"oneOf" : [ {
"description" : "value must be an integer greater than zero.",
"type" : "integer",
"minimum" : 1
}, {
"type" : "null"
} ]
},
"channel_type" : { },
"notification_id" : {
"description" : "value must be an integer greater than zero.",
"type" : "integer",
"minimum" : 1
},
"recipients" : {
"type" : "array",
"items" : {
"$ref" : "#/components/schemas/metabase.notification.models.NotificationRecipient"
}
},
"template" : {
"oneOf" : [ {
"$ref" : "#/components/schemas/metabase.channel.models.channel.ChannelTemplateUserProvided"
}, {
"type" : "null"
} ]
},
"template_id" : {
"oneOf" : [ {
"description" : "value must be an integer greater than zero.",
"type" : "integer",
"minimum" : 1
}, {
"type" : "null"
} ]
}
},
"required" : [ "channel_type" ]
}
},
"payload" : {
"$ref" : "#/components/schemas/metabase.notification.models.NotificationCard"
},
"payload_id" : {
"type" : "integer"
},
"payload_type" : {
"type" : "string",
"enum" : [ "notification/dashboard", "notification/system-event", "notification/testing", "notification/card" ]
},
"subscriptions" : {
"type" : "array",
"items" : {
"$ref" : "#/components/schemas/metabase.notification.models.NotificationSubscription"
}
}
},
"required" : [ "payload_type", "payload" ]
}, {
"type" : "object",
"properties" : {
"creator" : {
"oneOf" : [ {
"type" : "object",
"properties" : { }
}, {
"type" : "null"
} ]
},
"creator_id" : {
"type" : "integer"
},
"handlers" : {
"type" : "array",
"items" : {
"type" : "object",
"properties" : {
"active" : {
"oneOf" : [ {
"type" : "boolean"
}, {
"type" : "null"
} ]
},
"channel" : {
"oneOf" : [ {
"$ref" : "#/components/schemas/metabase.channel.models.channel.Channel"
}, {
"type" : "null"
} ]
},
"channel_id" : {
"oneOf" : [ {
"description" : "value must be an integer greater than zero.",
"type" : "integer",
"minimum" : 1
}, {
"type" : "null"
} ]
},
"channel_type" : { },
"notification_id" : {
"description" : "value must be an integer greater than zero.",
"type" : "integer",
"minimum" : 1
},
"recipients" : {
"type" : "array",
"items" : {
"$ref" : "#/components/schemas/metabase.notification.models.NotificationRecipient"
}
},
"template" : {
"oneOf" : [ {
"$ref" : "#/components/schemas/metabase.channel.models.channel.ChannelTemplateUserProvided"
}, {
"type" : "null"
} ]
},
"template_id" : {
"oneOf" : [ {
"description" : "value must be an integer greater than zero.",
"type" : "integer",
"minimum" : 1
}, {
"type" : "null"
} ]
}
},
"required" : [ "channel_type" ]
}
},
"payload_id" : {
"type" : "integer"
},
"payload_type" : {
"type" : "string",
"enum" : [ "notification/dashboard", "notification/system-event", "notification/testing", "notification/card" ]
},
"subscriptions" : {
"type" : "array",
"items" : {
"$ref" : "#/components/schemas/metabase.notification.models.NotificationSubscription"
}
}
},
"required" : [ "payload_type" ]
} ]
}, {
"oneOf" : [ {
"type" : "object",
"properties" : {
"creator" : {
"oneOf" : [ {
"type" : "object",
"properties" : { }
}, {
"type" : "null"
} ]
},
"handlers" : {
"type" : "array",
"items" : {
"type" : "object",
"properties" : {
"active" : {
"oneOf" : [ {
"type" : "boolean"
}, {
"type" : "null"
} ]
},
"channel" : {
"oneOf" : [ {
"$ref" : "#/components/schemas/metabase.channel.models.channel.Channel"
}, {
"type" : "null"
} ]
},
"channel_id" : {
"oneOf" : [ {
"description" : "value must be an integer greater than zero.",
"type" : "integer",
"minimum" : 1
}, {
"type" : "null"
} ]
},
"channel_type" : { },
"notification_id" : {
"description" : "value must be an integer greater than zero.",
"type" : "integer",
"minimum" : 1
},
"recipients" : {
"type" : "array",
"items" : {
"$ref" : "#/components/schemas/metabase.notification.models.NotificationRecipient"
}
},
"template" : {
"oneOf" : [ {
"$ref" : "#/components/schemas/metabase.channel.models.channel.ChannelTemplateUserProvided"
}, {
"type" : "null"
} ]
},
"template_id" : {
"oneOf" : [ {
"description" : "value must be an integer greater than zero.",
"type" : "integer",
"minimum" : 1
}, {
"type" : "null"
} ]
}
},
"required" : [ "channel_type" ]
}
},
"payload" : {
"$ref" : "#/components/schemas/metabase.notification.models.NotificationCard"
},
"subscriptions" : {
"type" : "array",
"items" : {
"$ref" : "#/components/schemas/metabase.notification.models.NotificationSubscription"
}
}
},
"required" : [ "payload" ]
}, {
"type" : "object",
"properties" : {
"creator" : {
"oneOf" : [ {
"type" : "object",
"properties" : { }
}, {
"type" : "null"
} ]
},
"handlers" : {
"type" : "array",
"items" : {
"type" : "object",
"properties" : {
"active" : {
"oneOf" : [ {
"type" : "boolean"
}, {
"type" : "null"
} ]
},
"channel" : {
"oneOf" : [ {
"$ref" : "#/components/schemas/metabase.channel.models.channel.Channel"
}, {
"type" : "null"
} ]
},
"channel_id" : {
"oneOf" : [ {
"description" : "value must be an integer greater than zero.",
"type" : "integer",
"minimum" : 1
}, {
"type" : "null"
} ]
},
"channel_type" : { },
"notification_id" : {
"description" : "value must be an integer greater than zero.",
"type" : "integer",
"minimum" : 1
},
"recipients" : {
"type" : "array",
"items" : {
"$ref" : "#/components/schemas/metabase.notification.models.NotificationRecipient"
}
},
"template" : {
"oneOf" : [ {
"$ref" : "#/components/schemas/metabase.channel.models.channel.ChannelTemplateUserProvided"
}, {
"type" : "null"
} ]
},
"template_id" : {
"oneOf" : [ {
"description" : "value must be an integer greater than zero.",
"type" : "integer",
"minimum" : 1
}, {
"type" : "null"
} ]
}
},
"required" : [ "channel_type" ]
}
},
"subscriptions" : {
"type" : "array",
"items" : {
"$ref" : "#/components/schemas/metabase.notification.models.NotificationSubscription"
}
}
}
} ]
} ]
},
"metabase.notification.models.FullyHydratedNotification" : {
"description" : "Fully hydrated notification.",
"oneOf" : [ {
@@ -14007,6 +14652,36 @@
"type" : "string",
"enum" : [ "events" ]
},
"metabase.transforms-base.util.source-table-entry" : {
"description" : "A source table entry in the array format. Combines alias with table reference.",
"type" : "object",
"properties" : {
"alias" : {
"type" : "string"
},
"database_id" : {
"type" : "integer"
},
"schema" : {
"oneOf" : [ {
"type" : "string"
}, {
"type" : "null"
} ]
},
"table" : {
"type" : "string"
},
"table_id" : {
"oneOf" : [ {
"type" : "integer"
}, {
"type" : "null"
} ]
}
},
"required" : [ "alias" ]
},
"metabase.transforms-inspector.schema.alert-trigger" : {
"description" : "Definition for conditional alerts.\n FE evaluates condition against card results and shows alert if triggered.",
"type" : "object",
@@ -14548,41 +15223,6 @@
"$ref" : "#/components/schemas/metabase.transforms.schema.checkpoint-strategy"
} ]
},
"metabase.transforms.schema.source-table-ref" : {
"description" : "A reference to a source table by name, for cases where table_id may not exist yet.\n Also saves querying metadata in situations where we'll need the name.",
"type" : "object",
"properties" : {
"database_id" : {
"type" : "integer"
},
"schema" : {
"oneOf" : [ {
"type" : "string"
}, {
"type" : "null"
} ]
},
"table" : {
"type" : "string"
},
"table_id" : {
"oneOf" : [ {
"type" : "integer"
}, {
"type" : "null"
} ]
}
},
"required" : [ "database_id", "table" ]
},
"metabase.transforms.schema.source-table-value" : {
"description" : "Either a table ID (int) or a reference map.",
"anyOf" : [ {
"type" : "integer"
}, {
"$ref" : "#/components/schemas/metabase.transforms.schema.source-table-ref"
} ]
},
"metabase.transforms.schema.table-incremental-target" : {
"type" : "object",
"properties" : {
@@ -14690,9 +15330,9 @@
"$ref" : "#/components/schemas/metabase.transforms.schema.source-incremental-strategy"
},
"source-tables" : {
"type" : "object",
"additionalProperties" : {
"$ref" : "#/components/schemas/metabase.transforms.schema.source-table-value"
"type" : "array",
"items" : {
"$ref" : "#/components/schemas/metabase.transforms-base.util.source-table-entry"
}
},
"type" : {
@@ -36285,7 +36925,7 @@
"content" : {
"application/json" : {
"schema" : {
"$ref" : "#/components/schemas/metabase.notification.models.FullyHydratedNotification"
"$ref" : "#/components/schemas/metabase.notification.api.notification.NotificationApiInput"
}
}
}
@@ -36314,7 +36954,7 @@
"content" : {
"application/json" : {
"schema" : {
"$ref" : "#/components/schemas/metabase.notification.models.FullyHydratedNotification"
"$ref" : "#/components/schemas/metabase.notification.api.notification.NotificationApiInput"
}
}
}
@@ -36465,7 +37105,7 @@
"content" : {
"application/json" : {
"schema" : {
"$ref" : "#/components/schemas/metabase.notification.models.FullyHydratedNotification"
"$ref" : "#/components/schemas/metabase.notification.api.notification.NotificationApiInput"
}
}
}

View File

@@ -7,12 +7,15 @@ redirect_from:
- /docs/latest/embedding/whitelabeling
- /docs/latest/embedding/fonts
- /docs/latest/embedding/customize-embeds
summary: Configure colors, fonts, and illustrations in your Metabase.
---
# Appearance
{% include plans-blockquote.html feature="Custom appearance" %}
_Admin > Settings > Appearance_
Appearance settings give admins the option to whitelabel Metabase to match your company’s branding.
If you're looking for date, time, number, or currency formatting, see [Formatting defaults](../data-modeling/formatting.md).
@@ -23,37 +26,10 @@ Hit cmd/ctrl + k to bring up the command palette and search for "Branding" and c
You can also click the **grid** icon at the bottom of the navigation sidebar and click through **Admin** > **Settings** > **Appearance**.
Appearance settings are split across different tabs:
- [Branding](#branding)
- [Conceal Metabase](#conceal-metabase)
## Dark mode
People can display their Metabase in dark mode in their [account settings](../people-and-groups/account-settings.md#theme). Options are:
- System default (which is also the default setting). Metabase will switch between light and dark mode when the system switches without having to reload the page.
- Always use dark mode.
- Always use light mode.
You can quickly toggle dark mode from anywhere in Metabase by opening the [command palette](../exploration-and-organization/exploration.md#command-palette) and searching for "light" or "dark" or "theme".
Dark mode is a user-level setting, not an instance-level setting. Currently, there's no way to change the theme to dark mode for the entire instance, but you can edit some [user interface colors](#user-interface-colors).
## Branding
In the Branding tab, you can configure your Metabase to match your brand visuals and voice.
- [Color palette](#color-palette)
- [User interface colors](#user-interface-colors)
- [Chart colors](#chart-colors)
- [Logo](#logo)
- [Font](#font)
- [Loading message](#loading-message)
- [Favicon](#favicon)
## Color palette
_Admin > Settings > Appearance > Branding_
You can customize colors in both the application UI and in the Metabase charts.
### User interface colors
@@ -66,62 +42,93 @@ You can customize the colors that Metabase uses throughout the app:
- **Second color:** The color of aggregations and breakouts in the graphical query builder.
- **Third color:** Color of filters in the query builder, buttons and links in filter widgets.
![QB with custom colors](./images/qb-colors.png)
When choosing interface color, keep in mind that some users of your Metabase can choose to display the interface in [dark mode](../people-and-groups/account-settings.md#theme). Pick colors that work well both in light and dark mode.
### Chart colors
![Chart colors](./images/chart-colors.png)
You can choose up to 24 hex values. If you choose fewer than 24 colors, Metabase will auto-generate colors to fill in the rest of the values. The order of colors doesn't apply to the order of colors for series on charts. When building a chart, Metabase will select colors to make each series easy to distinguish.
Custom colors are unavailable for:
You can preview what the chart colors will look like by switching to the **Preview** tab.
![Preview chart](./images/preview.png)
Custom colors are **unavailable** for:
- [Number charts](../questions/visualizations/numbers.md)
- [Trend charts](../questions/visualizations/trend.md)
- [Funnel charts](../questions/visualizations/funnel.md)
- Conditional formatting ([tables](../questions/visualizations/table.md) and [pivot tables](../questions/visualizations/pivot-table.md))
- [Maps](../questions/visualizations/map.md)
- [Pin and grid maps](../questions/visualizations/map.md)
## Logo
Only a **limited subset** of custom colors will be used for:
- Conditional formatting in [tables](../questions/visualizations/table.md) and [pivot tables](../questions/visualizations/pivot-table.md)
- [Maps](../questions/visualizations/map.md)
- [Sunburst chart](../questions/visualizations/pie-or-donut-chart.md)
In most cases, replacing default colors with custom chart colors will not be applied to
## Icons
_Admin > Settings > Appearance > Branding_
### Logo
You can replace Metabase's familiar, tasteful, inspired-yet-not-threateningly-avant-garde dotted M logo with your very own logo. For things to work best, the logo you upload should be an SVG file that looks good when it's around 60px tall. (In other words, ask the nearest designer for help.)
### Favicon
The URL or image that you want to use as the favicon (the logo visible in browser tabs, address bars, bookmark lists, and other places).
If you use a relative path, that path isn't relative to the Metabase JAR, but to the webserver. So unless you're using a reverse-proxy, the path will be relative to the frontend resources available to the JAR.
## Dark mode
People can display their Metabase in dark mode in their [account settings](../people-and-groups/account-settings.md#theme). Options are:
- System default (which is also the default setting). Metabase will switch between light and dark mode when the system switches without having to reload the page.
- Always use dark mode.
- Always use light mode.
You can quickly toggle dark mode from anywhere in Metabase by opening the [command palette](../exploration-and-organization/exploration.md#command-palette) and searching for "light" or "dark" or "theme".
Dark mode is a user-level setting, not an instance-level setting. Currently, there's no way to change the theme to dark mode for the entire instance, but you can edit some [user interface colors](#user-interface-colors).
## Font
_Admin > Settings > Appearance > Branding_
This is the primary font used in charts and throughout the Metabase application (your "instance font"). See [Fonts](./fonts.md).
## Loading message
_Admin > Settings > Appearance > Branding_
This message is the text Metabase presents when it's loading a query. Options include:
- "Doing science..." (the default)
- "Running query..."
- "Loading results..."
## Favicon
## Names
The URL or image that you want to use as the favicon (the logo visible in browser tabs, address bars, bookmark lists, and other places).
_Admin > Settings > Appearance > Conceal Metabase_
If you use a relative path, that path isn't relative to the Metabase JAR, but to the webserver. So unless you're using a reverse-proxy, the path will be relative to the frontend resources available to the JAR.
## Conceal Metabase
Hide or customize pieces of the Metabase product to tailor the experience to your brand and needs.
- [Application name](#application-name)
- [Documentation and references](#documentation-and-references)
- [Help link in the settings menu](#help-link-in-the-settings-menu)
- [Metabase illustrations](#metabase-illustrations)
## Application name
### Application name
You can change every place in the app that says “Metabase” to something like “Acme Analytics,” or whatever you want to call your Metabase app.
## Documentation and references
Setting a custom application name will also hide the "How to use Metabase" section in the navigation.
Control the visibility of links to official Metabase documentation and other references to Metabase in your instance.
### Documentation and references
This setting affects all links in the product experience that point to Metabase.com URLs (with the exception of links and references in the Admin settings).
Control the visibility of links to official Metabase documentation and other references to Metabase in your instance outside of Admin settings.
## Help link in the settings menu
Keep in mind that if you hide documentation links, people using your Metabase might not be able to troubleshoot their problems or learn how to use Metabase features like [custom expressions](../questions/query-builder/expressions.md).
### Help link in the settings menu
The Settings menu (the "grid" menu in the upper right of your Metabase) includes a **Help** option that links to a [Metabase help page](https://www.metabase.com/help/) by default. You can change this menu Help item by selecting one of the following options:
@@ -131,6 +138,8 @@ The Settings menu (the "grid" menu in the upper right of your Metabase) includes
## Metabase illustrations
_Admin > Settings > Appearance > Conceal Metabase_
![Lighthouse illustration](./images/lighthouse-illustration.png)
Customize each of the illustrations in Metabase.

View File

@@ -2,13 +2,14 @@
title: Custom maps
redirect_from:
- /docs/latest/administration-guide/20-custom-maps
summary: Add custom region maps and customize the map tile server.
---
# Custom maps
By default, Metabase uses OpenStreetMaps for map visualizations, but there are a few customization options.
_Admin > Settings > Maps_
## Map settings
By default, Metabase uses OpenStreetMaps tiles for pin and grid map visualizations, and comes with two built-in region maps - world countries and US states. You can change the tiles used for pin and grid maps, and upload additional region maps.
To find the map settings:
@@ -22,7 +23,12 @@ To find the map settings:
By default, Metabase uses the [OpenStreetMaps](https://www.openstreetmap.org) tile server for pin and grid maps. If your organization requires a different
look or level of detail in your map visualizations, you can change the map tile server by adding the map tile server path to the first field on the page.
The path must either be a URL that starts with `http://` or `https://` or a relative path to a local file in the JVM's classpath.
To change the map tile server:
1. Go to **Admin > Settings > Maps**.
2. Under **Map tile server URL**, add the path to the new map tile server.
The path must either be a URL that starts with `http://` or `https://` or a relative path to a local file in the JVM's classpath.
Currently, Metabase uses a single tile server per instance. You can't specify different tiles for different maps.
@@ -32,6 +38,8 @@ Metabase comes with two built-in [region maps](../questions/visualizations/map.m
If you need a map of other regions - like EU countries or NYC neighborhoods - you can specify a GeoJSON file containing region information. You can often find GeoJSON maps by searching online for "[Your region] + geojson", like "NYC neighborhoods GeoJSON." Many community members and government organizations have already developed map files for common regions. You can also create your own GeoJSON with a tool like [MapShaper](https://mapshaper.org/) or [GeoJSON.io](https://geojson.io/).
### Custom geoJSON requirements
Your GeoJSON file should:
- Be less than 5 MB in size.
@@ -39,6 +47,8 @@ Your GeoJSON file should:
- Use geographic coordinates (latitude and longitude) to define region polygons. Metabase doesn't support projected coordinates, so you'll need to convert projected coordinates to geographic coordinates.
- Accessible by a public URL. Currently, you can't upload a GeoJSON to Metabase.
### Add a custom map
To add a custom map:
1. Click the **grid icon**, then go to **Admin** > **Settings** > **Maps** > **Custom Maps**.
@@ -47,11 +57,11 @@ To add a custom map:
4. Provide the URL to your GeoJSON file.
5. Specify the JSON properties that should serve as region identifier and region name.
![Uploading a custom GeoJSON](./images/custom-geojson.png)
![Uploading a custom GeoJSON](./images/custom-geojson.png)
- **Name of the map** will be displayed in the region selector for [custom region maps](../questions/visualizations/map.md#custom-regions)
- **Region's identifier** is a GeoJSON field that identifies your region. The values in this field should match how the regions are referenced in your data. The field does not need to match the display name .
- **Region's display name** is a GeoJSON field that specifies how your region name will be displayed on a map. This field can be different from region's identifier.
- **Name of the map** will be displayed in the region selector for [custom region maps](../questions/visualizations/map.md#custom-regions).
- **Region's identifier** is a GeoJSON field that identifies your region. The values in this field should match how the data refers to the regions. The field doesn't need to match the display name .
- **Region's display name** is a GeoJSON field that specifies how maps will display region names. This field can be different from region's identifier.
To pre-load one or more region maps when Metabase starts, you can use the environment variable [`MB_CUSTOM_GEOJSON`](./environment-variables.md#mb_custom_geojson) or a [config file option](./config-file.md) `custom-geojson` .

View File

@@ -11,7 +11,7 @@ Once you connect your database to Metabase, you'll want to configure an email ac
Both admins and people with [settings access](../permissions/application.md#settings-access) can set up email.
## Email on Metabase Cloud
## Set up email on Metabase Cloud
_Admin > Settings > Email_
@@ -57,47 +57,103 @@ When setting up a custom SMTP server on Metabase Cloud, you'll configure these f
- **SMTP USERNAME**: Your SMTP account username.
- **SMTP PASSWORD**: Your SMTP account password.
You'll also need to specify:
- **From address**: The email address you want to use for the sender of emails.
- **Reply-to address**: The email address you want replies to go to, if different from the From address.
Once you set up your SMTP, you'll be able to [Configure email settings](#configure-email-settings).
You can edit these settings at any time. You can also toggle between this custom SMTP server and the server managed by Metabase Cloud.
## Configuring your email account
## Set up email on self-hosted Metabases
_Admin > Settings > Email_
For Metabase to send messages to people, you'll need to set up an email account to send emails via **SMTP** (simple mail transfer protocol). SMTP is an email standard that, when combined with SSL/TLS, provides security protection for emails.
To start, go to the Admin Panel from the dropdown menu in the top right of Metabase, then from the Settings page, click on **Email** in the left menu.
If you're on Metabase Cloud, see [Set up email on Metabase Cloud](#set-up-email-on-metabase-cloud).
You should see this form:
To set up email on self-hosted Metabase:
![Email Credentials](images/EmailCredentials.png)
1. Go to **Admin > Settings > Email**.
2. Next to **Self-Hosted SMTP**, click **Configure**.
3. Specify the email configuration:
Here you'll set:
![Email Credentials](images/EmailCredentials.png)
- **SMTP HOST**: The address of the SMTP server that handles your emails.
- **SMTP PORT**: The port your SMTP server uses for outgoing emails.
- **SMTP SECURITY**:
- **SMTP Host**: The address of the SMTP server that handles your emails.
- **SMTP Port**: The port your SMTP server uses for outgoing emails.
- **SMTP Security**:
- None
- SSL
- TLS
- STARTTLS
- **SMTP USERNAME**: Your SMTP account username.
- **SMTP PASSWORD**: Your SMTP account password.
- **SMTP Username**: Your SMTP account username.
- **SMTP Password**: Your SMTP account password.
You'll also need to specify your:
3. Click **Save changes**.
## Configure email settings
_Admin > Settings > Email_
![email settings](./images/email-settings.png)
### Add From and Reply-to addresses
Once you set up your email, you can configure:
- **From Name**: The name you want to use for the sender of emails.
- **From address**: The email address you want to use for the sender of emails.
- **Reply-to address**: The email address you want replies to go to, if different from the From address.
## Add recipients as CC or BCC
### Add recipients as CC or BCC
By default, Metabase will hide email recipients by including them in the BCC list (Blind Carbon Copy) of the email. But if you're having issues with your email provider blocking emails with BCC recipients, and you don't mind having people see who else has been copied on the email Metabase sends them, you can tell Metabase to CC (Carbon Copy) recipients instead.
### Recommended email settings
To configure CC/BCC:
1. Go to **Admin > Settings > Email**
2. Under **Add recipients as CC or BCC**, select how you want Metabase to handle recipients.
### Approved domains for notifications
{% include plans-blockquote.html feature="Approved domains for notifications" %}
You can configure allowed email address domain(s) for new [dashboard subscriptions](../dashboards/subscriptions.md) and [alerts](../questions/alerts.md).
Adding approved domains allows you to restrict which email addresses people can send alerts and subscriptions to. This restriction only applies to sending email to people who lack an account with that Metabase. People with Metabase accounts who aren't [restricted by row or column security](../permissions/row-and-column-security.md) will be able to email any other person with an account in that same Metabase.
To configure allowed domains:
1. Go to **Admin > Settings > Email**
2. Under **Allowed domains for notifications**, add allowed domains:
- To allow all domains, leave the field empty (allowing all domains is the default).
- To specify multiple domains, separate each domain with a comma, with no space in between (e.g., `domain1,domain2`).
You can also set this property using the environment variable [`MB_SUBSCRIPTION_ALLOWED_DOMAINS`](../configuring-metabase/environment-variables.md#mb_subscription_allowed_domains).
> Changing this setting won't affect already existing subscriptions and alerts.
### Suggest recipients on dashboard subscriptions and alerts
{% include plans-blockquote.html feature="Configuring suggested recipients" %}
You can control which recipients people can see when they create a new [dashboard subscription](../dashboards/subscriptions.md) or [alert](../questions/alerts.md).
![Suggested recipients](./images/suggested-recipients.png)
For example, you may want to restrict people to viewing potential recipients that belong to the same [groups](../people-and-groups/managing.md#groups) they are a member of.
To configure suggested recipients for subscriptions and alerts:
1. Go to **Admin > Settings > Email**.
2. Under **Suggest recipients on dashboard subscriptions and alerts**, select one of the options:
- Suggest all users
- Only suggest users in the same groups
- Don't show suggestions
People with [row or column restrictions](../permissions/row-and-column-security.md) won't see suggestions.
## Email best practices
- SSL is strongly recommended because it's more secure and gives your account extra protection from threats.
- If your email service has a whitelist of email addresses that are allowed to send email, be sure to whitelist the email address that you put in the **From address** field to ensure you and your teammates receive all emails from Metabase.
@@ -110,11 +166,11 @@ By default, Metabase will hide email recipients by including them in the BCC lis
### Google Apps
1. In the **SMTP HOST** field, enter smtp.gmail.com
2. Fill in 465 for the **SMTP PORT** field
3. For the **SMTP SECURITY** field, enter **SSL**
4. In the **SMTP USERNAME** field, enter your Google Apps email address (e.g. hello@yourdomain.com)
5. Enter your Google Apps password in the **SMTP PASSWORD** field
1. In the **SMTP Host** field, enter `smtp.gmail.com`.
2. Fill in 465 for the **SMTP Port** field.
3. For the **SMTP Security**, select **SSL**.
4. In the **SMTP UsernameE** field, enter your Google Apps email address (e.g. `hello@yourdomain.com`).
5. Enter your Google Apps password in the **SMTP Password** field.
6. Enter the email address you would like to be used as the sender of system notifications in the **From address** field.
### Amazon SES
@@ -135,36 +191,6 @@ Check if [email quotas](https://docs.aws.amazon.com/ses/latest/dg/quotas.html) a
3. Although Mandrill lists **port 587**, [any port supported by Mandrill](https://mailchimp.com/developer/transactional/docs/smtp-integration/#the-basics) will work for SMTP email.
4. Now you can go back to the Metabase Admin Panel form and enter the info there.
## Approved domains for notifications
{% include plans-blockquote.html feature="Approved domains for notifications" %}
Allowed email address domain(s) for new [dashboard subscriptions](../dashboards/subscriptions.md) and [alerts](../questions/alerts.md).
Adding approved domains allows you to restrict which email addresses people can send alerts and subscriptions to. This restriction only applies to sending email to people who lack an account with that Metabase. People with Metabase accounts who aren't [restricted by row or column security](../permissions/row-and-column-security.md) will be able to email any other person with an account in that same Metabase.
To allow all domains, leave the field empty (allowing all domains is the default).
To specify multiple domains, separate each domain with a comma, with no space in between (e.g., "domain1,domain2").
You can also set this property using the environment variable [`MB_SUBSCRIPTION_ALLOWED_DOMAINS`](../configuring-metabase/environment-variables.md#mb_subscription_allowed_domains).
> This setting doesn't affect existing subscriptions and alerts.
## Suggest recipients on dashboard subscriptions and alerts
{% include plans-blockquote.html feature="Configuring suggested recipients" %}
Control which recipients people can see when they create a new [dashboard subscription](../dashboards/subscriptions.md) or [alert](../questions/alerts.md). For example, you may want to restrict people to viewing potential recipients that belong to the same [groups](../people-and-groups/managing.md#groups) they are a member of.
Options include:
- Suggest all users
- Only suggest users in the same groups
- Don't show suggestions
People with [row or column restrictions](../permissions/row-and-column-security.md) won't see suggestions.
## Further reading
- [Alerts](../questions/alerts.md)

View File

@@ -7,15 +7,21 @@ redirect_from:
# Fonts
{% include plans-blockquote.html feature="Customizable font" %}
{% include plans-blockquote.html feature="Customizable fonts" is_plural=true%}
On Pro and Enterprise plans, you can customize the font Metabase uses (the default is [Lato](https://fonts.google.com/specimen/Lato)). You can choose from a curated set of Google Fonts that accommodate the regular, bold, and heavy font weights that Metabase relies on for its various UI elements.
## Included fonts
![Font settings](./images/font-settings.png)
To change your Metabase font, click the **grid** icon in the upper right of the screen and select **Admin** > **Settings** > **Appearance**. Under **Font**, select from a list of included fonts.
## Configure fonts
To change your Metabase font:
1. Click the **grid** icon in the upper right of the screen.
2. Select **Admin**.
3. In Admin console, go to **Settings** > **Appearance** > **Branding**
4. Under **Font**, select from a list of included fonts:
- [Custom font](#custom-fonts)
- [Lato](https://fonts.google.com/specimen/Lato)
- [Lora](https://fonts.google.com/specimen/Lora)
- [Merriweather](https://fonts.google.com/specimen/Merriweather)
@@ -35,16 +41,23 @@ To change your Metabase font, click the **grid** icon in the upper right of the
- [Slabo 27px](https://fonts.google.com/specimen/Slabo+27px)
- Source Sans Pro
- [Ubuntu](https://fonts.google.com/specimen/Ubuntu)
- [Custom font](#add-custom-fonts)
Comic Sans is currently not included.
## Custom fonts
You can also upload your own custom font.
To set a custom font, click the **grid** icon in the upper right of the screen and select **Admin** > **Settings** > **Appearance**.
## Add custom fonts
For **Font**, select **Custom...** and enter URLs to your font files.
To set a custom font:
## Font style options
1. Click the **grid** icon in the upper right of the screen.
2. Select **Admin**.
3. In the Admin console, go to **Settings** > **Appearance** > **Branding**.
4. Under **Fonts**, click the dropdown and select **Custom...**
5. Enter URLs to your font files.
### Custom font style options
You can set three different font styles with three different URLs, one for each font style (size and weight) that Metabase will use to display its user interface properly. The font weights are:
@@ -60,7 +73,7 @@ For best results, set at least the 400 and 700 styles. If you have a single font
For custom fonts, Metabase supports woff, woff2, ttf files. If the URL you provide lacks a specific file extension, Metabase will assume it's a woff2 file.
## Google Font URLs
### Google Font URLs
To get a URL for a [Google Font](https://fonts.google.com/), visit the Google Font page and select the style you want to use. Then make an HTTP request to get the URL of the tff file. For example, say we want to use Roboto Mono: here's how we could get the font file URLs for both the 400 and 700 styles:
@@ -95,7 +108,7 @@ For latin text, we'd copy the relevant src URLs for each style, in this case:
And paste those URLS in the relevant input fields in **Admin** > **Settings** > **Appearance** > **Font** section where it says "Tell us where to find the file for each font weight. You don’t need to include all of them, but it’ll look better if you do."
## Hosting fonts on GitHub
### Hosting fonts on GitHub
If you host a font on GitHub, the font should be in a public repository, and you'll need to link to the raw font file(s) served from the raw.githubusercontent.com domain.
@@ -115,13 +128,13 @@ raw.githubusercontent.com/${user}/${repo}/${branch}/${path}
Note that in the raw link, there is no `/blob/` directory in the URL.
## Supporting multiple languages
### Supporting multiple languages
To support multiple character sets, for example both Latin and Cyrillic, you'll need to merge font files.
## Customizing the font for individual embedded items
When configuring [guest embeds](../embedding/guest-embedding.md), you can select from any of the [included fonts](#included-fonts). If you've set a custom font for your Metabase, you can also select "Use instance font" to use your custom font in the embed.
When configuring [guest embeds](../embedding/guest-embedding.md), you can select from any of the [included fonts](#configure-fonts). If you've set a custom font for your Metabase, you can also select "Use instance font" to use your custom font in the embed.
## Further reading

Binary file not shown.

Before

Width:  |  Height:  |  Size: 38 KiB

After

Width:  |  Height:  |  Size: 109 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 63 KiB

After

Width:  |  Height:  |  Size: 216 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 258 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 264 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 231 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 68 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 115 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 48 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 28 KiB

After

Width:  |  Height:  |  Size: 106 KiB

View File

@@ -6,15 +6,122 @@ redirect_from:
# Languages and localization
_Admin > Settings > Localization_
Admins can update the localization settings for the instance:
1. Click the **grid** icon in the upper right.
2. Click **Admin**.
2. Select **Admin**.
3. In the **Settings** tab, click on **Localization** in the left sidebar.
These localization settings allow you to set global language and formatting defaults for dates, times, numbers, and currencies.
You can also override these localization options for specific fields or questions. For more info, see [Formatting](../data-modeling/formatting.md).
People can also override these localization options for specific fields or questions. For more info, see [Formatting](../data-modeling/formatting.md).
## Instance settings
### Set default instance language
_Admin > Settings > Localization > Instance settings > Instance language_
You can set the default language (also called the "instance language") across your Metabase UI, system [emails](./email.md), [dashboard subscriptions](../dashboards/subscriptions.md), and [alerts](../questions/alerts.md).
People can override these settings in their personal [account settings](../people-and-groups/account-settings.md).
To set the instance-wider language:
1. Go to **Admin > Settings > Localization**.
2. Under **Instance language**, pick the language for your instance.
See [List of supported languages](#supported-languages). Some translations are created by the Metabase community, and might not be perfect.
### Set default instance report timezone
_Admin > Settings > Localization > Instance settings > Report timezone_
Use **report timezone** to set a default display time zone for dates and times in Metabase. The report timezone setting is a display setting only, so changing the report timezone won't affect the time zone of any data in your database.
Report timezone doesn't apply to `timestamp without time zone` data types, including the output of [`convertTimezone`](../questions/query-builder/expressions/converttimezone.md) expressions. For example:
| Raw timestamp in your database | Data type | Report time zone | Displayed as |
| ---------------------------------------- | ----------------------------- | ---------------- | ---------------------- |
| `2022-12-28T12:00:00 AT TIME ZONE 'CST'` | `timestamp with time zone` | 'Canada/Eastern' | Dec 28, 2022, 7:00 AM |
| `2022-12-28T12:00:00-06:00` | `timestamp with offset` | 'Canada/Eastern' | Dec 28, 2022, 7:00 AM |
| `2022-12-28T12:00:00` | `timestamp without time zone` | 'Canada/Eastern' | Dec 28, 2022, 12:00 AM |
Report timezone is only supported for the following databases:
- BigQuery
- Druid
- MySQL
- Oracle
- PostgreSQL
- Presto
- Redshift
- Vertica
To set report timezone:
1. Go to **Admin > Settings > Localization**.
2. Under **Report timezone**, pick the default report timezone.
### First day of the week
_Admin > Settings > Localization > Instance settings > First day of the week_
If you need to, you can change the first day of the week for your instance (the default is Sunday).
Setting the first day of the week affects how the [query builder](../questions/query-builder/editor.md) filters or groups by week. People can, however, use the `week` function to override this default when filtering or grouping by week of year. See [using a different first week of the year](../questions/query-builder/expressions/week.md#using-a-different-first-week-of-the-year).
This setting doesn't affect [SQL queries](../questions/native-editor/writing-sql.md).
## Dates and times display settings
You can configure the default formatting for dates and times.
Note that people can also override these localization options for specific fields or questions. For more info, see [Formatting](../data-modeling/formatting.md).
To configure default date and time format settings:
1. Go to **Admin > Settings > Localization**.
2. Under **Dates and times**, configure your settings:
- **Date style:** the way dates should be displayed in tables, axis labels, and tooltips.
- **Date separators:** you can choose between slashes (`2022/12/14`), dashes (`2022-12-14`), and dots (`2022.12.14`).
- **Abbreviate names of days and months:** whenever a date is displayed with the day of the week and/or the month written out, turning this setting on will display e.g. "January" as "Jan" or "Monday" as "Mon".
- **Time style:** choose to display the time using either a 12 or 24-hour clock (e.g., 3:00 PM or 15:00).
## Number display settings
_Admin > Settings > Localization_
Some people use commas to separate thousands places, and others use periods. You can configure which camp you belong to.
Note that people can also override these localization options for specific fields or questions. For more info, see [Formatting](../data-modeling/formatting.md).
To configure default separator settings:
1. Go to **Admin > Settings > Localization**.
2. Under **Number**, configure the **Separator style**.
## Currency display settings
_Admin > Settings > Localization_
You can choose how should currency fields be displayed by default (you can to configure _which_ fields should be displayed as currency in table metadata or in question formatting setting, see [Formatting](../data-modeling/formatting.md) )
Note that people can also override these localization options for specific fields or questions.
To configure default currency settings:
1. Go to **Admin > Settings > Localization**.
2. Under **Currency**, configure currency settings:
- **Unit of currency:** if you do most of your business in a particular currency, you can specify that here.
- **Currency label style:** whether you want to have your currencies labeled with a symbol, a code (like "USD"), or its full name.
## Localizing embedded Metabase
You can translate both Metabase UI elements (like button labels) and content (like dashboard names) in guest embeds. See [Setting the language for guest embeds](../embedding/guest-embedding.md) and [Translating embedded dashboards and questions](../embedding/translations.md).
## Supported languages
@@ -78,65 +185,3 @@ Note that while we only remove languages in major releases, we are happy to add
### Contributing to translations for Metabase
If you'd like to help make Metabase available in a language you're fluent in, we'd love your help! Check out our [Crowdin project](https://crowdin.com/project/metabase-i18n).
## Instance settings
### Instance language
Here you can set the default language (also called the "instance language") across your Metabase UI, system [emails](./email.md), [dashboard subscriptions](../dashboards/subscriptions.md), and [alerts](../questions/alerts.md).
People can override these settings in their personal [account settings](../people-and-groups/account-settings.md).
Some translations are created by the Metabase community, and might not be perfect.
### Report timezone
Use **report timezone** to set a default display time zone for dates and times in Metabase. The report timezone setting is a display setting only, so changing the report timezone won't affect the time zone of any data in your database.
Report timezone doesn't apply to `timestamp without time zone` data types, including the output of [`convertTimezone`](../questions/query-builder/expressions/converttimezone.md) expressions. For example:
| Raw timestamp in your database | Data type | Report time zone | Displayed as |
| ---------------------------------------- | ----------------------------- | ---------------- | ---------------------- |
| `2022-12-28T12:00:00 AT TIME ZONE 'CST'` | `timestamp with time zone` | 'Canada/Eastern' | Dec 28, 2022, 7:00 AM |
| `2022-12-28T12:00:00-06:00` | `timestamp with offset` | 'Canada/Eastern' | Dec 28, 2022, 7:00 AM |
| `2022-12-28T12:00:00` | `timestamp without time zone` | 'Canada/Eastern' | Dec 28, 2022, 12:00 AM |
Report timezone is only supported for the following databases:
- BigQuery
- Druid
- MySQL
- Oracle
- PostgreSQL
- Presto
- Redshift
- Vertica
### First day of the week
If you need to, you can change the first day of the week for your instance (the default is Sunday).
Setting the first day of the week affects how the [query builder](../questions/query-builder/editor.md) filters or groups by week. People can, however, use the `week` function to override this default when filtering or grouping by week of year. See [using a different first week of the year](../questions/query-builder/expressions/week.md#using-a-different-first-week-of-the-year).
This setting doesn't affect [SQL queries](../questions/native-editor/writing-sql.md).
## Dates and times
- **Date style:** the way dates should be displayed in tables, axis labels, and tooltips.
- **Date separators:** you can choose between slashes (`2022/12/14`), dashes (`2022-12-14`), and dots (`2022.12.14`).
- **Abbreviate names of days and months:** whenever a date is displayed with the day of the week and/or the month written out, turning this setting on will display e.g. "January" as "Jan" or "Monday" as "Mon".
- **Time style:** choose to display the time using either a 12 or 24-hour clock (e.g., 3:00 PM or 15:00).
## Numbers
- **Separator style:** some people use commas to separate thousands places, and others use periods. Here's where you can indicate which camp you belong to.
## Currency
- **Unit of currency:** if you do most of your business in a particular currency, you can specify that here.
- **Currency label style:** whether you want to have your currencies labeled with a symbol, a code (like "USD"), or its full name.
- **Where to display the unit of currency:** this pertains specifically to tables, and lets you choose whether you want the currency labels to appear only in the column heading, or next to each value in the column.
## Localizing embedded Metabase
You can translate both Metabase UI elements (like button labels) and content (like dashboard names) in guest embeds. See [Setting the language for guest embeds](../embedding/guest-embedding.md) and [Translating embedded dashboards and questions](../embedding/translations.md).

View File

@@ -21,20 +21,25 @@ See [How to read logs](../troubleshooting-guide/server-logs.md).
## Configuring logging Level
Metabase uses [log4j](https://logging.apache.org/log4j/2.x/)for logging configuration. Here is Metabase's [default logging configuration](https://github.com/metabase/metabase/blob/master/resources/log4j2.xml). Some troubleshooting tasks might require you to override this logging configuration (for example, to see more details about errors). See Log4j's docs for info on [log levels](https://logging.apache.org/log4j/2.x/manual/customloglevels.html).
Metabase uses [Log4j](https://logging.apache.org/log4j/2.x/) for logging configuration. Here is Metabase's [default logging configuration](https://github.com/metabase/metabase/blob/master/resources/log4j2.xml). Some troubleshooting tasks might require you to override this logging configuration (for example, to see more details about errors). See Log4j's docs for info on [log levels](https://logging.apache.org/log4j/2.x/manual/customloglevels.html).
### Temporary override logging configuration
To temporarily adjust the logging configuration, go to **Admin** > **Tools** > **Logs** and click on **Customize log levels**.
_Admin > Tools > Logs_.
You can select from log level presets for common troubleshooting tasks (for example, troubleshooting sync issues), or provide your own configuration as a JSON. For example, here's an override configuration that increases logging for troubleshooting linked filters:
To temporarily adjust the logging configuration:
```json
{
"metabase.parameters.chain-filter": "debug",
"metabase.parameters.chain-filter.dedupe-joins": "debug"
}
```
1. Go to **Admin** > **Tools** > **Logs**.
2. Click on **Customize log levels** above the logs.
You can select from log-level presets for common troubleshooting tasks (for example, troubleshooting sync issues), or provide your own configuration as JSON. For example, here's an override configuration that increases logging for troubleshooting linked filters:
```json
{
"metabase.parameters.chain-filter": "debug",
"metabase.parameters.chain-filter.dedupe-joins": "debug"
}
```
The override from Admin settings will be temporary. You can select for how long the override should be in place (e.g., 60 minutes). When the override times out, the logging configuration will revert to the default logging configuration (or a custom configuration if you're using a [custom log file](#use-a-custom-log-configuration-file)).

View File

@@ -6,10 +6,12 @@ redirect_from:
# General settings
This section contains settings for your whole instance, like its URL, the reporting timezone, and toggles for disabling or enabling some of Metabase's optional features.
_Admin > Settings > Feneral_
This section contains settings for your whole instance, like its URL, the reporting timezone, and toggles for disabling or enabling some of Metabase's optional features.
You can configure these settings by clicking the **grid icon** in the upper right, then going to **Admin** > **Settings** > **General**.
## Site name
How you’d like to refer to this instance of Metabase.
@@ -18,13 +20,7 @@ How you’d like to refer to this instance of Metabase.
The site URL is the web address that people use to access your Metabase instance. Make sure to include `http://` or `https://` to make sure it’s reachable. This feature is only available for self-hosted Metabases. For customers on Metabase Cloud, check out [Custom domains](../cloud/custom-domain.md).
## Custom homepage
Admins can pick a dashboard to serve as the homepage. If people lack permissions to view the selected dashboard, Metabase will redirect them to the default homepage.
If you've set a dashboard as your homepage, and want to revert to the default Metabase homepage, simply turn off the **Enabled** toggle to disable the Custom Homepage feature.
## Redirect to HTTPS
### Redirect to HTTPS
By default, Metabase is served over HTTP.
@@ -34,13 +30,19 @@ For example, say you enable HTTPS redirect for a Metabase instance at the site U
> Note: if you haven't set up HTTPS on your server, Metabase will not let you enable HTTPS redirect. Instead, you'll get a warning saying "It looks like HTTPS is not properly configured."
## Custom homepage
Admins can pick a dashboard to serve as the homepage. If people lack permissions to view the selected dashboard, Metabase will redirect them to the default homepage.
To revert to the default Metabase homepage, simply toggle off Custom homepage.
## Email address for help requests
This email address will be displayed in various messages throughout Metabase when users encounter a scenario where they need assistance from an admin, such as a password reset request.
## Anonymous tracking
This option turns determines whether or not you allow [anonymous data about your usage of Metabase](../installation-and-operation/information-collection.md) to be sent back to us to help us improve the product. [Your database’s data is never tracked or sent](https://www.metabase.com/security).
On self-hosted Metabases, this option turns determines whether or not you allow [anonymous data about your usage of Metabase](../installation-and-operation/information-collection.md) to be sent back to us to help us improve the product. [Your database’s data is never tracked or sent](https://www.metabase.com/security).
## Friendly table and field names

View File

@@ -6,7 +6,9 @@ redirect_from:
# Set up Slack
If you want to have your [dashboard subscriptions](../dashboards/subscriptions.md) or [alerts](../questions/alerts.md) sent to Slack channels (or people on Slack), an admin must first integrate your Metabase with Slack.
_Admin > Settings > Notification channels > Slack_
If you want to have your [dashboard subscriptions](../dashboards/subscriptions.md) or [alerts](../questions/alerts.md) sent to Slack channels (or people on Slack), you need to first integrate your Metabase with Slack.
Both admins and people with [settings access](../permissions/application.md#settings-access) can set up Slack.
@@ -14,84 +16,88 @@ Both admins and people with [settings access](../permissions/application.md#sett
For Metabase to post to your Slack channels, you’ll need to create a Slack App and make it available to Metabase.
From any Metabase page, go to **Admin** > **Settings** > **Notification channels** > **Slack**.
1. In Metabase, go to **Admin > Settings > Notification channels**.
2. Click **Connect to Slack**.
3. Click **Create a Slack App**. Metabase will open a new tab with the Slack website.
4. On the Slack website, click **Create an App**.
5. Pick a workspace to develop your app.
6. You may get a warning that says **This app is created from a 3rd party manifest. Always verify URLs and permissions below.**
Click on **Open Slack Apps**. Metabase will open a new browser tab and send you over to the Slack website to create the Slack app.
This warning is expected (Metabase is the third party here). You can click on **Edit configurations** to see the app manifest Metabase sent along in the URL. Here is the manifest in YAML format:
On the Slack website, click **Create an App**.
```yml
_metadata:
major_version: 1
minor_version: 1
display_information:
name: Metabase
description: Bringing the power of Metabase to your Slack #channels!
background_color: "#509EE3"
features:
bot_user:
display_name: Metabase
oauth_config:
scopes:
bot:
- users:read
- channels:read
- channels:join
- files:write
- chat:write
- chat:write.customize
- chat:write.public
- groups:read
```
### Pick a workspace to develop your app
The manifest just take cares of some settings for your app and helps speed things along.
Select the workspace you want to create your app.
### The app manifest
When you click on **Open Slack App**, Metabase will pass along the app manifest, which Slack will use to set up your app.
You may get a warning that says:
**This app is created from a 3rd party manifest** Always verify URLs and permissions below.
This warning is expected (Metabase is the third party here). You can click on **Configure** to see the app manifest Metabase sent along in the URL. Here is the manifest in YAML format:
```yml
_metadata:
major_version: 1
minor_version: 1
display_information:
name: Metabase
description: Bringing the power of Metabase to your Slack #channels!
background_color: "#509EE3"
features:
bot_user:
display_name: Metabase
oauth_config:
scopes:
bot:
- users:read
- channels:read
- channels:join
- files:write
- chat:write
- chat:write.customize
- chat:write.public
- groups:read
```
The manifest just take cares of some settings for your app and helps speed things along.
Click the **Next** button. Then hit **Create** to set up your Slack app.
7. Click the **Next** button. Then hit **Create** to set up your Slack app.
## Install your app to your workspace
On the Slack site for your newly created app, in the **Settings** > **Basic Information** tab, under **Install your app**, click on **Install to workspace**. On the next screen, click **Allow** to give Metabase access to your Slack workspace.
1. On the Slack site for your newly created app, go to **Settings** > **Basic Information** tab
2. Under **Install your app**, click on **Install to workspace**.
3. On the next screen, click **Allow** to give Metabase access to your Slack workspace.
## The Bot User OAuth Token
## Configure your app in Metabase
On the Slack site page for your Slack app, on the left in the **Features** section, click on **OAuth and Permissions** in the Slack Apps sidebar and then copy the **Bot User OAuth Token**. Return to the Slack settings page in your Metabase and paste this token in the Metabase field with the same name.
Once you [created the app](#create-your-slack-app) and [installed it in your workspace](#install-your-app-to-your-workspace), you tell Metabase to use it by giving Metabase the OAuth token for the app.
## Save your changes in Metabase
To obtain the OAuth token for the Slack aopp:
In Metabase, click on the **Save changes** button and that’s it! Metabase will automatically run a quick test to check that the API token is working properly. If something goes wrong, it'll give you an error message.
1. Go to the Slack site page for your Slack app.
2. On the Slack page for your app, go to **OAuth & Permissions** in the left sidebar.
3. On the **OAuth & Permissions** page for your Slack app, copy the **Bot User OAuth Token**.
To set up the app in Metabase:
1. In Metabase, go to **Admin > Settings > Notification channels > Slack**. Click **Connect to Slack**.
2. Paste the token into **Slack bot user OAuth token**.
3. **Save changes** in Metabase.
Metabase will automatically run a quick test to check that the API token is working properly. If something goes wrong, it'll give you an error message.
## Sending alerts and subscriptions to private Slack channels
In order to send subscriptions and alerts to private Slack channels, you must first add the Metabase app to the private channel.
In order to send [subscriptions](../dashboards/subscriptions.md) and [alerts](../questions/alerts.md) to private Slack channels, you must first add the Metabase app to the private channel.
In Slack, go to the private channel and mention the Metabase app. For example, if you called your Slack app "Metabase", you'd just type `@Metabase`. Slack will ask you if you want to invite your app to your channel, which you should.
To add your app to a private Slack channel:
### Metabase not listing your private channel?
1. In Slack, go to the private channel and mention the Metabase app. For example, if you called your Slack app "Metabase", you'd just type `@Metabase`.
It can take a little time for metabase to see all the channels the app has been invited to. New channels may not appear in listings for up to 10 minutes after inviting the app to the channel.
2. Slack will ask you if you want to invite your app to your channel, which you should.
In order for metabase to see private channels, the app must have the `groups:read` oauth scope. Although this scope should be granted when setting up the app through metabase, older installations might not have this scope.
If you think this might be the case [visit the app settings in slack](https://api.slack.com/apps/):
Once you added the app to a private channel, you should see the channel in the list of channels when setting up a subscription or alerts within 10 mins (it can take a little time for Metabase to see all the channels the app has been invited to).
- Click on the metabase app in the app listing.
- Click on **OAuth & Permissions** in the sidebar.
- Under **Scopes** add the `groups:read` scope.
- The app will the need to be reinstalled to the workspace
by clicking the **Reinstall** button under **OAuth Tokens**.
In order for metabase to see private channels, the app must have the `groups:read` OAuth scope. Although this scope should be granted when setting up the app through Metabase, older installations might not have this scope.
To check or edit your OAuth settings:
1. [Visit the app settings in slack](https://api.slack.com/apps/):
2. Click on the Metabase app in the list of apps.
3. Go to **OAuth & Permissions** in the sidebar.
4. Under **Scopes**, add the `groups:read` scope if it's not added already.
5. Reinstall the app by clicking the **Reinstall** button under **OAuth Tokens**.
## Further reading

View File

@@ -39,7 +39,7 @@ You can make your database columns time zone aware by storing them as specific d
The exact data type will depend on your database. Some Metabase features only work with specific data types:
- [Report timezone setting](../configuring-metabase/localization.md#report-timezone)
- [Report timezone setting](../configuring-metabase/localization.md#set-default-instance-report-timezone)
- [`converttimezone` custom expression](../questions/query-builder/expressions/converttimezone.md)
## Common pitfalls

View File

@@ -11,25 +11,27 @@ Only admins and people with settings access can send alerts to webhooks.
For now, webhooks are only available for [alerts](../questions/alerts.md); you can't select a webhook as the recipient of a [dashboard subscription](../dashboards/subscriptions.md).
## Creating a webhook
## Create a webhook
Before you can send an alert to a webhook, an admin will need to create a webhook to target.
_Admin > Settings > Notification channels_
Admins and people with [settings access](../permissions/application.md#settings-access) can create a webhook by clicking the **grid icon** > **Admin** > **Notification channels**. In **Webhooks for alerts**, click **+ Add another**. Metabase will show you a short form to fill out:
Before people can send alerts to a webhook, an admin or someone with [settings access](../permissions/application.md#settings-access) will need to create a webhook to target.
- **Webhook URL**. Where you want Metabase to send the results of an alert. Must be a valid URL.
- **Give it a name**. Name the webhook so that people can pick the right hook when setting up an alert on a question.
- **Description**. Tell people what the hook is for.
- **Authentication method**. See below.
To create a webhook:
## Webhook authentication method
1. Click the **grid** icon in top right corner and select **Admin**.
2. In the Admin console, go **Settings > Notification channels**.
3. In **Webhooks for alerts**, click **Add a webhoor**.
4. Metabase will show you a short form to fill out:
You can specify an auth method for the webhook.
- **None**: Anything goes.
- **Basic**: Set a username and password.
- **Bearer**: Include a [secret token](https://datatracker.ietf.org/doc/html/rfc6750).
- **API key**: You can add the API key to the Header or as a Query param. Both approaches require a key and value (the API key itself).
- **Webhook URL**. Where you want Metabase to send the results of an alert. Must be a valid URL.
- **Give it a name**. Name the webhook so that people can pick the right hook when setting up an alert on a question.
- **Description**. Tell people what the hook is for.
- **Authentication method**:
- **None**: Anything goes.
- **Basic**: Set a username and password.
- **Bearer**: Include a [secret token](https://datatracker.ietf.org/doc/html/rfc6750).
- **API key**: You can add the API key to the Header or as a Query param. Both approaches require a key and value (the API key itself).
## Webhook payload

View File

@@ -4,52 +4,52 @@ title: Actions on dashboards
# Actions on dashboards
You can add buttons to dashboards to perform [actions](../actions/start.md) like creating or updating records, and combine them with dashboard [filter](./filters.md).
![Dashboard with filter, action button, and detail card view](./images/dashboard-filter-action.png)
To put [actions](../actions/start.md) in action, you can combine them with a [model](../data-modeling/models.md) and a [filter](./filters.md) on a dashboard.
## Create an action
## Adding an action to a dashboard
To add an action button to a dashboard, you'll first need to create an action on a model. See [Model actions](../actions/introduction.md).
Visit a dashboard page and click on the **pencil** icon, then click on the **box with a mouse pointer** to add an action.
## Add an action button to a dashboard
Metabase will add an action button to the dashboard grid, and open a sidebar with the buttons settings.
Once you [created an action](../actions/introduction.md), you can add a button to a dashboard to perform that action:
### Button text
1. Visit a dashboard page and click the **pencil** icon to start editing the dashboard.
2. Click on the **box with a mouse pointer** to add an action.
A label explaining what the button does, e.g., "Ignition".
Metabase will add an action button to the dashboard grid, and open a sidebar with button settings:
### Button variant
- **Button text**: A label explaining what the button does, e.g., "Add record".
- **Button variant**: How a button looks. You can select from a variety of handsome buttons:
You can select from a variety of handsome buttons:
![Button types](./images/buttons.png)
- Primary
- Outline
- Danger
- Success
- Borderless
3. Pick an action to connect to the button.
4. For every field in the action, select whether people should supply the value themselves, or whether the action should use the value from the dashboard filter. See [Connecting an action to a dashboard filter](#connect-an-action-to-a-dashboard-filter).
5. Click **Done**, and **Save** the dashboard.
![Button types](./images/buttons.png)
## Connecting an action to a dashboard filter
For most actions, when people click on a button, they'll be prompted to input values in the fields defined by that action.
Many types of actions rely on knowing the Entity ID for the model to determine which records to update or delete. To have people select the ID for the action, you'll need to:
1. Click on the pencil icon to edit the dashboard.
2. Add an action to the dashboard (if you haven't already).
3. [Add a filter](./filters.md) to a dashboard, wire it up to any cards that you want to, and click **Done** in the bottom of the sidebar.
4. Hover over the action button and click on the **gear** icon, and select **Change action**.
5. Click on the field's dropdown to select where the action should get it's value. Here you can select "Ask the user" or have it automatically populated by a dashboard filter. In this case, we'll select our "ID" filter.
![Wiring up an action button to a dashboard filter](./images/id-value.png)
If you also wire that filter up to a card with a model on the dashboard, you can filter for individual records in that model, view them in the model's card, and have the action buttons auto-populate the id.
People viewing the dashboard will be able to click the button and perform your chosen action:
![Button form](./images/button-form.png)
You can add as many buttons as you want, and wire them up to one or more filters.
## Connect an action to a dashboard filter
When people click the action button on a dashboard, they'll be prompted to input values in the fields defined by that action. Alternatively, you can pre-fill some action fields with the values selected for a dashboard filter. Passing filter values to action fields is useful when the dashboard filters by an ID, and you want the action button to update the record associated with that ID.
To connect an action field to a filter on a dashboard:
1. On a dashboard with an action button, click the **pencil icon** edit the dashboard.
2. [Add a filter](./filters.md) to a dashboard, connect the filter to one or more cards, and click **Done** in the bottom of the sidebar.
3. [Add an action button to the dashboard](#add-an-action-button-to-a-dashboard) (if you haven't already).
4. Hover over the action button and click on the **gear** icon, and select **Change action**.
5. Click the field's dropdown to select where the action should get its value, and pick a filter to connect to (filters will be referenced in the dropdown by their name):
![Wiring up an action button to a dashboard filter](./images/id-value.png)
## Actions are unavailable for public dashboards and dashboards in guest embeds
While you can add actions to dashboards and use them in your Metabase, actions won't work on dashboards accessed via [public links](./introduction.md#sharing-dashboards-with-public-links), or dashboards in guest embeds.
@@ -59,3 +59,4 @@ If you want people outside of your Metabase to use an action, you can create a [
## Further reading
- [Actions](../actions/start.md)
- [Editable tables](../data-modeling/editable-tables.md)

View File

@@ -13,7 +13,7 @@ Instead of creating duplicate dashboards to show different cuts of the same data
## Filter and parameter widgets
There are two basic types of widgets you can add. The type of filter or parameter widget you choose determines how the widget works, including which fields you can connect to the widget.
There are two basic types of widgets you can add: filters or parameters. The type of filter or parameter widget you choose determines how the widget works, including which fields you can connect to the widget.
### Filter widgets
@@ -32,11 +32,32 @@ There are two basic types of widgets you can add. The type of filter or paramete
- [Time grouping](#time-grouping-parameter)
## Adding a filter or parameter widget
## Dashboard, header, and card widgets
You can add widgets to the whole dashboard, to headers, or to individual dashboard cards.
![Filter location](./images/filter-location.png)
- **Dashboard-level widgets** can connect to cards on the entire dashboard, across all tabs.
- **Header-level widgets** can only be connected to cards on the same tab.
- **Card-level widgets** can only be connected to their individual cards.
By default, prefer dashboard-level widgets.
If, however, your dashboard grows larger, and it doesn't make sense to break the dashboard up into multiple dashboards, you can add widgets to headings and cards so people can filter in place as they scroll through sections. In these cases, you should scope the effects of a heading widget to the section immediately below.
If you want tab-specific widgets, you could either:
- Use a dashboard widget, but only connect the widget to cards on a specific tab. The dashboard widgets will only be visible when people select the tab.
- Use a header widget.
These are just rules of thumb to keep the user experience predictable. Do whatever works for your use case.
## Add a filter or parameter to a dashboard
![Add a Filter](./images/add-filter.png)
1. Click the **pencil icon** to enter dashboard editing mode.
1. While viewing a dashboard, click the **pencil icon** to enter dashboard editing mode.
2. You can add a filter or parameter widget to:
- **The whole dashboard**. You'll need to connect these dashboard-level filters to individual cards. Metabase will only display dashboard-level widgets if they're connected to a card on the current tab.
@@ -47,25 +68,14 @@ There are two basic types of widgets you can add. The type of filter or paramete
3. Select a [filter type](#filter-and-parameter-widgets).
4. [Connect your filter or parameter widget to one or more dashboard cards](#connecting-a-filter-or-parameter-widget-to-dashboard-cards). Only dashboard-level widgets can be connected to cards on multiple tabs.
5. [Configure your filter](#editing-a-filter).
5. [Configure your filter](#configure-dashboard-filters-and-parameters).
6. **Save** your changes.
If the filter isn't connected to any of the cards on the current tab, Metabase won't display the filter.
### When to add a widget to a heading or card
## Filter types
These are just rules of thumb to keep the user experience predictable. Do whatever works for your use case.
By default, you should add widgets to the dashboard itself.
If, however, your dashboard grows larger, and it doesn't make sense to break the dashboard up into multiple dashboards, you can add widgets to headings and cards so people can filter in place as they scroll through sections. In these cases, you should scope the effects of a heading widget to the section immediately below. Filters on cards should generally only update the card itself.
If you want tab-specific widgets, you could either:
- Add them to the dashboard itself, but only connect the widget to cards on a specific tab.
- Use a heading filter.
## Date picker filters
### Date picker filters
When picking a Date picker filter, Metabase will prompt you to pick an operator:
@@ -78,13 +88,68 @@ When picking a Date picker filter, Metabase will prompt you to pick an operator:
Single Date and Date Range will provide a calendar widget, while the other options provide slightly different dropdown interfaces for picking values. To get a widget that's just like the date picker in the query builder, choose "All Options".
### Issues with connecting to a date variable
#### Issues with connecting to a date variable
If you get a message like "A date variable in this card can only be connected to a time type with the Single date option," you can handle it in a couple of ways.
If you get a message like "A date variable in this card can only be connected to a time type with the Single date option," it's probably because you're connecting your filter to a [basic variable](../questions/native-editor/basic-sql-parameters.md) (and not a field filter) in a native query. You can handle this scenario in a couple of ways:
- **If you want a date picker where people can select multiple dates**, you'll need to change the variable in your SQL code to a [field filter](../questions/native-editor/field-filters.md).
- **If you want the filter widget to just take a single date**, you'll need to change the dashboard filter widget's type to "Single date".
### Location filters
There are four types of Location filters to choose from.
- City
- State
- ZIP or Postal Code
- Country
Additionally, you can select an operator for the location filter:
- **Is**. Select one or more values from a list or search box. Use **Is** when you just want to plug a value into a variable. For multiple values, the card must be either a question built using the query builder, a native/SQL question using a [field filter](../questions/native-editor/field-filters.md), or a basic variable set to accept [multiple values](../questions/native-editor/basic-sql-parameters.md#basic-variable-that-allows-people-to-select-multiple-values).
- **Is not**. Exclude one or more specific values.
- **Contains**. Match values that contain the entered text.
- **Does not contain**. Filter out values that contain the entered text.
- **Starts with**. Match values that begin with the entered text.
- **Ends with**. Match values that end with the entered text.
### ID filter
The ID filter provides a simple input box where you can type the ID of a user, order, and so on.
You can give people the option to pick one value or multiple values.
### Number filter
You can choose from:
- Equal to
- Not equal to
- Between
- Greater than or equal to
- Less than or equal to
### Text or category filter
A flexible filter type that lets you create either a dropdown menu or an input box to filter on any text or category field in your cards. Options include:
- **Is**. Select one or more values from a list or search box. Use **Is** when you just want to plug a value into a variable. For multiple values, the card must be a question built using the query builder, a native/SQL question using a [field filter](../questions/native-editor/field-filters.md), or a basic variable set to [multiple values](../questions/native-editor/basic-sql-parameters.md#basic-variable-that-allows-people-to-select-multiple-values).
- **Is not**. Exclude one or more specific values.
- **Contains**. Match values that contain the entered text.
- **Does not contain**. Filter out values that contain the entered text.
- **Starts with**. Match values that begin with the entered text.
- **Ends with**. Match values that end with the entered text.
You can also select how people should filter on this column:
- Dropdown list
- Search box
- Input box
### Boolean filter
A boolean filter allows people to filter data based on true/false values.
## Time grouping parameter
![Time grouping](./images/time-grouping.png)
@@ -105,61 +170,6 @@ Grouping options include:
To connect a time grouping widget to a SQL question, you'll need to insert time grouping parameters in your code. See [time grouping parameters](../questions/native-editor/time-grouping-parameters.md).
## Location filters
There are four types of Location filters to choose from.
- City
- State
- ZIP or Postal Code
- Country
Additionally, you can select an operator for the location filter:
- **Is**. Select one or more values from a list or search box. Use **Is** when you just want to plug a value into a variable. For multiple values, the card must be either a question built using the query builder, a native/SQL question using a [field filter](../questions/native-editor/field-filters.md), or a basic variable set to accept [multiple values](../questions/native-editor/basic-sql-parameters.md#basic-variable-that-allows-people-to-select-multiple-values).
- **Is not**. Exclude one or more specific values.
- **Contains**. Match values that contain the entered text.
- **Does not contain**. Filter out values that contain the entered text.
- **Starts with**. Match values that begin with the entered text.
- **Ends with**. Match values that end with the entered text.
## ID filter
The ID filter provides a simple input box where you can type the ID of a user, order, and so on.
You can give people the option to pick one value or multiple values.
## Number filter
You can choose from:
- Equal to
- Not equal to
- Between
- Greater than or equal to
- Less than or equal to
## Text or category filter
A flexible filter type that lets you create either a dropdown menu or an input box to filter on any text or category field in your cards. Options include:
- **Is**. Select one or more values from a list or search box. Use **Is** when you just want to plug a value into a variable. For multiple values, the card must be a question built using the query builder, a native/SQL question using a [field filter](../questions/native-editor/field-filters.md), or a basic variable set to [multiple values](../questions/native-editor/basic-sql-parameters.md#basic-variable-that-allows-people-to-select-multiple-values).
- **Is not**. Exclude one or more specific values.
- **Contains**. Match values that contain the entered text.
- **Does not contain**. Filter out values that contain the entered text.
- **Starts with**. Match values that begin with the entered text.
- **Ends with**. Match values that end with the entered text.
You can also select how people should filter on this column:
- Dropdown list
- Search box
- Input box
## Boolean filter
A boolean filter allows people to filter data based on true/false values.
## Connecting a filter or parameter widget to dashboard cards
For each widget that you add, you'll need to tell Metabase which column the filter should update for each card.
@@ -177,13 +187,7 @@ Which cards you can connect a filter or parameter widget to depends on:
For cards built in the query builder, _filters_ can be connected to fields at any stage of the query. _Time grouping parameters_ can only be connected to fields in the last stage of the query, and so to make use of time grouping parameters, your query should have a summary by a datetime field as the last stage. For example, if you have a query that's just computing `Count` of products by `Category` and `Created At`, you'll be able to connect the time grouping parameter to the `Created At` grouping, but if you modify the query to filter for results with `Count > 100`, you won't be able to connect time grouping parameter on a dashboard to that query because the last stage is now a filter.
## Filtering dashboards with native/SQL questions
To connect a dashboard filter widget to a card with a question created with the native editor, you'll need to [add a field filter or basic variable to your query](../questions/native-editor/sql-parameters.md).
For parameters, check out [Time grouping parameters](../questions/native-editor/time-grouping-parameters.md).
## Auto-connecting filters to cards
### Auto-connecting filters to cards
If there are other cards that also have the field you select, Metabase will offer to automatically connect the filter to those cards too (including relevant cards on other tabs). If you later add a card with the selected field, Metabase will also try to connect that filter to the new card.
@@ -193,47 +197,78 @@ To undo this auto-connecting of cards, click the notification that pops up when
You can even wire up filters to text cards, but only if [the text card includes a variable](./introduction.md#including-variables-in-text-cards).
## Requiring a filter or parameter
## Filtering dashboards with native/SQL questions
You can tell Metabase to require a filter so that people _must_ filter the dashboard by a certain column on a card. If you require a filter, you'll also need to supply a default value for that filter.
To connect a dashboard filter widget to a card with a question created with the native editor, you'll need to [add a field filter or basic variable to your query](../questions/native-editor/sql-parameters.md).
You might want to require a filter value if:
If your native query uses a basic variable (and not a field filter), you'll only be able to use dashboard filter types that select a single value (so for example, you won't be able to use date range filters).
- Your unfiltered dashboard contains questions that pull lots of data, as enforcing filtered data can prevent people from inadvertently querying tons of data and running up your data warehouse costs.
- The questions on your dashboard don't make sense without a filter. For example, if you create a dashboard intended to view data relevant to a specific customer (as opposed to all customers), you can require a customer ID so that the dashboard only loads data for a particular customer.
For parameters, check out [Time grouping parameters in SQL](../questions/native-editor/time-grouping-parameters.md).
## Editing a filter
## Configure dashboard filters and parameters
To edit a dashboard filter's settings:
To edit settings for a dashboard filter or parameter:
1. Click the **pencil** icon to enter dashboard editing mode.
2. Click the filter you want to edit.
2. Click the widget you want to edit.
3. A widget editing sidebar will open on the right side
From this filter editing view, you can wire up dashboard cards to the filter, or use the filter settings sidebar to:
From this editing view, you can wire up dashboard cards to the filter, or use the filter settings sidebar to:
- [Rename filter](#rename-filter)
- [Set filter input type](#set-filter-input-type)
- [Set a default filter value](#set-a-default-filter-value)
- [Remove a filter](#remove-a-filter)
- [Reorder filters](#reorder-filters)
- [Make a multi-select filter](#make-a-multi-select-filter)
- [Change a filter's selectable values](#change-a-filters-selectable-values)
- [Rename a dashboard widget](#rename-a-dashboard-widget)
- [Change widget type](#change-filter-or-parameter-type)
- [Change filter operator](#change-filter-operator)
- [Set filter input type](#set-filter-input-type)
- [Make a multi-select filter](#make-a-multi-select-filter)
- [Change a filter's selectable values](#change-a-filters-selectable-values)
- [Set a default filter value](#set-a-default-filter-value)
- [Make a filter required](#make-a-filter-or-parameter-required)
- [Move a filter](#move-a-filter-or-parameter)
- [Remove a filter](#remove-a-filter-or-parameter)
### Rename filter
### Rename a dashboard widget
1. In dashboard edit mode, click the filter you want to edit.
2. Change the label text.
2. In the filter editing sidebar, change the **Label** text.
Renaming the filter only affects the filter's display; the label has no effect on which columns Metabase filters.
### Change filter or parameter type
You can change the [type](#filter-types) or an existing filter (for example, from a Date filter to a Text filter). Any incompatible columns connected to the widget will be disconnected.
To change the widget type:
1. When viewing a dashboard, click the **pencil** icon to **Edit the dashboard**.
2. Click on the filter or parameter you want to edit. A widget editing sidebar should pop up on the right side.
3. In the sidebar, change the type of filter or parameter. Changing the widget type disconnects the widget from all cards. You'll need to reconnect to the relevant columns on each card for the new type. If you've changed the widget type by mistake and want to restore the widget and its connections to cards, you can exit dashboard edit mode without saving your changes.
### Change filter operator
For some [filter types](#filter-types), you can configure the filter operator - meaning, how Metabase should use the value that a person passed in the filter. For example, for a Number filter, you can configure whether Metabase should filter for values exactly equal to the value passed in the filter, greater than the value, or less than the value.
To change the operator for a dashboard filter:
1. When viewing a dashboard, click the **pencil** icon to **Edit the dashboard**.
2. Click on the filter you want to edit. A widget editing sidebar should pop up on the right side.
3. In **Filter operator**, pick the filter operator. The options will depend on the filter type. Some filter types (for example, ID) don't have operator selection.
### Set filter input type
You can set a widget to display options as a dropdown menu, search box, or input box.
[Metadata settings](../data-modeling/metadata-editing.md#filtering) for the filtered column, including [variable settings in native queries](../questions/native-editor/filter-widgets.md#dropdown-menu-and-search), can also affect the filter's appearance.
For example, if the column you're connecting a filter to is configured in the [metadata settings](../data-modeling/metadata-editing.md#filtering) to display a search box instead of a dropdown, that metadata setting will take precedence.
To configure filter input type:
1. In dashboard edit mode, click the filter you want to edit.
2. From the filter settings sidebar, set **How should people filter on this column?**:
- [Dropdown list](#dropdown-list)
- [Search box](#search-box)
- [Input box](#plain-input-box)
- [Dropdown list](#dropdown-list)
- [Search box](#search-box)
- [Input box](#plain-input-box)
#### Dropdown list
@@ -256,24 +291,6 @@ An input box that lets people enter plain text (no suggestion list).
Useful for looking up partial matches (such as the ["contains" filter](#text-or-category-filter)) in columns that contain free text, such as comments or descriptions. The input box is the default filter widget for columns with more than 100 unique values.
### Set a default filter value
1. In dashboard edit mode, click the filter you want to edit.
2. From the sidebar, choose a value from the **Default value** input field.
For example, you might want to set a default filter value like "Active," so that when people load your dashboard, they only see data for "Active" records (not "Inactive," "Canceled," and so on).
### Remove a filter
1. In dashboard edit mode, click the filter you want to edit.
2. From the sidebar, click **Remove**.
If you accidentally remove a filter, just click **Cancel** in the top-right to exit dashboard edit mode without saving your changes.
### Reorder filters
In dashboard edit mode, click the grabber handle (six dots) on the left side of a filter widget, then drag the widget to a different position.
### Make a multi-select filter
1. In dashboard edit mode, click the filter you want to edit.
@@ -285,15 +302,65 @@ A multi-select filter with the widget type [Dropdown list](#dropdown-list) or [S
1. In dashboard edit mode, click the filter you want to edit.
2. From the sidebar, find **How should users filter on this column?**.
3. Select "Dropdown list".\*
3. Select "Dropdown list". If you don't see "Dropdown list" as an option, go to [Filter widgets: Dropdown list](#dropdown-list) for more info.
4. Click **Edit** (to the right of "Dropdown list") to specify where the values should come from:
- From connected fields
- From another model or question
- Custom list
![Selectable values](./images/selectable-values.png)
![Selectable values](./images/selectable-values.png)
\* If you don't see "Dropdown list" as an option, go to [Filter widgets: Dropdown list](#dropdown-list) for more info.
### Set a default filter value
You might want to set a default filter value, like "Active," so that when people load your dashboard, they only see data for "Active" records (not "Inactive," "Canceled," and so on).
1. When viewing a dashboard, click the **pencil** icon to **Edit the dashboard**.
2. Click on the filter you want to make required. A filter sidebar should pop up on the right side.
3. In the sidebar, scroll down and choose a value from the **Default value** input field.
### Make a filter or parameter required
You can tell Metabase to require a filter so that people _must_ filter the dashboard by a certain column on a card. If you require a filter, you'll also need to supply a default value for that filter.
You might want to require a filter value if:
- Your unfiltered dashboard contains questions that pull lots of data. Enforcing filtered data can prevent people from inadvertently querying tons of data and running up your data warehouse costs.
- The questions on your dashboard don't make sense without a filter. For example, if you create a dashboard intended to view data relevant to a specific customer (as opposed to all customers), you can require a customer ID so that the dashboard only loads data for a particular customer.
To require a value for a dashboard filter:
1. When viewing a dashboard, click the **pencil** icon to **Edit the dashboard**.
2. Click on the filter you want to make required. A filter sidebar should pop up on the right side.
3. In the filter settings sidebar, scroll to the toggle **Always require a value**.
4. Specify the default value for the filter.
### Move a filter or parameter
Widgets can be displayed and applied on dashboard, header, or card level, see [Dashboard, header, and card widgets](#dashboard-header-and-card-widgets). If you want to change the level of the filter - for example, move a dashboard filter into a card filter, or a header filter into a dashboard filter - you'll need to move it in the filter settings (you can't drag filters to a different level).
To move a filter:
1. In dashboard edit mode, click the filter or parameter you want to edit.
2. From the sidebar, click **Move filter**.
3. Select a card or header to move the widget to. Select "Top of the page" to make the widget into a dashboard-wide filter or parameter.
4. Make sure that the widget is connected to the right columns.
### Remove a filter or parameter
1. In dashboard edit mode, click the filter you want to edit.
2. From the sidebar, click **Remove**.
If you accidentally remove a filter, just click **Cancel** in the top-right to exit dashboard edit mode without saving your changes.
## Reorder filters
To reorder dashboard-wide filters:
1. While viewing a dashboard, click the **pencil** icon to enter edit mode.
2. In dashboard edit mode, click the grabber handle (six dots) on the right side of a filter widget, then drag the widget to a different position.
You can't drag a dashboard level filter to a header or a card. To move a dashboard-level filter to a header or a card, see [Move filter](#move-a-filter-or-parameter).
## Linking filters

Binary file not shown.

Before

Width:  |  Height:  |  Size: 67 KiB

After

Width:  |  Height:  |  Size: 122 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 43 KiB

After

Width:  |  Height:  |  Size: 110 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 79 KiB

After

Width:  |  Height:  |  Size: 135 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 317 KiB

After

Width:  |  Height:  |  Size: 426 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 290 KiB

After

Width:  |  Height:  |  Size: 187 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 232 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 83 KiB

After

Width:  |  Height:  |  Size: 429 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 150 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 19 KiB

After

Width:  |  Height:  |  Size: 89 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 111 KiB

After

Width:  |  Height:  |  Size: 213 KiB

View File

@@ -23,12 +23,24 @@ You can add [filter widgets to dashboards](./filters.md) that filter data identi
You can make as many dashboards as you want. Go nuts.
## Example dashboard
Every new Metabase comes with an example dashboard, **E-commerce insights**, in the **Examples** collection (though your admin can turn off or delete the examples). The example dashboard is yours to explore and play with.
## How to create a dashboard
In the top right of the screen, click the **+ New** > **Dashboard**. Give your new dashboard a name and a description, choose which [collections](../exploration-and-organization/collections.md) the dashboard should go in, then click **Create**, and Metabase will take you to your shiny new dashboard.
{% include youtube.html id='W-i9E5_Wjmw' %}
1. In the top right of the screen, click the **+ New** > **Dashboard**.
2. Give your new dashboard a name and a description.
3. Choose which [collections](../exploration-and-organization/collections.md) the dashboard should go in.
4. Click **Create**, and Metabase will take you to your shiny new dashboard.
5. Next, you'll need to add some questions (charts) to the dashboard, see [Adding or saving questions to the dashboard](#adding-or-saving-questions-to-a-dashboard).
## Adding or saving questions to a dashboard
To get some charts on a dashboard, you'll need to [create questions](../questions/introduction.md) (Metabase word for chart or query) and then add them, to the dashboard.
You can add questions that are saved to collections, or save questions directly to a dashboard.
### From a dashboard
@@ -98,11 +110,15 @@ To see how to wire up a filter to a card, see [dashboard filters](./filters.md).
## Link cards
![Dashboards with link cards](./images/dashboard-with-link-cards.png)
Link cards are specialized cards that let you search and link to other items in your Metabase. You can also use them for external links. Useful for pointing people to other resources relevant to your dashboard.
To add a link card to a dashboard, click the **pencil** icon to enter dashboard editing mode, then click on the **link** icon. Click on the input field in the link card to search your Metabase for an item to link to, or paste an external link.
![Dashboards with link cards](./images/dashboard-with-link-cards.png)
To add a link card to a dashboard:
1. When viewing a dashboard, click the **pencil** icon to enter dashboard editing mode;
2. Click the **link** (paper clip) icon to add a link card.
3. On the link card, click the input field to search your Metabase for an item to link to, or paste an external link.
Link cards support variables so you can use dashboard filters to update values in the link card's URL. For example, you could include a variable in a URL using double braces, like so:
@@ -313,16 +329,15 @@ Public links can be viewed by anyone, even if they don't have access to Metabase
## Exporting results from a dashboard
See [Exporting results](../questions/exporting-results.md).
You can export the entire dashboard as PDF, or export results of individual questions on the dashboard. See [Exporting results](../questions/exporting-results.md).
## Configuring a dashboard through its URL
You can amend the URL of a dashboard to automatically enter fullscreen, enable night mode, or auto-refresh the dashboard. Customizing the dashboard's URL allows you to configure the dashboard - even when you do not have any input access to the device where the dashboard will be displayed, like scripted screens, for example.
You can amend the URL of a dashboard to automatically enter fullscreen or auto-refresh the dashboard. Customizing the dashboard's URL allows you to configure the dashboard - even when you do not have any input access to the device where the dashboard will be displayed, like scripted screens, for example.
To configure a dashboard using its URL, you can add the following optional keywords:
- `fullscreen`
- `night`
- `refresh`
Here's an example URL:
@@ -331,7 +346,7 @@ Here's an example URL:
https://metabase.mydomain.com/dash/2#refresh=60&fullscreen&night
```
The part that says `refresh=60` sets the dashboard to automatically refresh every 60 seconds, `fullscreen` sets it to fullscreen mode, and `night` sets it to night mode (night mode only works when using fullscreen). Use an ampersand, `&`, in between keywords, and make sure there's a hash, `#`, after the dashboard's ID number.
The part that says `refresh=60` sets the dashboard to automatically refresh every 60 seconds, `fullscreen` sets it to fullscreen mode. Use an ampersand, `&`, in between keywords, and make sure there's a hash, `#`, after the dashboard's ID number.
There is one important limitation with the `fullscreen` option: for security reasons, many browsers require user interaction to initiate fullscreen. In those browsers, using the `fullscreen` option will enable the fullscreen UI in Metabase, but it won't expand the browser content to fill the screen. To ensure the dashboard occupies the entire screen, either activate fullscreen by clicking the button in the UI, or use the `fullscreen` URL option and launch the browser in fullscreen or kiosk mode.

View File

@@ -1,8 +1,8 @@
---
title: Dashboard subscriptions
redirect_from:
- /docs/latest/users-guide/dashboard-subscriptions
- /docs/latest/enterprise-guide/dashboards-subscriptions
- /docs/latest/users-guide/dashboard-subscriptions
- /docs/latest/enterprise-guide/dashboards-subscriptions
---
# Dashboard subscriptions
@@ -15,52 +15,71 @@ If your Metabase has email or Slack set up, all you need to do is create a dashb
To enable dashboard subscriptions, your administrators will need to have set up email or Slack for your Metabase. See [Setting up email](../configuring-metabase/email.md) or [Setting up Slack](../configuring-metabase/slack.md).
## Setting up a dashboard subscription
## Set up a dashboard subscription
To set up a subscription to a dashboard, click on the **Sharing** icon and select **Subscriptions**. Metabase will slide out a sidebar on the right, with an option to set up a subscription via email or Slack:
To set up a subscription to a dashboard,
![Set up a dashboard subscription with email or slack](./images/email-or-slack.png)
1. Click on the **three dots** icon Select **Subscriptions**.
Let's say we want to email a dashboard. We'll click on the **Email it** option in the sidebar, and Metabase will give us some options:
![Select subscriptions from menu](./images/select-subscriptions.png)
![Dashboard subscription email options](./images/email-options.png)
2. Metabase will slide out a sidebar on the right, with an option to set up a subscription via email or Slack.
## Email subscription options
3. Configure [subscription recipients](#subscription-recipients) and [frequency](#frequency-and-timing). Optionally, you can configure filter and attachment settings.
For emails, we can:
![Dashboard subscription email options](./images/email-options.png)
### Add subscribers
### Subscription recipients
Add email addresses to register subscribers. On Metabase [Pro](https://www.metabase.com/product/pro) and [Enterprise](https://www.metabase.com/product/enterprise), admins can limit email recipients to [approved domains for notifications](../configuring-metabase/email.md#approved-domains-for-notifications) and [configure which recipients Metabase suggests](../configuring-metabase/email.md#suggest-recipients-on-dashboard-subscriptions-and-alerts).
#### Email
### Determine frequency and timing
You can sent email subscriptions both to people who have Metabase accounts (by typing their names) and to people outside Metabase (by typing their email).
Tell Metabase how often it should send the dashboard:
On Metabase [Pro](https://www.metabase.com/product/pro) and [Enterprise](https://www.metabase.com/product/enterprise), admins can limit email recipients to [approved domains for notifications](../configuring-metabase/email.md#approved-domains-for-notifications) and [configure which recipients Metabase suggests](../configuring-metabase/email.md#suggest-recipients-on-dashboard-subscriptions-and-alerts).
#### Slack
For Slack subscriptions, you can set up a subscription for a channel (like #general), or for a single person via their Slack username (not their display name).
You can also send subscriptions to private channels, but that requires additional configuration, see [Sending alerts and subscriptions to private Slack channels](../configuring-metabase/slack.md#sending-alerts-and-subscriptions-to-private-slack-channels).
If you rename the subscribed channel in Slack, you'll need to update the subscription to point to the new Slack channel name.
### Frequency and timing
You can tell Metabase how often it should send the dashboard:
- Hourly
- Daily
- Weekly
- Monthly
And what time of day to send the dashboard.
You'll need to specify what time of day to send the dashboard, and, for weekly and monthly subscription, the day when to send the subscription.
### Send email now
### Test subscription
A button that sends an email to all subscribers each time you touch it.
You can click **Send email/Slack now** in subscription settings to send a test email or Slack message (without waiting for regular schedule). This will send a subscriptions immediately to all subscribers or Slack channels.
### Don't send if there aren't results
If there are no results, you can tell Metabase to skip sending the email.
We recommend first creating a subscription with a test email/channel, then using **Send email/Slack now** to test it, and once you are satisfied with the subscription, replacing the test email/channel with real recipients and saving the subscription.
### Set filter values for when this gets sent
{% include plans-blockquote.html feature="Dashboard subscription filter customization" %}
Here you can set filters to apply when Metabase sends the subscription.
You can set filters to apply when Metabase sends the subscription to send "views" of the dashboard to different people. See [Customize filter values for each dashboard subscription](#customize-filter-values-for-each-dashboard-subscription).
## Attach results
### Don't send if there aren't results
When configuring a subscription, you can tell Metabase if it should attach results to the email as a file, in addition to displaying the table in the email body.
If the questions on the dashboard return no results, you can tell Metabase to skip sending the email.
This is helpful for dashboards that are displaying time-limited results (for example, "Survey responses over the last week"), or dashboards that display rare events (like "Latest outage analysis").
## Email attachments
When configuring an email subscription, you can tell Metabase if it should attach results to the email as a file, in addition to displaying the table in the email body.
Currently, you can only send attachments with question results. You can't sent the whole dashboard as a PDF attachment.
If you've added filters to your dashboard and set default values for those filters, Metabase will apply those default values to your subscriptions, filtering the results of all questions that are connected to those filters when the subscriptions are sent. To learn more, check out [dashboard filters](./filters.md).
@@ -85,22 +104,6 @@ The attached files will include up to 1 048 575 rows by default (Excel's row lim
You can toggle on "Send only attachments (no charts)" if you want to receive just the .csv or .xlsx files without the charts. Remember to select the results you want to attach in "Questions to attach" above the toggle.
## Slack subscription options
For Slack subscriptions, you can set up a subscription for a channel (like #general), or for a single person via their Slack username.
> Note that Slack username can be different from Slack display name.
![slack subscription options](./images/slack-subscription-options.png)
> If you rename the subscribed channel in Slack, you'll need to update the subscription to point to the new Slack channel name.
You can specify how often Metabase sends a Slack message (hourly, daily, weekly, or monthly), and whether to send a message if the dashboard fails to return results.
### Sending subscriptions to private channels
See [Sending alerts and subscriptions to private Slack channels](../configuring-metabase/slack.md#sending-alerts-and-subscriptions-to-private-slack-channels).
## Adding multiple subscriptions
You can add multiple subscriptions to a single dashboard. To add a subscription, click on the **+** icon in the dashboard subscription panel.
@@ -119,7 +122,7 @@ You can view a list of all alerts and dashboard subscriptions that people have s
{% include plans-blockquote.html feature="Dashboard subscription filter customization" %}
You can customize which filter values to apply to each dashboard subscription. That way you can send different groups of people an email (or Slack message) the contents of the dashboard with different filters applied. You only need to maintain one dashboard, which you can use to send results relevant to each subscriber.
You can customize which filter values to apply to each dashboard subscription. That way you can send an email (or Slack message) with the dashboard results to different groups of people, with different dashboard filters applied for each group. You only need to maintain one dashboard, which you can use to send results relevant to each subscriber. For example, send a dashboard filtered for "Marketing" department and "This week" date weekly to a marketing lead, and send the dashboard filtered for all departments and "This quarter" to the CEO.
### Setting filter values

View File

@@ -5,11 +5,11 @@ summary: Admins can create, update, and delete data in tables right in Metabase.
# Editable tables
{% include plans-blockquote.html feature="Editable table data" %}
{% include plans-blockquote.html feature="Editable tables" %}
Admins can enable editable table data in Metabase.
Admins can enable editable tables in Metabase, which will allow admins to edit data in tables directly from Metabase.
![Edit table](./images/edit-table.png)
![Add option](./images/add-option.png)
## Databases that support editable tables
@@ -20,6 +20,7 @@ Currently, editable tables are available for the following databases:
## Setting up editable tables
_Admin > Databases > Editable tables_
To set up table editing, admins can:
@@ -33,11 +34,16 @@ For this to work, Metabase's connection to your database must support writing ba
## Update or delete records in a table
_Browse Databases > Edit table_
To update or delete records in a table:
1. Open the left sidebar.
2. In the Data section, click **Databases**.
3. Hover over the table you want to edit and click the **Pencil** icon.
![Edit table](./images/edit-table.png)
4. Edit rows in the table just like you would in a spreadsheet.
Depending on the data in the column, Metabase may show a list of values to choose from. If you need to add an option to that list, simply type out the option and add it (you may need to refresh the browser for the new option to show up in the list).
@@ -69,7 +75,7 @@ If you try to delete a row that has foreign key references from other tables, yo
Metabase offers two ways to modify data in your database: **editable table data** and [actions](../actions/introduction.md).
### When to use editable table data
### When to use editable tables
Use editable table data to:

View File

@@ -5,10 +5,6 @@ summary: Learn how to unfold JSON columns into separate fields that you can filt
# Working with JSON
## Filtering JSON
In the [query builder](../questions/query-builder/editor.md), Metabase can't parse JSON in columns, so you can only filter by "Is empty" or "Not empty".
## JSON unfolding
With [some databases](#databases-that-support-json-unfolding), Metabase can unfold JSON columns into their component fields, which you can then filter on using the query builder.
@@ -29,8 +25,21 @@ This unfolding allows you to filter for values found in the original JSON object
Metabase will prefix the unfolded column names with the name of the original column that contained the JSON. You can change the column names in **Admin** > [Table metadata](metadata-editing.md), or by creating a [model](./models.md) and editing the column metadata.
## Databases that support JSON unfolding
- [BigQuery](../databases/connections/postgresql.md): automatically enabled, applies to `STRUCT` types only.
If your data is stored in the [STRUCT data type](https://cloud.google.com/bigquery/docs/reference/standard-sql/data-types#struct_type) in BigQuery, you can query the table's nested fields. This is enabled by default. However, Metabase won't unfold JSON stored in BigQuery as the `JSON` type. This is because in BigQuery, nested fields are _part of the table definition itself_, so when Metabase syncs with your BigQuery database, it'll be able to get metadata about any of your tables, including tables with nested fields. Querying nested fields, however, doesn't extend to arrays (REPEATED (STRUCT)) in BigQuery.
- [Druid (JDBC)](../databases/connections/druid.md)
- [MongoDB](../databases/connections/mysql.md): automatically enabled for all nested fields.
- [MySQL](../databases/connections/mysql.md)
- [PostgreSQL](../databases/connections/postgresql.md)
## Toggling JSON unfolding for a database
_Admin > Databases > Advanced options > Allow unfolding of JSON column_
If you notice a hit to performance from this JSON unfolding, we recommend turning it off.
To turn off JSON unfolding for a database:
@@ -47,6 +56,8 @@ To turn off JSON unfolding for a database:
## Toggling JSON unfolding for a specific column
_Admin > Table metadata > Unfold JSON_
If performance degrades, or you'd rather keep the JSON contained in the original column, you can turn off unfolding for individual fields in their settings.
1. Click the **grid** icon in the upper right.
@@ -64,14 +75,6 @@ If performance degrades, or you'd rather keep the JSON contained in the original
For example, if you upload a CSV with JSON in it, you might need to update the data/type in the database. Note that you can't edit the data type via Metabase; you can only change its field type. So even if the field type in Metabase is `Field containing JSON`, if the data/type isn't `JSON`, Metabase won't give you the option to unfold the column. You'll need to change the column type in the database itself.
## Databases that support JSON unfolding
- [BigQuery](../databases/connections/postgresql.md): automatically enabled, applies to `STRUCT` types only.
If your data is stored in the [STRUCT data type](https://cloud.google.com/bigquery/docs/reference/standard-sql/data-types#struct_type) in BigQuery, you can query the table's nested fields. This is enabled by default. However, Metabase won't unfold JSON stored in BigQuery as the `JSON` type. This is because in BigQuery, nested fields are _part of the table definition itself_, so when Metabase syncs with your BigQuery database, it'll be able to get metadata about any of your tables, including tables with nested fields. Querying nested fields, however, doesn't extend to arrays (REPEATED (STRUCT)) in BigQuery.
- [Druid (JDBC)](../databases/connections/druid.md)
- [MongoDB](../databases/connections/mysql.md): automatically enabled for all nested fields.
- [MySQL](../databases/connections/mysql.md)
- [PostgreSQL](../databases/connections/postgresql.md)
## Filtering JSON
In the [query builder](../questions/query-builder/editor.md), Metabase can't parse JSON in columns, so you can only filter by "Is empty" or "Not empty".

View File

@@ -1,17 +1,19 @@
---
title: "Table metadata admin settings"
title: "Table metadata editing"
redirect_from:
- /docs/latest/administration-guide/03-metadata-editing
---
# Table metadata admin settings
# Table metadata editing
> Prefer using [Data Studio > Data structure](../data-studio/data-structure.md) for metadata editing. The page _Admin > Table Metadata_ will be removed in future versions of Metabase.
_Admin > Table metadata_
![Table metadata settings](./images/table-metadata-settings.png)
Metabase lets you add and edit metadata for your tables and columns.
![Table metadata settings](./images/table-metadata-settings.png)
The **Table metadata settings only affect the way Metabase displays the data. None of the settings change the data in your database.**
Admins can grant access to these metadata settings to other groups. See [table metadata permissions](../permissions/data.md#manage-table-metadata-permissions).

View File

@@ -13,17 +13,7 @@ Metrics are like pre-defined calculations: create your aggregations once, save t
For example, you may want to create a metric that calculates revenue, so people can refer to revenue in their own questions. That way you standardize how revenue is calculated (so you don't end up with five different calculations for the revenue).
## Using metrics
You can:
- Save metrics to [collections](../exploration-and-organization/collections.md).
- Add metrics to [dashboards](../dashboards/introduction.md).
- View metrics in the [database browser](../exploration-and-organization/exploration.md#browse-your-databases).
- Pick metrics as aggregation columns in the Summarize block when creating questions, modify them or combine.
- [Pro](https://www.metabase.com/product/pro) and [Enterprise](https://www.metabase.com/product/enterprise) plans include the ability to [mark metrics as verified](../exploration-and-organization/content-verification.md).
### Metrics in the query builder
## Metrics in the query builder
When asking questions in the query builder, you can find metrics that your team created in the summarization section under **Common metrics**. You can pick multiple metrics and they will be calculated independently and joined automatically along the chosen dimensions.
@@ -35,6 +25,16 @@ You can also pick a metric as a data source when creating a new question. If the
You can use custom expressions to combine multiple metrics, or perform calculations on top of metrics.
## Using metrics
You can:
- When creating questions in the query builder, you can pick metrics as aggregation columns in the Summarize block. You can modify metrics, or combine them.
- Save metrics to [collections](../exploration-and-organization/collections.md), including the [Library](../data-studio/library.md).
- Add metrics to [dashboards](../dashboards/introduction.md).
- View metrics in the [database browser](../exploration-and-organization/exploration.md#browse-your-databases).
- [Pro](https://www.metabase.com/product/pro) and [Enterprise](https://www.metabase.com/product/enterprise) plans include the ability to [mark metrics as verified](../exploration-and-organization/content-verification.md).
## Creating a metric
To create a metric, bring up the command palette with cmd/ctrl + k. That’s cmd + k for Macs, or ctrl + k for Windows PCs. Search for New metric.
@@ -86,9 +86,13 @@ By "editing" a metric, we mean [editing the metric's query definition](#editing-
These collection permissions also interact with the group's [data permissions](../permissions/data.md), which define whether the group can view or query the metric's source data.
## Metrics in the Library
By adding metrics to your Library, the query builder will display the metrics more prominently in menus. See [Library metrics](../data-studio/library.md#metrics)
## Verifying a metric
See [content verification](../exploration-and-organization/content-verification.md).
See [content verification](../exploration-and-organization/content-verification.md). Prefer using [Library metrics](../data-studio/library.md#metrics) instead of content verification.
## Further reading

View File

@@ -28,7 +28,7 @@ To persist models for faster loading, you'll need to turn on model persistence f
1. [Your Metabase](#turn-on-model-persistence-for-your-metabase)
2. [Individual databases](#turn-on-model-persistence-for-each-database)
3. [(Optional) individual models](#turn-on-model-persistence-for-individual-models)
3. [individual models](#turn-on-model-persistence-for-individual-models)
### Turn on model persistence for your Metabase
@@ -36,7 +36,7 @@ To turn on model persistence for your Metabase, go to **Admin** > **Performance*
You can set models to refresh based on one of the default frequencies (every 1 hour, 2 hours, etc.), or select the **Custom** option to use [cron syntax](https://www.quartz-scheduler.org/documentation/quartz-2.3.0/tutorials/crontrigger.html) to specify your own update frequency.
The cron scheduler uses the [Report Timezone](../configuring-metabase/localization.md#report-timezone) if selected. Otherwise the scheduler will use the System Timezone (which defaults to GMT in [Metabase Cloud](https://www.metabase.com/cloud/)).
The cron scheduler uses the [default instance report Timezone](../configuring-metabase/localization.md#set-default-instance-report-timezone) if selected. Otherwise the scheduler will use the System Timezone (which defaults to GMT in [Metabase Cloud](https://www.metabase.com/cloud/)).
We recommend scheduling your models to refresh on a frequency that makes sense with how often your source tables update with new data.
@@ -54,6 +54,8 @@ Once you've turned on model persistence for your Metabase, you'll need to set it
4. Ensure that the credentials Metabase uses to connect to your data warehouse can manage and write to that schema.
By default, new models on the database will _not_ b persisted. You need to [Turn on model persistence for individual models](#turn-on-model-persistence-for-individual-models).
## Turn on model persistence for individual models
{% include plans-blockquote.html feature="Individual model persistence" %}

View File

@@ -6,7 +6,9 @@ redirect_from:
# Models
Models are a fundamental building block in Metabase. Models curate data from another table or tables from the same database to anticipate the kinds of questions people will ask of the data. You can think of them as derived tables, or a special kind of saved question meant to be used as the starting point for new questions. You can base a model on a SQL or query builder question, which means you can include custom, calculated columns in your model.
> Prefer [Transforms](../data-studio/transforms/transforms-overview.md) instead of models. Models remain supported for now, but will be deprecated in future versions of Metabase.
Models curate data from another table or tables from the same database to anticipate the kinds of questions people will ask of the data. You can think of them as derived tables, or a special kind of saved question meant to be used as the starting point for new questions. You can base a model on a SQL or query builder question, which means you can include custom, calculated columns in your model.
Models:

View File

@@ -4,6 +4,8 @@ title: "Segments"
# Segments
> Prefer [Data Studio](../data-studio/data-structure.md#segments) for managing segments.
Metabase allows admins to create segments so people can quickly and easily reference them in the query builder.
To manage segments:

View File

@@ -5,6 +5,8 @@ summary: Find broken content and unused items so you can fix problems and clean
# Dependency diagnostics
{% include plans-blockquote.html feature="Dependency disagnistics" %}
Dependency diagnostics shows you content with broken dependencies, and content that isn't referenced by anything else.
To open Dependency diagnostics:

View File

@@ -5,6 +5,8 @@ summary: Visualize how your content connects and what depends on what in Metabas
# Dependency graph
{% include plans-blockquote.html feature="Dependency graph" %}
![Dependency graph](./images/dependency-graph.png)
The dependency graph provides a visual representation of how your Metabase content is connected. You can use it to follow how data flows through your Metabase to better understand the impact of any changes you make.

Binary file not shown.

After

Width:  |  Height:  |  Size: 42 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 100 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 67 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 226 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 232 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 69 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 108 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 103 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 114 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 78 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 122 KiB

View File

@@ -1,6 +1,8 @@
---
title: Data studio
summary: Data Studio provides tools to shape and track your data so everyone can trust the numbers.
redirect_from:
- /docs/latest/data-studio/start
---
# Data Studio
@@ -23,3 +25,11 @@ Data Studio provides tools to shape and track your data so everyone can trust th
- **[Transforms](./transforms/transforms-overview.md)**: Wrangle your data in Metabase, write the query results back to your database, and reuse them in Metabase as sources for new queries.
\* Available on [Pro and Enterprise plans](https://www.metabase.com/pricing/).
## Get to Data Studio
The keys to Data Studio are granted only to people in either the Admin or [Data Analysts](../people-and-groups/managing.md#data-analysts) groups.
1. Click the **grid** icon in the upper right.
2. Select **Data Studio**.

View File

@@ -11,6 +11,8 @@ Jobs are scheduled runs of transforms based on the transform's tags.
## Transform tags
![Transform tags](../images/tags.png)
Add tags to transforms so that you can use jobs to run the transforms on a schedule. For example, you could add a "Nightly" tag to a transform, and have a job that runs all the transforms with the "Nightly" tag at midnight every day.
To add a tag to a transform:
@@ -23,12 +25,12 @@ By default, Metabase comes with hourly, daily, weekly, and monthly tags and jobs
Once you've tagged a transform, you can create a job that uses that tag to run the transform on the job's schedule.
Job can use multiple tags, and will run all transforms that have _any_ of those tags. For example, you can have a job "Weekend job" that is scheduled run at noon on Saturdays and Sundays that picks up all transforms tagged either "Saturday", "Sunday", or "Weekend".
## Jobs
_Data Studio > Jobs_
![Transform jobs](../images/jobs.png)
Jobs run one or more transforms on schedule based on transform tags.
To see all jobs, go to **Data Studio** and click on the **Jobs** at the bottom of the left sidebar.
@@ -40,6 +42,8 @@ Jobs have two components: schedule and tags.
- **Schedule** determines when the job will be executed: daily, hourly, etc. You can specify a custom cron schedule (e.g. "Every weekday at 9:05 AM"). The times are given in your Metabase's system timezone.
- **Tags** determine _which_ transforms a job runs, not when the job runs. For example, you can create a `Weekdays` tag, add that tag to a few transforms, then create a job that runs all the transforms with the `Weekdays` tag every weekday at 9:05AM.
Job can use multiple tags, and will run all transforms that have _any_ of those tags. For example, you can have a job "Weekend job" that is scheduled run at noon on Saturdays and Sundays that picks up all transforms tagged either "Saturday", "Sunday", or "Weekend".
## Jobs will run all dependent transforms
If one transform depends on another, Metabase will run the dependency first, even if that transform isn't tagged in the job. So if transform B depends on A, Metabase will first run A, even if A doesn't have a tag.
@@ -50,6 +54,8 @@ You can see which transforms a job will run (and in which order) on the job's pa
## Runs
![Transform runs](../images/runs.png)
You can see all past and current transform runs (both manual and scheduled) by going to **Data Studio** and clicking on **Runs** at the bottom of the left sidebar. The transform run times will be given in Greenwich Mean Time (GMT).
You can click on any transform run to see more details about the run, like the error logs. To go to the transform definition from the transform run page, click on the icon next the transform name in the right sidebar.

View File

@@ -5,14 +5,14 @@ summary: Configure self-hosted Python execution environment to run Python transf
# Python runner
> Self-hosted Python transforms require self-hosted Pro or Enterprise plan with the Transforms add-on.
> Self-hosted Python transforms require self-hosted Pro or Enterprise plan with the **Advanced transforms** add-on.
To run Python transforms from a self-hosted Metabase, you'll need to configure a separate self-hosted execution environment. If you're using Metabase Cloud, you'll need to buy the Transforms add-on.
## Prerequisites
- Docker installed and running.
- **Metabase Pro or Enterprise license** (Python Runner requires a Pro/Enterprise plan).
- **Self-hosted Metabase Pro or Enterprise license** (Python Runner requires a Pro/Enterprise plan).
- For production: an S3-compatible storage bucket (AWS S3, MinIO, etc.).
## Quickstart

View File

@@ -24,9 +24,12 @@ Python-based transforms require a dedicated [Python execution environment](#set-
To execute Python transforms, you'll need a _Python runner_ - a dedicated environment for running Python code.
If you're on Metabase Cloud, get the **Transforms add-on**, and you're good to go.
- If you're on Metabase Cloud, get the **Transforms add-on** with **SQL + Python** option, and you're good to go.
If you're self-hosting Metabase, you'll need to set up a self-hosted Python runner, see [Python runner](python-runner.md).
- If you're self-hosting Metabase, you'll need to:
1. Get the **Advanced transforms** add-on for your subscription in Metabase Store [store.metabase.com](https://store.metabase.com).
2. Set up a self-hosted Python runner, see [Python runner](python-runner.md).
## Create a Python transform

View File

@@ -5,10 +5,12 @@ summary: Create Metabase questions and SQL queries to transform your data and wr
# Query-based transforms
> On Metabase Cloud, you need the Transforms add-on to run query-based transforms.
> On Metabase Cloud, you need the **Transforms** add-on to run query-based transforms.
With query-based transforms, you can write a query in SQL or Metabase's query builder, and then write the results of the query back into the database on schedule.
![Query transform](../images/sql-transform.png)
For general information about Metabase transforms, see [Transforms](transforms-overview.md).
## How query-based transforms work
@@ -21,12 +23,14 @@ For general information about Metabase transforms, see [Transforms](transforms-o
## Create a query-based transform
Currently, you can't convert between different transform types (like converting a query builder transform to a SQL-based transform, or a SQL transform into a Python transform). If you want to change your transform built with the query builder into a SQL transform, you'll need to create a new transform with the same target and tags, and delete the old transform.
On Metabase Cloud, you need the **Transforms** add-on to create query-based transforms.
1. Go to **Data studio > Transforms**.
2. Click **+ New** and pick "Query builder", "SQL", or "Copy of existing question".
Currently, you can't convert between different transform types (like converting a query builder transform to a SQL-based transform, or a SQL transform into a Python transform). If you want to change your transform built with the query builder into a SQL transform, you'll need to create a new transform with the same target and tags, and delete the old transform.
3. Write your transform query as you would normally write a query in Metabase. See [Query builder](../../questions/query-builder/editor.md) and [SQL editor](../../questions/native-editor/writing-sql.md) documentation for more information.
Not all databases support transforms, see [Databases that support transforms](transforms-overview.md#databases-that-support-transforms).

View File

@@ -11,6 +11,8 @@ Transforms can be used to, well, transform your data - do stuff like preprocessi
You'll write a query or a Python script in Metabase, a transform will run this query or script, create a table in your target database containing the results, and sync that table to Metabase, so it can be used as a data source for questions or other transforms.
![Transforms](../images/transforms.png)
## Transforms overview
- **Transforms** are queries (created either with SQL or the query builder) or Python scripts that write back to your database and create a new, persistent table. Use transforms to clean, join, or pre-aggregate data.
@@ -62,6 +64,8 @@ You can see all your Metabase's transforms:
2. Click the **grid** icon on top right and go to **Data Studio**.
3. In the left sidebar, select **Transforms**.
![Transforms](../images/transforms.png)
## Create a transform
_Data Studio > Transforms_
@@ -75,10 +79,14 @@ To create a transform:
3. In the left sidebar, select **Transforms**.
4. Click **+ New** and select a source for your transform.
![New transform](../images/new_transform.png)
You can create your transform using Metabase's [graphical query builder](../../questions/query-builder/editor.md), SQL, or Python.
For more information on transforms built with the query builder or SQL, see [query-based transforms](query-transforms.md). For more information on Python transforms, see [Python transforms](python-transforms.md).
![Query transform](../images/sql-transform.png)
If you select **Copy of a saved question** for the transform's source, you can copy the query of an existing Metabase question (either a SQL question or a query builder question) into your transform query. Metabase will only _copy_ the question's query. Later edits to that original question won't affect the transform's query.
5. Create the query or script for your transform.
@@ -97,6 +105,8 @@ To create a transform:
- **Folder** (optional): The folder where the transform should live. Click on the field to pick a different folder or create a new one.
- **Incremental transformation** (optional): see [Incremental query-based transforms](query-transforms.md#incremental-query-transforms) or [Incremental Python transforms](python-transforms.md)
![Transform settings](../images/transform-settings.png)
7. Optionally, once the transform is saved, assign tags to your transform. Tags are used by [jobs](./jobs-and-runs.md) to run transforms on schedule.
## Use Metabot to generate code for transforms
@@ -105,13 +115,19 @@ To create a transform:
You can ask Metabot to generate a new SQL or Python-based transform, or edit an existing transform.
1. Go to **Data studio > Transforms**.
1. Go to **Data studio > Transforms**. If you want Metabot to edit an existing transform, navigate to the transform.
2. While in Transforms view, click on the Metabot icon in top right.
3. Describe the transform that you'd like Metabot to write.
You can specify which kind of transform you want (Python or SQL) and @-mention specific data sources to help Metabot understand your request.
Metabot will create a to-do list for itself that will show its thinking process, and then work through the list.
![Create a new transform with codegen](../images/transform-codegen.png)
4. Metabot will create a to-do list for itself that will show its thinking process, and then work through the list.
5. If you asked Metabot to create a new transform, review the code that Metabot offers in the chat window and click on "Create" under the code snippet.
![Create snippet](../images/create-transform.png)
You can continue working with Metabot to refine your code. Metabot will suggest code changes, and give you the option of accepting or rejecting the changes.
@@ -123,6 +139,8 @@ You can edit the transform's name and description, query/script, target table, a
If you're using remote sync, you won't be able to edit transforms if your instance is in ["read-only" sync mode](../../installation-and-operation/remote-sync.md).
![Edit transform settings](../images/transform-edit-settings.png)
### Edit transform's query or script
_Data Studio > Transforms > Definition_
@@ -162,10 +180,12 @@ For Python transforms, you'll also see the transform's execution logs.
## Transform dependencies
> Transform dependency graph is only available on Pro and Enterprise plans (both self-hosted and Metabase Cloud)
{% include plans-blockquote.html feature="Transform dependencies" is_plural=true%}
_Data Studio > Transforms > Dependencies_
![Transforms dependencies](../images/transform-dependencies.png)
Transform queries can use the data from other transforms, and query-based transforms can also reference Metabase questions and models. For example, you can have a transform that uses data from a `raw_events` table and writes to a `stg_events` table, and then create another transform that uses data from the `stg_events` table and writes to an `events` table.
Metabase will track transform dependencies and execute transforms in a reasonable order. So for example, if transform B relies on a table created by transform A, Metabase will run transform A first, then run transform B.

View File

@@ -14,11 +14,14 @@ Connect Metabase to your data sources.
## Adding a database connection
To add a database connection, click the **grid** icon in the top right, and navigate to **Admin** > **Databases** > **Add a database**.
To add a database connection:
Fill out the fields for that database, and click **Save changes** at the bottom.
1. Click the **grid** icon in the top right.
2. Select **Admin**.
3. In Admin settings, navigate **Databases** > **Add a database**.
4. Fill out the fields for that database, and click **Save changes** at the bottom.
The connection settings differ database to database. For the list of connection settings available for your database, click on the link to your database below.
The connection settings differ database to database. For the list of connection settings available for your database, click the link to your database below.
## Connecting to supported databases

View File

@@ -211,8 +211,6 @@ If Metabase also needs to create tables, you'll need additional AWS Glue permiss
## Writeable connection
{% include plans-blockquote.html feature="Writeable connection" is_plural=true%}
Set up an additional connection used for write operations. See [Writeable connections](../writeable-connection.md).
## Model features

View File

@@ -163,8 +163,6 @@ If you're having trouble with your BigQuery connection, you can check out this [
## Writeable connection
{% include plans-blockquote.html feature="Writeable connection" is_plural=true%}
Set up an additional connection used for write operations. See [Writeable connections](../writeable-connection.md).
## Model features

View File

@@ -103,8 +103,6 @@ A fingerprinting query examines the first 10,000 rows from each column and uses
## Writeable connection
{% include plans-blockquote.html feature="Writeable connection" is_plural=true%}
Set up an additional connection used for write operations. See [Writeable connections](../writeable-connection.md).
## Model features

View File

@@ -103,8 +103,6 @@ A fingerprinting query examines the first 10,000 rows from each column and uses
## Writeable connection
{% include plans-blockquote.html feature="Writeable connection" is_plural=true%}
Set up an additional connection used for write operations. See [Writeable connections](../writeable-connection.md).
## Model features

View File

@@ -66,8 +66,6 @@ A fingerprinting query examines the first 10,000 rows from each column and uses
## Writeable connection
{% include plans-blockquote.html feature="Writeable connection" is_plural=true%}
Set up an additional connection used for write operations. See [Writeable connections](../writeable-connection.md).
## Model features

View File

@@ -103,8 +103,6 @@ If your password contains characters that aren't UTF-8, then you might need to a
## Writeable connection
{% include plans-blockquote.html feature="Writeable connection" is_plural=true%}
Set up an additional connection used for write operations. See [Writeable connections](../writeable-connection.md).
## Database routing

View File

@@ -132,8 +132,6 @@ If you're not seeing all of the fields show up for a collection in Metabase, one
## Writeable connection
{% include plans-blockquote.html feature="Writeable connection" is_plural=true%}
Set up an additional connection used for write operations. See [Writeable connections](../writeable-connection.md).
## Database routing

View File

@@ -189,8 +189,6 @@ If your password contains characters that aren't UTF-8, then you might need to a
## Writeable connection
{% include plans-blockquote.html feature="Writeable connection" is_plural=true%}
Set up an additional connection used for write operations. See [Writeable connections](../writeable-connection.md).
## Model features

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