@malloy-publisher/server 0.3.0 → 0.3.1

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.
Files changed (24) hide show
  1. package/dist/app/assets/{EnvironmentPage-D6kQraU3.js → EnvironmentPage-CMNz23OH.js} +1 -1
  2. package/dist/app/assets/{HomePage-BZbuE5jv.js → HomePage-CIFBQm1O.js} +1 -1
  3. package/dist/app/assets/{LightMode-BxZdPcNr.js → LightMode-230hA2MG.js} +1 -1
  4. package/dist/app/assets/{MainPage-DrczCw4J.js → MainPage-DBgaP8G6.js} +2 -2
  5. package/dist/app/assets/{MaterializationsPage-BFLHLEuk.js → MaterializationsPage-B5tdbpRJ.js} +1 -1
  6. package/dist/app/assets/ModelPage-A6Kd1_wx.js +2 -0
  7. package/dist/app/assets/{PackagePage-DHsVf_mP.js → PackagePage-JUM3EcgJ.js} +1 -1
  8. package/dist/app/assets/RenderedResult-mDE-4u8S.es-s0zwv__L.js +116 -0
  9. package/dist/app/assets/{RouteError-CHq8ubhy.js → RouteError-BJAZkbpg.js} +1 -1
  10. package/dist/app/assets/{ThemeEditorPage-B2y8Y64Y.js → ThemeEditorPage-a0QNervK.js} +1 -1
  11. package/dist/app/assets/index-B5_U5YBb.js +1 -0
  12. package/dist/app/assets/index-BR3mOYNn.js +1322 -0
  13. package/dist/app/assets/{index-By-g8wiC.js → index-CNMFq7Ua.js} +1 -1
  14. package/dist/app/assets/index-CRAwrhYM.js +2 -0
  15. package/dist/app/assets/index-DplzDOL2.js +453 -0
  16. package/dist/app/assets/index-JaIfCAcq.js +443 -0
  17. package/dist/app/assets/index.es-CB4dOn75.js +106 -0
  18. package/dist/app/index.html +1 -1
  19. package/dist/server.mjs +52 -47
  20. package/package.json +1 -1
  21. package/dist/app/assets/ModelPage-CFnfQ6BL.js +0 -1
  22. package/dist/app/assets/index-BVv6KQ93.js +0 -557
  23. package/dist/app/assets/index-Bqrhk3ff.js +0 -2
  24. package/dist/app/assets/index-CawCwLK3.js +0 -1774
