dataface 0.1.2__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- d3_format/__init__.py +14 -0
- d3_format/errors.py +19 -0
- d3_format/format.py +551 -0
- d3_format/spec.py +159 -0
- dataface/DATAFACE_SYNTAX.md +1135 -0
- dataface/__init__.py +93 -0
- dataface/_docs_site.py +20 -0
- dataface/_install_hint.py +26 -0
- dataface/agent_api/__init__.py +79 -0
- dataface/agent_api/_init_templates/__init__.py +0 -0
- dataface/agent_api/_init_templates/agents_dft_snippet.md +26 -0
- dataface/agent_api/_init_templates/dataface.yml +15 -0
- dataface/agent_api/_init_templates/faces-dataface.yml +144 -0
- dataface/agent_api/_init_templates/index.md +24 -0
- dataface/agent_api/_paths.py +118 -0
- dataface/agent_api/_project_agents_md.py +43 -0
- dataface/agent_api/_session_store.py +486 -0
- dataface/agent_api/_state.py +28 -0
- dataface/agent_api/chat.py +221 -0
- dataface/agent_api/dashboards.py +257 -0
- dataface/agent_api/describe.py +366 -0
- dataface/agent_api/describe_query.py +120 -0
- dataface/agent_api/docs/__init__.py +25 -0
- dataface/agent_api/docs/_loader.py +292 -0
- dataface/agent_api/docs/yaml-reference.md +2757 -0
- dataface/agent_api/file_refs.py +118 -0
- dataface/agent_api/init.py +126 -0
- dataface/agent_api/inspect.py +128 -0
- dataface/agent_api/mcp_install.py +170 -0
- dataface/agent_api/query.py +274 -0
- dataface/agent_api/schema.py +658 -0
- dataface/agent_api/schema_search.py +284 -0
- dataface/agent_api/search.py +270 -0
- dataface/agent_api/skill_install.py +141 -0
- dataface/agent_api/skill_render.py +90 -0
- dataface/agent_api/skills.py +293 -0
- dataface/agent_api/surface_aliases.yaml +128 -0
- dataface/agent_api/validate.py +175 -0
- dataface/agent_api/validate_query.py +84 -0
- dataface/ai/__init__.py +39 -0
- dataface/ai/agent.py +139 -0
- dataface/ai/context.py +45 -0
- dataface/ai/events.py +62 -0
- dataface/ai/external_mcp.py +610 -0
- dataface/ai/generate_sql.py +96 -0
- dataface/ai/llm.py +403 -0
- dataface/ai/mcp/__init__.py +51 -0
- dataface/ai/mcp/server.py +289 -0
- dataface/ai/memories.py +85 -0
- dataface/ai/prompts.py +177 -0
- dataface/ai/schema_context.py +138 -0
- dataface/ai/skills/before-after-comparison/SKILL.md +102 -0
- dataface/ai/skills/before-after-comparison/examples/before-after-comparison.yml +24 -0
- dataface/ai/skills/dashboard-build/SKILL.md +212 -0
- dataface/ai/skills/dashboard-build/examples/_smoke.yml +15 -0
- dataface/ai/skills/dashboard-design/SKILL.md +182 -0
- dataface/ai/skills/dashboard-review/SKILL.md +113 -0
- dataface/ai/skills/dashboard-structural-review/SKILL.md +173 -0
- dataface/ai/skills/dashboard-visual-review/SKILL.md +139 -0
- dataface/ai/skills/dataface-mcp-setup/SKILL.md +177 -0
- dataface/ai/skills/dataface-troubleshooting/SKILL.md +225 -0
- dataface/ai/skills/drill-down-link/SKILL.md +112 -0
- dataface/ai/skills/drill-down-link/examples/drill-down-link.yml +27 -0
- dataface/ai/skills/faceted-small-multiples/SKILL.md +116 -0
- dataface/ai/skills/faceted-small-multiples/examples/faceted-small-multiples.yml +33 -0
- dataface/ai/skills/filter-bar-with-variables/SKILL.md +105 -0
- dataface/ai/skills/filter-bar-with-variables/examples/filter-bar-with-variables.yml +49 -0
- dataface/ai/skills/kpi-row/SKILL.md +101 -0
- dataface/ai/skills/kpi-row/examples/kpi-row.yml +55 -0
- dataface/ai/skills/report-design/SKILL.md +184 -0
- dataface/ai/skills/single-metric-bignum/SKILL.md +90 -0
- dataface/ai/skills/single-metric-bignum/examples/single-metric-bignum.yml +27 -0
- dataface/ai/skills/table-heavy-ops-dashboard/SKILL.md +114 -0
- dataface/ai/skills/table-heavy-ops-dashboard/examples/table-heavy-ops-dashboard.yml +48 -0
- dataface/ai/skills/time-series-trend/SKILL.md +93 -0
- dataface/ai/skills/time-series-trend/examples/time-series-trend.yml +26 -0
- dataface/ai/skills/top-n-with-detail/SKILL.md +98 -0
- dataface/ai/skills/top-n-with-detail/examples/top-n-with-detail.yml +45 -0
- dataface/ai/skills/two-by-two-grid-overview/SKILL.md +78 -0
- dataface/ai/skills/two-by-two-grid-overview/examples/two-by-two-grid-overview.yml +64 -0
- dataface/ai/tool_schemas.py +132 -0
- dataface/ai/tools/__init__.py +312 -0
- dataface/ai/yaml_utils.py +57 -0
- dataface/cli/__init__.py +3 -0
- dataface/cli/_console.py +48 -0
- dataface/cli/_error_format.py +83 -0
- dataface/cli/_extras.py +190 -0
- dataface/cli/_json_output.py +8 -0
- dataface/cli/_parsing.py +17 -0
- dataface/cli/_version_info.py +56 -0
- dataface/cli/commands/__init__.py +3 -0
- dataface/cli/commands/_agent_input.py +205 -0
- dataface/cli/commands/_agent_server.py +115 -0
- dataface/cli/commands/chat.py +645 -0
- dataface/cli/commands/describe.py +107 -0
- dataface/cli/commands/docs.py +131 -0
- dataface/cli/commands/extension.py +179 -0
- dataface/cli/commands/init.py +240 -0
- dataface/cli/commands/inspect.py +94 -0
- dataface/cli/commands/mcp_init.py +167 -0
- dataface/cli/commands/query.py +386 -0
- dataface/cli/commands/render.py +291 -0
- dataface/cli/commands/schema.py +411 -0
- dataface/cli/commands/search.py +49 -0
- dataface/cli/commands/serve.py +114 -0
- dataface/cli/commands/skills.py +133 -0
- dataface/cli/commands/skills_init.py +161 -0
- dataface/cli/commands/validate.py +63 -0
- dataface/cli/main.py +1501 -0
- dataface/core/__init__.py +75 -0
- dataface/core/compile/__init__.py +244 -0
- dataface/core/compile/_jinja_helpers.py +78 -0
- dataface/core/compile/channel.py +222 -0
- dataface/core/compile/chart_focus.py +101 -0
- dataface/core/compile/chart_resolved.py +169 -0
- dataface/core/compile/chart_type_detection.py +489 -0
- dataface/core/compile/chart_update.py +261 -0
- dataface/core/compile/colors.py +64 -0
- dataface/core/compile/compiler.py +904 -0
- dataface/core/compile/config.py +823 -0
- dataface/core/compile/custom_chart_types.py +208 -0
- dataface/core/compile/data_table_attachment.py +1287 -0
- dataface/core/compile/detect.py +110 -0
- dataface/core/compile/errors.py +302 -0
- dataface/core/compile/filter_injection.py +319 -0
- dataface/core/compile/introspection.py +527 -0
- dataface/core/compile/jinja.py +511 -0
- dataface/core/compile/labels_env.py +52 -0
- dataface/core/compile/markdown.py +154 -0
- dataface/core/compile/meta.py +388 -0
- dataface/core/compile/models/__init__.py +0 -0
- dataface/core/compile/models/chart/__init__.py +0 -0
- dataface/core/compile/models/chart/authored.py +2137 -0
- dataface/core/compile/models/chart/compiled.py +398 -0
- dataface/core/compile/models/config.py +347 -0
- dataface/core/compile/models/face/__init__.py +0 -0
- dataface/core/compile/models/face/authored.py +659 -0
- dataface/core/compile/models/face/compiled.py +522 -0
- dataface/core/compile/models/factories.py +201 -0
- dataface/core/compile/models/markers.py +40 -0
- dataface/core/compile/models/palette.py +36 -0
- dataface/core/compile/models/primitives.py +415 -0
- dataface/core/compile/models/query/__init__.py +0 -0
- dataface/core/compile/models/query/authored.py +246 -0
- dataface/core/compile/models/query/compiled.py +710 -0
- dataface/core/compile/models/refs.py +137 -0
- dataface/core/compile/models/source.py +611 -0
- dataface/core/compile/models/style/__init__.py +0 -0
- dataface/core/compile/models/style/authored.py +481 -0
- dataface/core/compile/models/style/compiled.py +3399 -0
- dataface/core/compile/models/style/merged.py +1682 -0
- dataface/core/compile/models/theme.py +362 -0
- dataface/core/compile/models/variable/__init__.py +0 -0
- dataface/core/compile/models/variable/authored.py +254 -0
- dataface/core/compile/models/vega_lite/__init__.py +0 -0
- dataface/core/compile/models/vega_lite/config.py +510 -0
- dataface/core/compile/models/vega_lite/contracts.py +171 -0
- dataface/core/compile/normalize_charts.py +494 -0
- dataface/core/compile/normalize_layout.py +1000 -0
- dataface/core/compile/normalize_queries.py +297 -0
- dataface/core/compile/normalize_variables.py +489 -0
- dataface/core/compile/normalizer.py +543 -0
- dataface/core/compile/palette.py +1100 -0
- dataface/core/compile/parameterized.py +658 -0
- dataface/core/compile/parser.py +228 -0
- dataface/core/compile/schema.py +20 -0
- dataface/core/compile/schema_renderers/__init__.py +0 -0
- dataface/core/compile/schema_renderers/json_schema.py +163 -0
- dataface/core/compile/schema_renderers/prompt.py +152 -0
- dataface/core/compile/schema_renderers/vscode_schema.py +301 -0
- dataface/core/compile/sizing.py +2126 -0
- dataface/core/compile/sources.py +518 -0
- dataface/core/compile/sql_authoring_lint.py +56 -0
- dataface/core/compile/style_cascade.py +471 -0
- dataface/core/compile/typography.py +299 -0
- dataface/core/compile/validator.py +301 -0
- dataface/core/compile/variables.py +53 -0
- dataface/core/compile/vega_config.py +98 -0
- dataface/core/compile/vega_lite/__init__.py +6 -0
- dataface/core/compile/vega_lite/validation.py +95 -0
- dataface/core/compile/yaml_error_formatter.py +838 -0
- dataface/core/connections.py +38 -0
- dataface/core/dashboard.py +358 -0
- dataface/core/defaults/default_config.yml +101 -0
- dataface/core/defaults/palettes/categorical/category-10-dark.yml +32 -0
- dataface/core/defaults/palettes/categorical/category-10-light.yml +43 -0
- dataface/core/defaults/palettes/categorical/category-10.yml +31 -0
- dataface/core/defaults/palettes/categorical/category-6-tonal-blue.yml +22 -0
- dataface/core/defaults/palettes/categorical/category-6-tonal-brown.yml +29 -0
- dataface/core/defaults/palettes/categorical/category-6-tonal-green.yml +20 -0
- dataface/core/defaults/palettes/categorical/category-6-tonal-orange.yml +21 -0
- dataface/core/defaults/palettes/categorical/category-6-tonal-purple.yml +20 -0
- dataface/core/defaults/palettes/categorical/editorial-10-dark.yml +32 -0
- dataface/core/defaults/palettes/categorical/editorial-10.yml +40 -0
- dataface/core/defaults/palettes/categorical/hero-6.yml +17 -0
- dataface/core/defaults/palettes/categorical/single-blue.yml +11 -0
- dataface/core/defaults/palettes/categorical/tableau.yml +20 -0
- dataface/core/defaults/palettes/data/xkcd_colors.json +3803 -0
- dataface/core/defaults/palettes/diverging/blue-red.yml +25 -0
- dataface/core/defaults/palettes/diverging/coolwarm.yml +24 -0
- dataface/core/defaults/palettes/diverging/crimson-green.yml +23 -0
- dataface/core/defaults/palettes/diverging/orange-teal.yml +23 -0
- dataface/core/defaults/palettes/diverging/sunset.yml +24 -0
- dataface/core/defaults/palettes/scaffold/dft-creams.yml +38 -0
- dataface/core/defaults/palettes/scaffold/dft-grays.yml +53 -0
- dataface/core/defaults/palettes/sequential/amber.yml +22 -0
- dataface/core/defaults/palettes/sequential/blue.yml +22 -0
- dataface/core/defaults/palettes/sequential/brown.yml +22 -0
- dataface/core/defaults/palettes/sequential/gray.yml +22 -0
- dataface/core/defaults/palettes/sequential/green.yml +22 -0
- dataface/core/defaults/palettes/sequential/purple.yml +22 -0
- dataface/core/defaults/palettes/sequential/rust.yml +22 -0
- dataface/core/defaults/palettes/sequential/teal.yml +22 -0
- dataface/core/defaults/palettes/tone/negative.yml +32 -0
- dataface/core/defaults/palettes/tone/positive.yml +22 -0
- dataface/core/defaults/palettes/tone/warning.yml +22 -0
- dataface/core/defaults/themes/_base.yaml +786 -0
- dataface/core/defaults/themes/bi.yaml +16 -0
- dataface/core/defaults/themes/carbong100.yaml +41 -0
- dataface/core/defaults/themes/cream.yaml +122 -0
- dataface/core/defaults/themes/dark.yaml +40 -0
- dataface/core/defaults/themes/diagnostics-title-angle-extreme.yaml +9 -0
- dataface/core/defaults/themes/diagnostics-title-baseline-extreme.yaml +9 -0
- dataface/core/defaults/themes/diagnostics-title-baseline.yaml +24 -0
- dataface/core/defaults/themes/diagnostics-title-center.yaml +8 -0
- dataface/core/defaults/themes/diagnostics-title-color-extreme.yaml +24 -0
- dataface/core/defaults/themes/diagnostics-title-font-extreme.yaml +25 -0
- dataface/core/defaults/themes/diagnostics-title-left.yaml +8 -0
- dataface/core/defaults/themes/diagnostics-title-offset-extreme.yaml +9 -0
- dataface/core/defaults/themes/diagnostics-title-size-extreme.yaml +24 -0
- dataface/core/defaults/themes/diagnostics-title-weight-extreme.yaml +24 -0
- dataface/core/defaults/themes/editorial.yaml +147 -0
- dataface/core/defaults/themes/light.yaml +30 -0
- dataface/core/defaults/themes/looker.yaml +17 -0
- dataface/core/defaults/themes/stark.yaml +134 -0
- dataface/core/errors/__init__.py +67 -0
- dataface/core/errors/codes_compile.py +56 -0
- dataface/core/errors/codes_execute.py +177 -0
- dataface/core/errors/codes_render.py +106 -0
- dataface/core/errors/codes_unknown.py +15 -0
- dataface/core/errors/hints.py +74 -0
- dataface/core/errors/registry.py +42 -0
- dataface/core/errors/structured.py +92 -0
- dataface/core/execute/__init__.py +91 -0
- dataface/core/execute/adapters/__init__.py +49 -0
- dataface/core/execute/adapters/adapter_registry.py +400 -0
- dataface/core/execute/adapters/base.py +245 -0
- dataface/core/execute/adapters/csv_adapter.py +239 -0
- dataface/core/execute/adapters/dbt_adapter.py +283 -0
- dataface/core/execute/adapters/dbt_adapter_factory.py +212 -0
- dataface/core/execute/adapters/dbt_macro_loader.py +95 -0
- dataface/core/execute/adapters/dbt_utils.py +150 -0
- dataface/core/execute/adapters/http_adapter.py +224 -0
- dataface/core/execute/adapters/metricflow_adapter.py +94 -0
- dataface/core/execute/adapters/schema_resolver_adapter.py +144 -0
- dataface/core/execute/adapters/sql_adapter.py +710 -0
- dataface/core/execute/adapters/values_adapter.py +58 -0
- dataface/core/execute/batch.py +744 -0
- dataface/core/execute/cache_backend.py +135 -0
- dataface/core/execute/cache_keys.py +66 -0
- dataface/core/execute/dbt_jinja.py +21 -0
- dataface/core/execute/dialects/__init__.py +121 -0
- dataface/core/execute/dialects/athena.py +75 -0
- dataface/core/execute/dialects/base.py +302 -0
- dataface/core/execute/dialects/bigquery.py +38 -0
- dataface/core/execute/dialects/databricks.py +68 -0
- dataface/core/execute/dialects/duckdb.py +35 -0
- dataface/core/execute/dialects/mysql.py +68 -0
- dataface/core/execute/dialects/postgres.py +39 -0
- dataface/core/execute/dialects/redshift.py +12 -0
- dataface/core/execute/dialects/snowflake.py +51 -0
- dataface/core/execute/dialects/sqlserver.py +92 -0
- dataface/core/execute/duckdb_cache.py +712 -0
- dataface/core/execute/duckdb_config.py +26 -0
- dataface/core/execute/errors.py +213 -0
- dataface/core/execute/executor.py +1249 -0
- dataface/core/execute/parallel.py +162 -0
- dataface/core/execute/setup_sql.py +58 -0
- dataface/core/execute/source_registry.py +72 -0
- dataface/core/execute/source_resolver.py +255 -0
- dataface/core/execute/sql_guard.py +387 -0
- dataface/core/execute/sql_literals.py +199 -0
- dataface/core/fonts.py +52 -0
- dataface/core/inspect/__init__.py +32 -0
- dataface/core/inspect/cache_factory.py +98 -0
- dataface/core/inspect/db_types.py +162 -0
- dataface/core/inspect/dbt_schema.py +96 -0
- dataface/core/inspect/defaults.yml +37 -0
- dataface/core/inspect/fanout_risk.py +109 -0
- dataface/core/inspect/manifest_utils.py +77 -0
- dataface/core/inspect/partials/categorical.yml +40 -0
- dataface/core/inspect/partials/date.yml +40 -0
- dataface/core/inspect/partials/numeric.yml +55 -0
- dataface/core/inspect/partition_types.py +38 -0
- dataface/core/inspect/query_validator.py +975 -0
- dataface/core/inspect/renderer.py +354 -0
- dataface/core/inspect/resolver.py +808 -0
- dataface/core/inspect/search.py +461 -0
- dataface/core/inspect/sources/__init__.py +32 -0
- dataface/core/inspect/sources/dbt.py +738 -0
- dataface/core/inspect/sources/duckdb_utils.py +66 -0
- dataface/core/inspect/templates/__init__.py +1 -0
- dataface/core/inspect/templates/categorical_column.yml +196 -0
- dataface/core/inspect/templates/charts.yml +109 -0
- dataface/core/inspect/templates/date_column.yml +248 -0
- dataface/core/inspect/templates/model.yml +138 -0
- dataface/core/inspect/templates/numeric_column.yml +261 -0
- dataface/core/inspect/templates/quality.yml +80 -0
- dataface/core/inspect/templates/string_column.yml +263 -0
- dataface/core/project_roots.py +165 -0
- dataface/core/render/__init__.py +87 -0
- dataface/core/render/board_links.py +176 -0
- dataface/core/render/chart/__init__.py +27 -0
- dataface/core/render/chart/arc_attached_table.py +251 -0
- dataface/core/render/chart/artifacts.py +16 -0
- dataface/core/render/chart/callout.py +225 -0
- dataface/core/render/chart/decisions.py +358 -0
- dataface/core/render/chart/geo.py +700 -0
- dataface/core/render/chart/kpi.py +916 -0
- dataface/core/render/chart/labels.py +76 -0
- dataface/core/render/chart/pipeline.py +818 -0
- dataface/core/render/chart/presentation.py +36 -0
- dataface/core/render/chart/profile.py +3438 -0
- dataface/core/render/chart/render_single.py +347 -0
- dataface/core/render/chart/renderers.py +193 -0
- dataface/core/render/chart/rendering.py +565 -0
- dataface/core/render/chart/serialization.py +90 -0
- dataface/core/render/chart/spark.py +496 -0
- dataface/core/render/chart/spark_bar.py +370 -0
- dataface/core/render/chart/spec_builders.py +154 -0
- dataface/core/render/chart/standard_renderer.py +2645 -0
- dataface/core/render/chart/table.py +2957 -0
- dataface/core/render/chart/table_support.py +1452 -0
- dataface/core/render/chart/tick_values.py +66 -0
- dataface/core/render/chart/time_unit_detect.py +809 -0
- dataface/core/render/chart/title_overflow.py +157 -0
- dataface/core/render/chart/type_inference.py +122 -0
- dataface/core/render/chart/validation.py +99 -0
- dataface/core/render/chart/vega_lite.py +125 -0
- dataface/core/render/chart/vega_lite_types.py +268 -0
- dataface/core/render/chart/vl_field_maps.py +346 -0
- dataface/core/render/chart_interactivity.py +24 -0
- dataface/core/render/control_registry.py +287 -0
- dataface/core/render/converters/__init__.py +24 -0
- dataface/core/render/converters/chart.py +276 -0
- dataface/core/render/converters/html.py +98 -0
- dataface/core/render/converters/pdf.py +40 -0
- dataface/core/render/converters/png.py +41 -0
- dataface/core/render/errors.py +144 -0
- dataface/core/render/face_api.py +160 -0
- dataface/core/render/faces.py +1194 -0
- dataface/core/render/font_measurement.py +48 -0
- dataface/core/render/font_support.py +197 -0
- dataface/core/render/fonts/DFTSansTabular-Regular.ttf +0 -0
- dataface/core/render/fonts/DFTSansTabular-Regular.woff2 +0 -0
- dataface/core/render/fonts/DFTSerifOldstyleProportional-Regular.ttf +0 -0
- dataface/core/render/fonts/DFTSerifOldstyleTabular-Regular.ttf +0 -0
- dataface/core/render/fonts/InterVariable.ttf +0 -0
- dataface/core/render/fonts/InterVariable.woff2 +0 -0
- dataface/core/render/fonts/NOTO_COLOR_EMOJI_LICENSE.txt +93 -0
- dataface/core/render/fonts/NOTO_EMOJI_LICENSE.txt +93 -0
- dataface/core/render/fonts/NotoColorEmoji-Regular.ttf +0 -0
- dataface/core/render/fonts/NotoColorEmoji-Regular.woff2 +0 -0
- dataface/core/render/fonts/NotoEmoji-Regular.ttf +0 -0
- dataface/core/render/fonts/NotoEmoji-Regular.woff2 +0 -0
- dataface/core/render/fonts/SOURCE_CODE_PRO_LICENSE.txt +93 -0
- dataface/core/render/fonts/SOURCE_SERIF_4_LICENSE.txt +98 -0
- dataface/core/render/fonts/SourceCodePro-Regular.ttf +0 -0
- dataface/core/render/fonts/SourceSerif4-Regular.ttf +0 -0
- dataface/core/render/fonts/_emoji_font_face.css +43 -0
- dataface/core/render/fonts/source-serif-4-variable-latin.woff2 +0 -0
- dataface/core/render/format_utils.py +329 -0
- dataface/core/render/geo_defaults.yml +28 -0
- dataface/core/render/json_format.py +146 -0
- dataface/core/render/layout_sizing.py +865 -0
- dataface/core/render/layouts.py +541 -0
- dataface/core/render/markdown_defaults.yml +16 -0
- dataface/core/render/missing_vars_prompt.py +79 -0
- dataface/core/render/placeholder.py +389 -0
- dataface/core/render/render_result.py +14 -0
- dataface/core/render/renderer.py +467 -0
- dataface/core/render/script_embedding.py +16 -0
- dataface/core/render/svg_utils.py +212 -0
- dataface/core/render/template_loader.py +69 -0
- dataface/core/render/templates/controls/_styles.css +606 -0
- dataface/core/render/templates/controls/checkbox.html +16 -0
- dataface/core/render/templates/controls/date.html +16 -0
- dataface/core/render/templates/controls/number.html +19 -0
- dataface/core/render/templates/controls/readonly.html +9 -0
- dataface/core/render/templates/controls/select.html +21 -0
- dataface/core/render/templates/controls/slider.html +22 -0
- dataface/core/render/templates/controls/text.html +16 -0
- dataface/core/render/templates/scripts/chart_interactivity.js +191 -0
- dataface/core/render/templates/scripts/variables.js +976 -0
- dataface/core/render/templates/svg/grid_pattern.svg +3 -0
- dataface/core/render/templates/svg/styles.css +51 -0
- dataface/core/render/terminal.py +311 -0
- dataface/core/render/terminal_charts.py +563 -0
- dataface/core/render/terminal_defaults.yml +2 -0
- dataface/core/render/terminal_layouts.py +299 -0
- dataface/core/render/terminal_text.py +31 -0
- dataface/core/render/text/__init__.py +1 -0
- dataface/core/render/text/case.py +113 -0
- dataface/core/render/text_format.py +129 -0
- dataface/core/render/utils.py +106 -0
- dataface/core/render/variable_controls.py +946 -0
- dataface/core/render/variable_input_refinement.py +140 -0
- dataface/core/render/warnings/__init__.py +15 -0
- dataface/core/render/warnings/bar_color_1_to_1_with_x.py +80 -0
- dataface/core/render/warnings/base.py +44 -0
- dataface/core/render/warnings/fanout_risk.py +15 -0
- dataface/core/render/warnings/from_query_diagnostic.py +56 -0
- dataface/core/render/warnings/missing_join_predicate.py +13 -0
- dataface/core/render/warnings/query_parse_error.py +14 -0
- dataface/core/render/warnings/query_returned_zero_rows.py +42 -0
- dataface/core/render/warnings/reaggregation.py +14 -0
- dataface/core/render/warnings/registry.py +45 -0
- dataface/core/render/warnings/suppression.py +46 -0
- dataface/core/render/warnings/temporal_single_point.py +63 -0
- dataface/core/render/warnings/unreferenced_chart.py +15 -0
- dataface/core/render/warnings/y_encoding_mostly_null.py +76 -0
- dataface/core/render/yaml_format.py +167 -0
- dataface/core/resolve_face.py +195 -0
- dataface/core/schema/__init__.py +0 -0
- dataface/core/schema/guidance.py +151 -0
- dataface/core/scoped_paths.py +59 -0
- dataface/core/serve/__init__.py +14 -0
- dataface/core/serve/bootstrap.py +39 -0
- dataface/core/serve/embedded.py +57 -0
- dataface/core/serve/port.py +129 -0
- dataface/core/serve/server.py +938 -0
- dataface/core/serve/templates/__init__.py +0 -0
- dataface/core/serve/templates/directory.yml +6 -0
- dataface/core/serve/templates/error.html.j2 +217 -0
- dataface/core/utils.py +121 -0
- dataface/core/validate.py +64 -0
- dataface/integrations/__init__.py +0 -0
- dataface/integrations/highlighting.py +351 -0
- dataface/integrations/markdown.py +537 -0
- dataface/py.typed +0 -0
- dataface-0.1.2.dist-info/METADATA +375 -0
- dataface-0.1.2.dist-info/RECORD +455 -0
- dataface-0.1.2.dist-info/WHEEL +4 -0
- dataface-0.1.2.dist-info/entry_points.txt +2 -0
- dataface-0.1.2.dist-info/licenses/LICENSE +202 -0
- mdsvg/__init__.py +168 -0
- mdsvg/fonts.py +656 -0
- mdsvg/images.py +299 -0
- mdsvg/parser.py +629 -0
- mdsvg/playground.py +284 -0
- mdsvg/py.typed +2 -0
- mdsvg/renderer.py +1623 -0
- mdsvg/style.py +355 -0
- mdsvg/types.py +200 -0
- mdsvg/utils.py +86 -0
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: kpi-row
|
|
3
|
+
kind: pattern
|
|
4
|
+
description: >
|
|
5
|
+
Pattern for a row of 3–5 KPI cards at the top of a face. Use when showing
|
|
6
|
+
summary metrics (revenue, orders, conversion rate, avg order value) from a
|
|
7
|
+
single aggregated query. Triggers on: 'KPI row', 'summary metrics', 'top
|
|
8
|
+
metrics', 'hero numbers', 'scorecard'. Each KPI needs a separate single-row
|
|
9
|
+
query OR one query with multiple columns. Do NOT use for time-series trends
|
|
10
|
+
(use time-series-trend). Do NOT use for a single hero metric (use
|
|
11
|
+
single-metric-bignum). Do NOT use if the data has more than 1 row per KPI.
|
|
12
|
+
metadata:
|
|
13
|
+
author: fivetran
|
|
14
|
+
---
|
|
15
|
+
|
|
16
|
+
# KPI Row
|
|
17
|
+
|
|
18
|
+
A horizontal row of 3–5 KPI cards placed at the top of a face. Each KPI
|
|
19
|
+
displays one aggregate value (a number, currency, or percent) with a label and
|
|
20
|
+
an optional prior-period delta in the support row.
|
|
21
|
+
|
|
22
|
+
## When to reach for this
|
|
23
|
+
|
|
24
|
+
- The face opens with a "how are we doing overall?" summary before detail charts
|
|
25
|
+
- You have 3–5 numeric aggregates drawn from the same time window
|
|
26
|
+
- Some metrics have a prior-period comparison to show trend direction
|
|
27
|
+
|
|
28
|
+
## When NOT to use this
|
|
29
|
+
|
|
30
|
+
- Single hero metric with a sparkline → use `single-metric-bignum`
|
|
31
|
+
- Data has multiple rows per KPI → aggregate to one row first
|
|
32
|
+
- More than 6 KPIs → split into two rows or a `two-by-two-grid-overview`
|
|
33
|
+
|
|
34
|
+
## The pattern
|
|
35
|
+
|
|
36
|
+
```yaml
|
|
37
|
+
queries:
|
|
38
|
+
kpis:
|
|
39
|
+
columns: [revenue, orders, avg_order, rev_delta, ord_delta]
|
|
40
|
+
values: [[248500, 1420, 175, 0.12, 0.08]]
|
|
41
|
+
|
|
42
|
+
charts:
|
|
43
|
+
revenue_kpi:
|
|
44
|
+
type: kpi
|
|
45
|
+
query: kpis
|
|
46
|
+
label: Revenue
|
|
47
|
+
value: revenue
|
|
48
|
+
format: currency_whole
|
|
49
|
+
support:
|
|
50
|
+
value: rev_delta
|
|
51
|
+
label: vs last period
|
|
52
|
+
format: percent_delta
|
|
53
|
+
glyph: "▲"
|
|
54
|
+
tone: positive
|
|
55
|
+
|
|
56
|
+
orders_kpi:
|
|
57
|
+
type: kpi
|
|
58
|
+
query: kpis
|
|
59
|
+
label: Orders
|
|
60
|
+
value: orders
|
|
61
|
+
support:
|
|
62
|
+
value: ord_delta
|
|
63
|
+
label: vs last period
|
|
64
|
+
format: percent_delta
|
|
65
|
+
glyph: "▲"
|
|
66
|
+
tone: positive
|
|
67
|
+
|
|
68
|
+
rows:
|
|
69
|
+
- height: 120
|
|
70
|
+
cols: [revenue_kpi, orders_kpi]
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
See `examples/kpi-row.yml` for the full 3-KPI worked example.
|
|
74
|
+
|
|
75
|
+
## Variations
|
|
76
|
+
|
|
77
|
+
| Variation | YAML knob | When |
|
|
78
|
+
|---|---|---|
|
|
79
|
+
| No delta | omit `support:` | Prior period not available |
|
|
80
|
+
| Currency | `format: currency_whole` | Revenue, spend, cost |
|
|
81
|
+
| Percent | `format: percent` | Rate, conversion, margin |
|
|
82
|
+
| Negative delta | `tone: negative`, `glyph: "▼"` | Unfavorable direction |
|
|
83
|
+
| Fixed row height | `height: 120` on the row | Prevent KPIs growing taller than charts below |
|
|
84
|
+
|
|
85
|
+
## Common pitfalls
|
|
86
|
+
|
|
87
|
+
| Pitfall | Why it breaks | Fix |
|
|
88
|
+
|---|---|---|
|
|
89
|
+
| Query returns multiple rows | `ChartDataError` — KPI expects exactly 1 row | Add `SUM()`/`COUNT()` to aggregate to one row |
|
|
90
|
+
| Delta column missing from query | Render error — column not found | Include delta columns in the same query |
|
|
91
|
+
| `glyph: "▲"` without `tone:` | Arrow renders but no semantic color | Add `tone: positive` or `tone: negative` |
|
|
92
|
+
| Overloaded label | Hard to scan at a glance | ≤ 3 words per label |
|
|
93
|
+
|
|
94
|
+
## Worked example
|
|
95
|
+
|
|
96
|
+
See `examples/kpi-row.yml` — three KPIs (Revenue, Orders, Avg Order Value)
|
|
97
|
+
from one inline-data query. Compiles and renders without a warehouse.
|
|
98
|
+
|
|
99
|
+
## YAML Reference
|
|
100
|
+
|
|
101
|
+
For syntax and field details: {{ s_yaml_reference_footer }}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
title: Q1 Sales Summary
|
|
2
|
+
description: KPI row pattern — three summary metrics from one aggregated query
|
|
3
|
+
|
|
4
|
+
queries:
|
|
5
|
+
kpis:
|
|
6
|
+
description: Single-row aggregate with current values and prior-period deltas
|
|
7
|
+
columns: [revenue, orders, avg_order, rev_delta, ord_delta, aov_delta]
|
|
8
|
+
values:
|
|
9
|
+
- [248500, 1420, 175, 0.12, 0.08, 0.04]
|
|
10
|
+
|
|
11
|
+
charts:
|
|
12
|
+
revenue_kpi:
|
|
13
|
+
type: kpi
|
|
14
|
+
query: kpis
|
|
15
|
+
label: Revenue
|
|
16
|
+
value: revenue
|
|
17
|
+
format: currency_whole
|
|
18
|
+
support:
|
|
19
|
+
value: rev_delta
|
|
20
|
+
label: vs last quarter
|
|
21
|
+
format: percent_delta
|
|
22
|
+
glyph: "▲"
|
|
23
|
+
tone: positive
|
|
24
|
+
|
|
25
|
+
orders_kpi:
|
|
26
|
+
type: kpi
|
|
27
|
+
query: kpis
|
|
28
|
+
label: Orders
|
|
29
|
+
value: orders
|
|
30
|
+
support:
|
|
31
|
+
value: ord_delta
|
|
32
|
+
label: vs last quarter
|
|
33
|
+
format: percent_delta
|
|
34
|
+
glyph: "▲"
|
|
35
|
+
tone: positive
|
|
36
|
+
|
|
37
|
+
aov_kpi:
|
|
38
|
+
type: kpi
|
|
39
|
+
query: kpis
|
|
40
|
+
label: Avg Order Value
|
|
41
|
+
value: avg_order
|
|
42
|
+
format: currency
|
|
43
|
+
support:
|
|
44
|
+
value: aov_delta
|
|
45
|
+
label: vs last quarter
|
|
46
|
+
format: percent_delta
|
|
47
|
+
glyph: "▲"
|
|
48
|
+
tone: positive
|
|
49
|
+
|
|
50
|
+
rows:
|
|
51
|
+
- height: 120
|
|
52
|
+
cols:
|
|
53
|
+
- revenue_kpi
|
|
54
|
+
- orders_kpi
|
|
55
|
+
- aov_kpi
|
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: report-design
|
|
3
|
+
kind: workflow
|
|
4
|
+
description: >
|
|
5
|
+
Design principles for Dataface narrative reports — data-driven documents
|
|
6
|
+
that answer specific questions. Use when creating analyses, investigations,
|
|
7
|
+
periodic reports, or when the user says 'write a report', 'analyze this
|
|
8
|
+
data', 'create an analysis', 'narrative report'. Covers narrative
|
|
9
|
+
structure, chart selection for reports, content writing, and the
|
|
10
|
+
executive-summary-first pattern. Do NOT use for at-a-glance monitoring
|
|
11
|
+
dashboards (use dashboard-design). Do NOT use for the
|
|
12
|
+
build-test-iterate workflow (use dashboard-build).
|
|
13
|
+
metadata:
|
|
14
|
+
author: fivetran
|
|
15
|
+
---
|
|
16
|
+
|
|
17
|
+
# Report Design
|
|
18
|
+
|
|
19
|
+
Reports are narrative-driven documents that tell a story with data and answer specific questions. They are NOT dashboards.
|
|
20
|
+
|
|
21
|
+
> Implementing in YAML? Switch to `{{ s_skill_build }}` for the build-test-iterate workflow.
|
|
22
|
+
|
|
23
|
+
## Report vs. Dashboard
|
|
24
|
+
|
|
25
|
+
| | Report | Dashboard |
|
|
26
|
+
|--|--------|-----------|
|
|
27
|
+
| **Purpose** | Answer a question, tell a story | Monitor status at a glance |
|
|
28
|
+
| **Text** | Extensive — narrative + recommendations | Minimal — titles and labels |
|
|
29
|
+
| **Charts** | Support the narrative (3-6 typically) | ARE the content |
|
|
30
|
+
| **Structure** | Executive summary → analysis → conclusions | KPIs → trends → breakdowns |
|
|
31
|
+
| **Interaction** | Read in minutes | Scan in seconds |
|
|
32
|
+
|
|
33
|
+
If the user needs at-a-glance monitoring, use the `dashboard-design` skill instead.
|
|
34
|
+
|
|
35
|
+
## Core Principles
|
|
36
|
+
|
|
37
|
+
1. **Answer the question first** — lead with the conclusion, not the methodology
|
|
38
|
+
2. **Every chart serves the narrative** — no chart without explanatory text above it
|
|
39
|
+
3. **Tell a story** — setting (context) → conflict (problem/question) → resolution (findings + recommendations)
|
|
40
|
+
4. **Be specific** — "Revenue dropped 12% because Region X lost 3 key accounts" not "Revenue decreased"
|
|
41
|
+
5. **Professional tone** — direct, concise, active voice
|
|
42
|
+
|
|
43
|
+
## Metadata Requirement
|
|
44
|
+
|
|
45
|
+
When producing Dataface YAML, include `description` metadata for AI context/search:
|
|
46
|
+
|
|
47
|
+
- `queries.*.description`: query purpose
|
|
48
|
+
- `charts.*.description`: what evidence the chart provides
|
|
49
|
+
- `variables.*.description`: filter meaning (if variables are present)
|
|
50
|
+
- Layout object `description` fields (`rows`/`cols`/`grid.items`/`tabs.items`) where section context helps
|
|
51
|
+
|
|
52
|
+
## Narrative Structure
|
|
53
|
+
|
|
54
|
+
Every report follows this arc:
|
|
55
|
+
|
|
56
|
+
```
|
|
57
|
+
1. EXECUTIVE SUMMARY
|
|
58
|
+
- 2-3 sentences with key findings
|
|
59
|
+
- Recommendation in bold
|
|
60
|
+
- The answer, upfront
|
|
61
|
+
|
|
62
|
+
2. CONTEXT
|
|
63
|
+
- Time period, scope, data sources
|
|
64
|
+
- Why this analysis was needed
|
|
65
|
+
|
|
66
|
+
3. ANALYSIS SECTIONS (2-4)
|
|
67
|
+
- Each section: one finding
|
|
68
|
+
- Pattern: State finding → explain significance → show chart evidence
|
|
69
|
+
- Transition between sections
|
|
70
|
+
|
|
71
|
+
4. CONCLUSIONS & RECOMMENDATIONS
|
|
72
|
+
- Numbered, specific, actionable (who/what/when)
|
|
73
|
+
- Quantify expected impact when possible
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
## Chart Selection for Reports
|
|
77
|
+
|
|
78
|
+
Reports use fewer charts than dashboards. Each must be referenced in the narrative:
|
|
79
|
+
|
|
80
|
+
| Report Need | Chart Type | Example Narrative |
|
|
81
|
+
|-------------|-----------|-------------------|
|
|
82
|
+
| The trend that tells the story | `line` | "Revenue has been declining since March" |
|
|
83
|
+
| Segments that matter | `bar` | "Region X underperformed by 23%" |
|
|
84
|
+
| A key metric | `kpi` | "Total impact: $2.3M" |
|
|
85
|
+
| Detailed breakdown | `table` | "Here are the top 10 affected accounts" |
|
|
86
|
+
| Composition change | `area` (stacked) | "The product mix shifted toward lower-margin items" |
|
|
87
|
+
|
|
88
|
+
**Prefer:** Fewer charts with more text. Tables for evidence. KPIs for anchoring key numbers.
|
|
89
|
+
|
|
90
|
+
**Avoid:** Many KPIs in a row (dashboard pattern). Charts without narrative context. Interactive filters (reports present a specific analysis).
|
|
91
|
+
|
|
92
|
+
## Writing Content
|
|
93
|
+
|
|
94
|
+
Use `text:` blocks in YAML for narrative text (Markdown).
|
|
95
|
+
|
|
96
|
+
**Opening each section:**
|
|
97
|
+
- State the finding first
|
|
98
|
+
- Explain why it matters
|
|
99
|
+
- Introduce the chart
|
|
100
|
+
|
|
101
|
+
**Closing each section:**
|
|
102
|
+
- Summarize the implication
|
|
103
|
+
- Transition to the next section
|
|
104
|
+
|
|
105
|
+
**Tone guidelines:**
|
|
106
|
+
- Active voice: "Revenue declined" not "A decline was observed"
|
|
107
|
+
- Specific numbers: "12% decline" not "significant decrease"
|
|
108
|
+
- No filler: Cut "It's worth noting that..." — just note it
|
|
109
|
+
- Honest about uncertainty where data doesn't fully support a claim
|
|
110
|
+
|
|
111
|
+
## YAML Structure for Reports
|
|
112
|
+
|
|
113
|
+
Reports use heavier `text:` usage than dashboards:
|
|
114
|
+
|
|
115
|
+
```yaml
|
|
116
|
+
title: "Q3 Revenue Analysis"
|
|
117
|
+
source: warehouse
|
|
118
|
+
|
|
119
|
+
queries:
|
|
120
|
+
revenue_trend:
|
|
121
|
+
sql: SELECT month, revenue FROM monthly_revenue ORDER BY month
|
|
122
|
+
|
|
123
|
+
charts:
|
|
124
|
+
trend:
|
|
125
|
+
query: revenue_trend
|
|
126
|
+
type: line
|
|
127
|
+
x: month
|
|
128
|
+
y: revenue
|
|
129
|
+
|
|
130
|
+
rows:
|
|
131
|
+
- text: |
|
|
132
|
+
## Executive Summary
|
|
133
|
+
Q3 revenue declined 12% quarter-over-quarter, driven primarily
|
|
134
|
+
by the loss of three enterprise accounts in the West region.
|
|
135
|
+
**Recommendation: Prioritize retention program for accounts >$100K ARR.**
|
|
136
|
+
|
|
137
|
+
- text: |
|
|
138
|
+
## Revenue Trend
|
|
139
|
+
Monthly revenue peaked in June and has declined each month since.
|
|
140
|
+
- trend
|
|
141
|
+
|
|
142
|
+
- text: |
|
|
143
|
+
## Conclusions
|
|
144
|
+
1. Launch retention program for enterprise accounts by end of month
|
|
145
|
+
2. Investigate West region account manager capacity
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
Key differences from dashboard YAML:
|
|
149
|
+
- Heavy `text:` blocks with narrative
|
|
150
|
+
- Fewer charts (3-6), more text
|
|
151
|
+
- No `variables:` — reports present a specific analysis
|
|
152
|
+
- Top-level flow follows the narrative arc
|
|
153
|
+
|
|
154
|
+
## Quality Checklist
|
|
155
|
+
|
|
156
|
+
- [ ] Answers the question in the executive summary
|
|
157
|
+
- [ ] Executive summary comes first (conclusion before methodology)
|
|
158
|
+
- [ ] Every chart has narrative context above it
|
|
159
|
+
- [ ] Findings are specific (numbers, percentages, comparisons)
|
|
160
|
+
- [ ] Recommendations are actionable (who/what/when)
|
|
161
|
+
- [ ] Story flows logically section to section
|
|
162
|
+
- [ ] Appropriate length (3-6 analysis sections)
|
|
163
|
+
- [ ] Professional tone (direct, specific, active voice)
|
|
164
|
+
- [ ] Query/chart/variable/layout `description` metadata is filled for AI context
|
|
165
|
+
|
|
166
|
+
## Common Mistakes
|
|
167
|
+
|
|
168
|
+
| Mistake | Fix |
|
|
169
|
+
|---------|-----|
|
|
170
|
+
| Methodology before conclusions | Lead with the answer — executives read top-down |
|
|
171
|
+
| Chart without narrative context | Every chart needs explanatory text above it |
|
|
172
|
+
| Vague findings ("revenue decreased") | Be specific: "revenue declined 12% QoQ" |
|
|
173
|
+
| Dashboard patterns in a report (KPI row) | Reports use narrative flow, not monitoring layout |
|
|
174
|
+
| Too many charts | 3-6 max — each must serve the story |
|
|
175
|
+
| Hedging without reason | Be confident where data supports it |
|
|
176
|
+
|
|
177
|
+
## Rationalizations to Resist
|
|
178
|
+
|
|
179
|
+
| Excuse | Reality |
|
|
180
|
+
|--------|---------|
|
|
181
|
+
| "User wants the methodology first" | They don't. They want the answer. Methodology can follow. |
|
|
182
|
+
| "Adding more charts shows thoroughness" | It shows clutter. Every chart must serve the narrative. |
|
|
183
|
+
| "I'll add filters so they can explore" | That's a dashboard. Reports present a specific analysis. |
|
|
184
|
+
| "The data speaks for itself" | It never does. Interpret it — that's the report's job. |
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: single-metric-bignum
|
|
3
|
+
kind: pattern
|
|
4
|
+
description: >
|
|
5
|
+
Pattern for a single hero KPI displayed at large scale with a prior-period
|
|
6
|
+
delta in the support row. Use when one metric is the primary signal of the
|
|
7
|
+
face and should visually dominate. Triggers on: 'hero metric', 'big number',
|
|
8
|
+
'single KPI', 'headline metric', 'north star', 'key metric', 'monthly
|
|
9
|
+
recurring revenue', 'MRR'. Optionally add a sparkline for trend context.
|
|
10
|
+
Do NOT use for three or more metrics (use kpi-row). Do NOT use when the
|
|
11
|
+
chart type is more important than the number (use time-series-trend).
|
|
12
|
+
metadata:
|
|
13
|
+
author: fivetran
|
|
14
|
+
---
|
|
15
|
+
|
|
16
|
+
# Single-Metric Bignum
|
|
17
|
+
|
|
18
|
+
One KPI rendered at the largest readable size, backed by a one-row query,
|
|
19
|
+
with a support row showing the prior-period delta. The visual emphasis signals
|
|
20
|
+
"this is what matters most on this face."
|
|
21
|
+
|
|
22
|
+
## When to reach for this
|
|
23
|
+
|
|
24
|
+
- A face exists to answer one question: "what is our MRR today?"
|
|
25
|
+
- The metric is a North Star that stakeholders check every day
|
|
26
|
+
- You want delta context (up X% vs last period) without a full chart
|
|
27
|
+
|
|
28
|
+
## When NOT to use this
|
|
29
|
+
|
|
30
|
+
- Three or more equally-important metrics → `kpi-row`
|
|
31
|
+
- Trend history is the point, not the current value → `time-series-trend`
|
|
32
|
+
- Sparkline is critical (needs array data) → note this in the face description
|
|
33
|
+
|
|
34
|
+
## The pattern
|
|
35
|
+
|
|
36
|
+
```yaml
|
|
37
|
+
queries:
|
|
38
|
+
hero:
|
|
39
|
+
# Compute current and prior totals upstream (e.g. in your dbt model) and
|
|
40
|
+
# select two columns. Inline window math against an aggregate row tends
|
|
41
|
+
# to break across warehouses — keep this query trivial.
|
|
42
|
+
sql: |
|
|
43
|
+
SELECT mrr, prior_mrr, (mrr - prior_mrr) / prior_mrr AS delta
|
|
44
|
+
FROM mrr_summary
|
|
45
|
+
|
|
46
|
+
charts:
|
|
47
|
+
mrr_kpi:
|
|
48
|
+
type: kpi
|
|
49
|
+
query: hero
|
|
50
|
+
label: Monthly Recurring Revenue
|
|
51
|
+
value: mrr
|
|
52
|
+
format: "$,.2s" # e.g. $1.84M
|
|
53
|
+
support:
|
|
54
|
+
value: delta
|
|
55
|
+
label: vs last month
|
|
56
|
+
format: "+.1%"
|
|
57
|
+
glyph: "▲"
|
|
58
|
+
tone: positive # positive / negative / warning
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
See `examples/single-metric-bignum.yml` for the worked example.
|
|
62
|
+
|
|
63
|
+
## Variations
|
|
64
|
+
|
|
65
|
+
| Variation | YAML knob | When |
|
|
66
|
+
|---|---|---|
|
|
67
|
+
| Large currency | `format: "$,.2s"` | Millions/billions (e.g., `$1.84M`) |
|
|
68
|
+
| Plain count | `format: ",.0f"` | Raw integer |
|
|
69
|
+
| Percent | `format: ".1%"` | Conversion rate, margin |
|
|
70
|
+
| Negative delta | `tone: negative`, `glyph: "▼"` | Unfavorable direction |
|
|
71
|
+
| Status string | `query: { rows: [{ status: "On track" }] }` + `value: status` | Qualitative health status |
|
|
72
|
+
| Sparkline | add a `spark` column in the query (array type) | Requires a warehouse that supports arrays |
|
|
73
|
+
|
|
74
|
+
## Common pitfalls
|
|
75
|
+
|
|
76
|
+
| Pitfall | Why it breaks | Fix |
|
|
77
|
+
|---|---|---|
|
|
78
|
+
| Query returns multiple rows | ChartDataError | Use `SUM()`/`MAX()` to collapse to exactly 1 row |
|
|
79
|
+
| `format: "$,.2s"` on a small number | Rounds aggressively (e.g. `$175` → `$0.00k`) | Use `"$,.0f"` for values under $10k |
|
|
80
|
+
| `tone:` without `glyph:` | Delta has semantic color but no directional icon | Add `glyph: "▲"` or `"▼"` |
|
|
81
|
+
| Overlong label | Label wraps awkwardly at large sizes | ≤ 4 words |
|
|
82
|
+
|
|
83
|
+
## Worked example
|
|
84
|
+
|
|
85
|
+
See `examples/single-metric-bignum.yml` — a hero MRR KPI with a +14.2%
|
|
86
|
+
support row. Inline data, no warehouse required.
|
|
87
|
+
|
|
88
|
+
## YAML Reference
|
|
89
|
+
|
|
90
|
+
For syntax and field details: {{ s_yaml_reference_footer }}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
title: Monthly Recurring Revenue
|
|
2
|
+
description: Single-metric bignum pattern — hero KPI with prior-period delta support row
|
|
3
|
+
|
|
4
|
+
queries:
|
|
5
|
+
hero:
|
|
6
|
+
description: Current MRR and month-over-month growth rate
|
|
7
|
+
columns: [mrr, delta_pct]
|
|
8
|
+
values:
|
|
9
|
+
- [1840000, 0.142]
|
|
10
|
+
|
|
11
|
+
charts:
|
|
12
|
+
mrr_kpi:
|
|
13
|
+
description: Hero MRR metric with month-over-month delta
|
|
14
|
+
type: kpi
|
|
15
|
+
query: hero
|
|
16
|
+
label: Monthly Recurring Revenue
|
|
17
|
+
value: mrr
|
|
18
|
+
format: currency_compact
|
|
19
|
+
support:
|
|
20
|
+
value: delta_pct
|
|
21
|
+
label: vs last month
|
|
22
|
+
format: percent_delta
|
|
23
|
+
glyph: "▲"
|
|
24
|
+
tone: positive
|
|
25
|
+
|
|
26
|
+
rows:
|
|
27
|
+
- mrr_kpi
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: table-heavy-ops-dashboard
|
|
3
|
+
kind: pattern
|
|
4
|
+
description: >
|
|
5
|
+
Pattern for operational dashboards dominated by sortable tables with
|
|
6
|
+
per-column formatting, labels, and conditional formatting. Use when users
|
|
7
|
+
need to monitor status, triage incidents, or review row-level data with
|
|
8
|
+
currency/percent/date formatting and visual severity cues. Triggers on:
|
|
9
|
+
'ops dashboard', 'incident table', 'ticket queue', 'status monitor',
|
|
10
|
+
'formatted table', 'sortable list', 'operational view'. Do NOT use when a
|
|
11
|
+
chart communicates the pattern better (use top-n-with-detail for rankings).
|
|
12
|
+
Do NOT use for purely aggregated summaries (use kpi-row or
|
|
13
|
+
two-by-two-grid-overview).
|
|
14
|
+
metadata:
|
|
15
|
+
author: fivetran
|
|
16
|
+
---
|
|
17
|
+
|
|
18
|
+
# Table-Heavy Ops Dashboard
|
|
19
|
+
|
|
20
|
+
An operational view where one or more tables dominate. Each table uses
|
|
21
|
+
`style.columns` to configure labels, number formats, and per-column widths.
|
|
22
|
+
Conditional formatting adds severity colors without changing the data.
|
|
23
|
+
|
|
24
|
+
## When to reach for this
|
|
25
|
+
|
|
26
|
+
- Users need to scan, sort, and triage rows (incidents, tickets, pipelines)
|
|
27
|
+
- Columns have mixed types: currency, percent, status strings, dates
|
|
28
|
+
- Severity or thresholds matter (P1 red, P2 yellow, resolved grey)
|
|
29
|
+
|
|
30
|
+
## When NOT to use this
|
|
31
|
+
|
|
32
|
+
- Data is better shown as a chart → pair with `top-n-with-detail`
|
|
33
|
+
- Data has only 1–5 aggregated rows → use `kpi-row` instead
|
|
34
|
+
- Table has hundreds of columns → subset in SQL first
|
|
35
|
+
|
|
36
|
+
## The pattern
|
|
37
|
+
|
|
38
|
+
```yaml
|
|
39
|
+
charts:
|
|
40
|
+
incidents:
|
|
41
|
+
type: table
|
|
42
|
+
query: open_incidents
|
|
43
|
+
title: Open Incidents
|
|
44
|
+
style:
|
|
45
|
+
columns:
|
|
46
|
+
- column: ticket_id
|
|
47
|
+
label: Ticket
|
|
48
|
+
- column: priority
|
|
49
|
+
label: Priority
|
|
50
|
+
- column: status
|
|
51
|
+
label: Status
|
|
52
|
+
- column: revenue_impact
|
|
53
|
+
label: Revenue Impact
|
|
54
|
+
format: "$,.0f"
|
|
55
|
+
align: right
|
|
56
|
+
width: 140
|
|
57
|
+
- column: created_at
|
|
58
|
+
label: Opened
|
|
59
|
+
format: "%Y-%m-%d"
|
|
60
|
+
header_overflow: wrap-two
|
|
61
|
+
conditional_formatting:
|
|
62
|
+
priority:
|
|
63
|
+
when:
|
|
64
|
+
- eq: P1
|
|
65
|
+
background: "#fee2e2"
|
|
66
|
+
font:
|
|
67
|
+
color: "#991b1b"
|
|
68
|
+
weight: "600"
|
|
69
|
+
- eq: P2
|
|
70
|
+
background: "#fef3c7"
|
|
71
|
+
font:
|
|
72
|
+
color: "#92400e"
|
|
73
|
+
- default: true
|
|
74
|
+
font:
|
|
75
|
+
color: "#334155"
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
See `examples/table-heavy-ops-dashboard.yml` for the inline-data worked example.
|
|
79
|
+
|
|
80
|
+
## Variations
|
|
81
|
+
|
|
82
|
+
| Variation | YAML knob | When |
|
|
83
|
+
|---|---|---|
|
|
84
|
+
| Currency column | `format: "$,.0f"` | Revenue, cost, spend |
|
|
85
|
+
| Percent column | `format: ".1%"` | Rate, margin, conversion |
|
|
86
|
+
| Date column | `format: "%Y-%m-%d"` | ISO dates |
|
|
87
|
+
| Link cell | `link: "/detail?id={{ ticket_id }}"` | Click-through to detail |
|
|
88
|
+
| Header wrapping | `header_overflow: wrap-two` | Long column labels |
|
|
89
|
+
| Spark cell | `spark: line` or `spark.type: bar-normalize` | Trend arrays or % values |
|
|
90
|
+
| Continuous color | `scale.background.palette` | Numeric intensity |
|
|
91
|
+
| Header style | `style.table.header.*` | BI or minimal header tone |
|
|
92
|
+
|
|
93
|
+
## Common pitfalls
|
|
94
|
+
|
|
95
|
+
| Pitfall | Why it breaks | Fix |
|
|
96
|
+
|---|---|---|
|
|
97
|
+
| Too many columns | Hard to scan, horizontal scroll | Limit to 6–8 most important columns |
|
|
98
|
+
| Formatting strings not D3/Excel format | Wrong output | Use D3 format specs: `"$,.0f"`, `".1%"` |
|
|
99
|
+
| Conditional rule with no style override | `ConditionalRule` validation error | Set `background:`, `font.color`, `font.weight`, or `glyph:` on each rule |
|
|
100
|
+
| Sorting expectation mismatch | Default sort is query order | Add `ORDER BY priority` in SQL for triage queues |
|
|
101
|
+
|
|
102
|
+
Conditional predicates are `eq`, `ne`, `lt`, `lte`, `gt`, `gte`, `between`,
|
|
103
|
+
`in`, `is_null`, and `default`. Use `in:` in YAML, not `in_:`. `default: true`
|
|
104
|
+
must be the last rule.
|
|
105
|
+
|
|
106
|
+
## Worked example
|
|
107
|
+
|
|
108
|
+
See `examples/table-heavy-ops-dashboard.yml` — five incident rows with
|
|
109
|
+
priority, status, revenue impact, and owner columns. Inline data, no warehouse
|
|
110
|
+
needed.
|
|
111
|
+
|
|
112
|
+
## YAML Reference
|
|
113
|
+
|
|
114
|
+
For syntax and field details: {{ s_yaml_reference_footer }}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
title: Incident Queue
|
|
2
|
+
description: Table-heavy ops dashboard pattern — formatted table with per-column labels and types
|
|
3
|
+
|
|
4
|
+
queries:
|
|
5
|
+
open_incidents:
|
|
6
|
+
description: Open and in-progress incidents with severity and impact
|
|
7
|
+
columns: [ticket_id, priority, status, assignee, revenue_impact]
|
|
8
|
+
values:
|
|
9
|
+
- ["T-001", "P1", "Open", "Alice", 15000]
|
|
10
|
+
- ["T-002", "P2", "In Progress", "Bob", 4500]
|
|
11
|
+
- ["T-003", "P1", "Open", "Carol", 22000]
|
|
12
|
+
- ["T-004", "P3", "Resolved", "Dave", 800]
|
|
13
|
+
- ["T-005", "P2", "In Progress", "Alice", 7200]
|
|
14
|
+
|
|
15
|
+
charts:
|
|
16
|
+
incidents_table:
|
|
17
|
+
description: Triageable incident list with priority, owner, and revenue impact
|
|
18
|
+
type: table
|
|
19
|
+
query: open_incidents
|
|
20
|
+
title: Open Incidents
|
|
21
|
+
style:
|
|
22
|
+
columns:
|
|
23
|
+
ticket_id:
|
|
24
|
+
label: Ticket
|
|
25
|
+
priority:
|
|
26
|
+
label: Priority
|
|
27
|
+
status:
|
|
28
|
+
label: Status
|
|
29
|
+
assignee:
|
|
30
|
+
label: Owner
|
|
31
|
+
revenue_impact:
|
|
32
|
+
label: Revenue Impact
|
|
33
|
+
format: currency_whole
|
|
34
|
+
conditional_formatting:
|
|
35
|
+
priority:
|
|
36
|
+
when:
|
|
37
|
+
- eq: P1
|
|
38
|
+
background: "#fee2e2"
|
|
39
|
+
font:
|
|
40
|
+
color: "#991b1b"
|
|
41
|
+
weight: "600"
|
|
42
|
+
- eq: P2
|
|
43
|
+
background: "#fef3c7"
|
|
44
|
+
font:
|
|
45
|
+
color: "#92400e"
|
|
46
|
+
|
|
47
|
+
rows:
|
|
48
|
+
- incidents_table
|