package/dist/server.mjs CHANGED
@@ -320380,14 +320380,18 @@ Scanned at a glance is a dashboard; read top to bottom is a notebook.
320380
320380
  2. **PICK THE VIEWS TO SHOW.** A dashboard is \`## artifact { tiles=[…] }\` naming existing views, so
320381
320381
  this is the design step: which views, how wide each sits, what each is called. There is one form,
320382
320382
  so there is no form to choose.
320383
- 3. **DECLARE THE GIVENS** the dashboard will filter by, in the model (usually \`givens.malloy\`), with
320384
- their control tags: see "Filter controls" below for the syntax and what each tag renders as. Skip
320385
- if they already exist, since a given is a model concern and dashboards share them.
320383
+ 3. **DECLARE THE GIVENS** the dashboard will filter by, in the dashboard file itself, with their
320384
+ control tags: see "Filter controls" below for the syntax and what each tag renders as. That is
320385
+ the convention because the dashboard builder edits the dashboard file and nothing else, so a
320386
+ filter it can add, change or remove is a declaration in that file. Bind them on the tiles (step
320387
+ 4). Reuse the package's \`givens.malloy\` only for a control several surfaces genuinely share, and
320388
+ then import it whole, knowing the builder can bind those givens but not edit them.
320386
320389
  4. **COMPOSE THE FILE** for \`dashboards/\`, following the template below, but do not save it yet.
320387
- Import the package's givens file **whole**: \`import '../givens.malloy'\`, not a named list.
320388
- Only the givens the tiles reference become controls, so a whole-file import brings nothing
320389
- extra, and a named list is one more thing to forget; forgetting one costs you a missing control
320390
- rather than an error. Sources are the other way round: name the few you need. Then import every
320390
+ Name the sources you need: \`import { order_items, products } from '../storefront.malloy'\`.
320391
+ Each tile binds its controls with a refinement, \`view: t is v + { where: category ~ $CATEGORY }\`,
320392
+ one clause per given it answers to; a \`filter<...>\` binds with \`~\`, a plain \`date\` or \`number\`
320393
+ given is a value and binds with \`>=\`, \`<=\` or \`=\`. Only the givens some tile references become
320394
+ controls, so a declaration nothing binds shows nothing. Then import every
320391
320395
  source or query any referenced given names in a \`suggest\`. Both are per-file, and getting the
320392
320396
  suggest wrong does not error: the control still looks like a picker but has no options, and says
320393
320397
  so underneath, "Could not load the options for this control". The package warnings name it too. **A \`suggest\` naming a \`query=\` needs that
@@ -320422,33 +320426,31 @@ out by Publisher into the grid \`# dashboard { columns=N }\` names.
320422
320426
  \`\`\`malloy
320423
320427
  ##! experimental.givens
320424
320428
  ## artifact { title="Storefront overview" tiles=["overview -> kpis", "overview -> revenue_trend", "overview -> revenue_by_state"] } dashboard { columns=12 }
320425
- import { scoped_sales } from './_shared.malloy'
320426
- import { products } from '../storefront.malloy'
320427
- import '../givens.malloy'
320429
+ import { order_items, products } from '../storefront.malloy'
320430
+
320431
+ // The controls, declared here: the tags are each one's control contract.
320432
+ # label="Category" control=select suggest { source=products dimension=category }
320433
+ given: CATEGORY :: filter<string> is f''
320434
+ # label="Ordered since"
320435
+ given: SINCE :: date is @2023-01-01
320428
320436
 
320429
320437
  // Layout goes on the VIEW, and a thin re-declaration is the place to put it: the
320430
- // modelled view keeps its chart tag, and this decides how wide it sits here.
320431
- source: overview is scoped_sales extend {
320438
+ // modelled view keeps its chart tag, this decides how wide it sits here, and the
320439
+ // \`+ { where: ... }\` says which controls the tile answers to.
320440
+ source: overview is order_items extend {
320432
320441
  # colspan=12
320433
320442
  # label="Key figures"
320434
320443
  # big_value
320435
- view: kpis is {
320436
- aggregate:
320437
- # label="Revenue"
320438
- # currency
320439
- total_sales
320440
- # label="Orders"
320441
- order_count
320442
- }
320444
+ view: kpis is key_figures + { where: category ~ $CATEGORY, where: created_at >= $SINCE }
320443
320445
 
320444
320446
  # colspan=8
320445
320447
  # break
320446
320448
  # label="Revenue by month"
320447
- view: revenue_trend is sales_by_month
320449
+ view: revenue_trend is sales_by_month + { where: category ~ $CATEGORY, where: created_at >= $SINCE }
320448
320450
 
320449
320451
  # colspan=4
320450
320452
  # label="Revenue by state"
320451
- view: revenue_by_state is sales_by_state
320453
+ view: revenue_by_state is sales_by_state + { where: category ~ $CATEGORY, where: created_at >= $SINCE }
320452
320454
  }
320453
320455
  \`\`\`
320454
320456
 
@@ -320461,8 +320463,8 @@ Three things the form costs, so you are not surprised by them:
320461
320463
  - **A tile expression is a string in an annotation, so the compiler never checks it.** Rename a view
320462
320464
  and the file still compiles; the tile fails at package load. Read the lint (step 6).
320463
320465
  - **No per-parent-row grouping.** There is no parent query to repeat a grid over.
320464
- - **Filtering lives in what the tiles name**, not on the page. That is the shared include's job,
320465
- below.
320466
+ - **Filtering lives on the tiles**, not on the page: each view's \`+ { where: ... }\` names the
320467
+ controls it answers to. Below is why, and the one thing that does not work.
320466
320468
 
320467
320469
  ### Also served: \`# artifact\` on a \`query:\`
320468
320470
 
@@ -320522,23 +320524,24 @@ object", so a dashboard has no description as a result.
320522
320524
 
320523
320525
  ### Where the filtering goes
320524
320526
 
320525
- A dashboard has no query, so the filtering it applies must live in what it composes: a source that
320526
- already has the givens applied. Put it in an untagged \`dashboards/_shared.malloy\`, which discovery
320527
- treats as a shared include rather than a dashboard. **It has to apply every given the dashboard
320528
- imports**: a given the dashboard imports but nothing references gets no control, silently, at reload
320529
- 200 with no warning. Note \`SINCE\` is a \`date\` rather than a \`filter<>\`, so it compares with \`>=\`
320530
- rather than \`~\`. Save the include before you compile the dashboard that imports it, since an importer
320531
- compiled against a sibling that is not on disk fails with an \`import-error\`.
320532
-
320533
- \`\`\`malloy
320534
- ##! experimental.givens
320535
- import { order_items } from '../storefront.malloy'
320536
- import '../givens.malloy'
320537
-
320538
- source: scoped_sales is order_items extend {
320539
- where: products.category ~ $CATEGORY and created_at >= $SINCE
320540
- }
320541
- \`\`\`
320527
+ A dashboard has no query, so its filtering lives on the views it names: a \`+ { where: field ~ $GIVEN }\`
320528
+ refinement on each tile, one clause per control the tile answers to. A tile without the clause does
320529
+ not move when the control does, which is how a page keeps one tile fixed while the rest filter. The
320530
+ givens those clauses read are declared in the same file (step 3).
320531
+
320532
+ **Binding is per declaration, not per name.** Measured: a dashboard declaring its own \`CATEGORY\`
320533
+ over a source whose model-level \`where:\` reads the model's \`CATEGORY\` compiles, shows the control,
320534
+ and filters nothing when it moves, because the two declarations only share a name. So do not mix
320535
+ the two designs on one given. The other design still works on its own: a source with the givens
320536
+ already applied in an untagged \`dashboards/_shared.malloy\`, reading \`import '../givens.malloy'\`,
320537
+ which discovery treats as a shared include rather than a dashboard. Then the dashboard imports both
320538
+ and the controls render for the givens its tiles reach. A given the dashboard imports but nothing
320539
+ references gets no control, silently, at reload 200 with no warning. Save the include before you
320540
+ compile the dashboard that imports it, since an importer compiled against a sibling that is not on
320541
+ disk fails with an \`import-error\`. The builder can bind such a control but not add, change or
320542
+ remove it, since it never edits imports or model files.
320543
+
320544
+ Note \`SINCE\` is a \`date\` rather than a \`filter<>\`, so it compares with \`>=\` rather than \`~\`.
320542
320545
 
320543
320546
  **\`# dashboard { columns=N }\` is the one spelling of the grid width**, on both forms, beside the
320544
320547
  artifact tag. Anything else inside the artifact tag is a package warning naming it, which is what you
@@ -320620,9 +320623,10 @@ rows.
320620
320623
  - **The filename is the dashboard's name:** its URL slug, its listing name, and its \`# drill\`
320621
320624
  target. The query inside can be called anything, and sometimes must be (a query named \`regions\`
320622
320625
  collides with an imported \`regions\` source).
320623
- - **Importing a given is what makes it bindable.** Malloy's given namespace is per-file. A given the
320624
- dashboard file does not import gets no control and cannot be sent to it, even when the \`where:\`
320625
- that references it lives up an import chain. A dashboard must import the givens its tiles use.
320626
+ - **A given has to be in the dashboard file's scope to be bindable**: declared there (the
320627
+ convention) or imported. Malloy's given namespace is per-file. A given the file cannot see gets
320628
+ no control and cannot be sent to it, even when a \`where:\` that references it lives up an import
320629
+ chain. And a given declared here does not drive a \`where:\` in the model: bind on the tiles.
320626
320630
  - **A suggest's source or query has to resolve in the dashboard file too.** \`suggest { source=products … }\`
320627
320631
  means the dashboard imports \`products\`.
320628
320632
  - **A model-level \`##\` tag must be on one line.** Wrapping one always breaks it, but how you find
@@ -320641,9 +320645,10 @@ choosing them.
320641
320645
 
320642
320646
  ## Filter controls
320643
320647
 
320644
- Controls come from the \`given:\` declarations the query references, and the tags on the declaration
320645
- are the control contract, declared once and identical on every dashboard and in every notebook that
320646
- uses them:
320648
+ Controls come from the \`given:\` declarations the tiles reference. Declare them in the dashboard
320649
+ file, which is what the builder edits; a package \`givens.malloy\` is for controls the data app and
320650
+ notebooks share, and a dashboard importing it whole gets the same controls but cannot edit them.
320651
+ The tags on the declaration are the control contract:
320647
320652
 
320648
320653
  \`\`\`malloy
320649
320654
  ##! experimental.givens
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@malloy-publisher/server",
3
3
  "description": "Malloy Publisher Server",
4
- "version": "0.3.0",
4
+ "version": "0.3.1",
5
5
  "main": "dist/server.mjs",
6
6
  "bin": {
7
7
  "malloy-publisher": "dist/server.mjs"
@@ -1 +0,0 @@
1
- import{D as g,r as j,a0 as u,j as a,J as s,a1 as N,a2 as d,a3 as y,H as f,Q as k,a4 as b,a5 as F,a6 as U,T as l,a7 as c,a8 as x}from"./index-BVv6KQ93.js";function v(e,n){const t=g();return j.useCallback((o,i)=>{const r=new URLSearchParams(o.givens).toString(),m=encodeURIComponent(e),p=encodeURIComponent(n),h=encodeURIComponent(o.dashboard);t(`/${m}/${p}/dashboards/${h}`+(r?`?${r}`:""),i)},[t,e,n])}function W({environmentName:e,packageName:n,dashboardName:t}){const{params:o,onGivensChange:i}=u(),r=v(e,n);return a.jsx(s,{sx:{p:3,maxWidth:1600,mx:"auto"},children:a.jsx(N,{resourceUri:d({environmentName:e,packageName:n}),dashboard:t,givens:o,onGivensChange:i,onNavigate:r,maxResultSize:1024*1024})})}function P({environmentName:e,packageName:n,notebookPath:t}){const{params:o,onGivensChange:i}=u(),r=v(e,n),m=g();return a.jsx(s,{sx:{p:3,maxWidth:1200,mx:"auto"},children:a.jsx(y,{resourceUri:d({environmentName:e,packageName:n,modelPath:t}),maxResultSize:1024*1024,givens:o,onGivensChange:i,onNavigate:m,onDrillNavigate:r})})}function C(){const e=f(),n=e["*"],{server:t}=k();if(!e.environmentName)return a.jsx("div",{children:a.jsx("h2",{children:"Missing environment name"})});if(!e.packageName)return a.jsx("div",{children:a.jsx("h2",{children:"Missing package name"})});const o={p:3,maxWidth:1200,mx:"auto"};if(n?.startsWith("dashboards/")&&!n.endsWith(".malloy")&&!n.endsWith(".malloynb"))return a.jsx(W,{environmentName:e.environmentName,packageName:e.packageName,dashboardName:n.slice(11)});if(n?.startsWith("data-apps/")&&!n.endsWith(".malloy")&&!n.endsWith(".malloynb")){const p=n.slice(10),h=d({environmentName:e.environmentName,packageName:e.packageName,modelPath:p});return a.jsx(b,{resourceUri:h})}const i=d({environmentName:e.environmentName,packageName:e.packageName,modelPath:n});if(n?.endsWith(".malloy"))return a.jsx(s,{sx:o,children:a.jsx(F,{resourceUri:i,runOnDemand:!0,maxResultSize:512*1024})});if(n?.endsWith(".malloynb"))return a.jsx(P,{environmentName:e.environmentName,packageName:e.packageName,notebookPath:n});const r=/\.[^./]+$/.test(n??""),m=U({server:t,environmentName:e.environmentName,packageName:e.packageName,path:n??""});return a.jsxs(s,{sx:o,children:[a.jsx(l,{variant:"h6",sx:{fontWeight:600},children:"Nothing to open at this path"}),a.jsxs(l,{variant:"body2",color:"text.secondary",sx:{mt:1},children:[a.jsx(s,{component:"span",sx:{fontFamily:c},children:n})," ","does not name a"," ",a.jsx(s,{component:"span",sx:{fontFamily:c},children:".malloy"})," ","or"," ",a.jsx(s,{component:"span",sx:{fontFamily:c},children:".malloynb"})," ","file in package"," ",a.jsx(s,{component:"span",sx:{fontFamily:c},children:e.packageName}),". This address opens"," ",a.jsx(s,{component:"span",sx:{fontFamily:c},children:".malloy"})," ","and"," ",a.jsx(s,{component:"span",sx:{fontFamily:c},children:".malloynb"})," ","files."]}),r&&a.jsxs(l,{variant:"body2",color:"text.secondary",sx:{mt:1},children:["A file from the package's"," ",a.jsx(s,{component:"span",sx:{fontFamily:c},children:"public/"})," ","directory is served at ",a.jsx(x,{href:m,children:m}),"."]}),a.jsxs(l,{variant:"body2",color:"text.secondary",sx:{mt:1},children:[a.jsxs(x,{href:`/${encodeURIComponent(e.environmentName)}/${encodeURIComponent(e.packageName)}`,children:["Back to ",e.packageName]})," ","lists this package's models, notebooks, and data apps."]})]})}export{C as default};