@gooddata/sdk-model 11.54.0-alpha.6 → 11.54.0
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.
- package/esm/index.d.ts +8 -0
- package/esm/index.d.ts.map +1 -1
- package/esm/index.js +8 -0
- package/esm/objRef/index.d.ts +1 -1
- package/esm/objRef/index.d.ts.map +1 -1
- package/esm/reports/builtinPageLayouts.d.ts +27 -0
- package/esm/reports/builtinPageLayouts.d.ts.map +1 -0
- package/esm/reports/builtinPageLayouts.js +196 -0
- package/esm/reports/content.d.ts +54 -0
- package/esm/reports/content.d.ts.map +1 -0
- package/esm/reports/content.js +12 -0
- package/esm/reports/factory.d.ts +65 -0
- package/esm/reports/factory.d.ts.map +1 -0
- package/esm/reports/factory.js +126 -0
- package/esm/reports/layout.d.ts +59 -0
- package/esm/reports/layout.d.ts.map +1 -0
- package/esm/reports/layout.js +18 -0
- package/esm/reports/pageLayout.d.ts +120 -0
- package/esm/reports/pageLayout.d.ts.map +1 -0
- package/esm/reports/pageLayout.js +83 -0
- package/esm/reports/report.d.ts +116 -0
- package/esm/reports/report.d.ts.map +1 -0
- package/esm/reports/report.js +35 -0
- package/esm/reports/slot.d.ts +219 -0
- package/esm/reports/slot.d.ts.map +1 -0
- package/esm/reports/slot.js +54 -0
- package/esm/reports/variables.d.ts +62 -0
- package/esm/reports/variables.d.ts.map +1 -0
- package/esm/reports/variables.js +41 -0
- package/esm/sdk-model.d.ts +756 -1
- package/package.json +6 -6
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
// (C) 2026 GoodData Corporation
|
|
2
|
+
import { isReportLayoutSection } from "./layout.js";
|
|
3
|
+
function generateReportLocalId(prefix) {
|
|
4
|
+
const unique = typeof crypto !== "undefined" && typeof crypto.randomUUID === "function"
|
|
5
|
+
? crypto.randomUUID().replace(/-/g, "").slice(0, 12)
|
|
6
|
+
: Math.random().toString(36).slice(2, 14);
|
|
7
|
+
return `${prefix}_${unique}`;
|
|
8
|
+
}
|
|
9
|
+
function deepClone(value) {
|
|
10
|
+
return JSON.parse(JSON.stringify(value));
|
|
11
|
+
}
|
|
12
|
+
function prefixLayoutSlotIds(node, prefix) {
|
|
13
|
+
if (isReportLayoutSection(node)) {
|
|
14
|
+
return {
|
|
15
|
+
...node,
|
|
16
|
+
children: node.children.map((child) => prefixLayoutSlotIds(child, prefix)),
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
return {
|
|
20
|
+
...node,
|
|
21
|
+
slotId: `${prefix}_${node.slotId}`,
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Creates a new report page definition.
|
|
26
|
+
*
|
|
27
|
+
* @alpha
|
|
28
|
+
*/
|
|
29
|
+
export function newReportPageLayoutDefinition(title, body, modifications) {
|
|
30
|
+
const content = { version: "1", ...body };
|
|
31
|
+
return {
|
|
32
|
+
type: "reportPageLayout",
|
|
33
|
+
title,
|
|
34
|
+
content,
|
|
35
|
+
...modifications,
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Clones a report page into a page instance embeddable in template/report content.
|
|
40
|
+
*
|
|
41
|
+
* @remarks
|
|
42
|
+
* The body is deep-copied and detached from the source page — no reference is kept.
|
|
43
|
+
* Slot localIdentifiers (and the layout slotIds pointing at them) are prefixed with the
|
|
44
|
+
* page-instance localIdentifier, so one page used repeatedly in the same content stays unique.
|
|
45
|
+
*
|
|
46
|
+
* @alpha
|
|
47
|
+
*/
|
|
48
|
+
export function newReportContentPageFromLayout(page, localIdentifier = generateReportLocalId("page")) {
|
|
49
|
+
const { version: _version, ...body } = deepClone(page.content);
|
|
50
|
+
return {
|
|
51
|
+
...body,
|
|
52
|
+
localIdentifier,
|
|
53
|
+
layout: prefixLayoutSlotIds(body.layout, localIdentifier),
|
|
54
|
+
slots: body.slots.map((slot) => ({
|
|
55
|
+
...slot,
|
|
56
|
+
localIdentifier: `${localIdentifier}_${slot.localIdentifier}`,
|
|
57
|
+
})),
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Creates report content from page instances.
|
|
62
|
+
*
|
|
63
|
+
* @alpha
|
|
64
|
+
*/
|
|
65
|
+
export function newReportContent(pages, modifications) {
|
|
66
|
+
return {
|
|
67
|
+
version: "1",
|
|
68
|
+
pages,
|
|
69
|
+
...modifications,
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Creates a new report template definition.
|
|
74
|
+
*
|
|
75
|
+
* @alpha
|
|
76
|
+
*/
|
|
77
|
+
export function newReportTemplateDefinition(title, content, modifications) {
|
|
78
|
+
return {
|
|
79
|
+
type: "reportTemplate",
|
|
80
|
+
title,
|
|
81
|
+
content,
|
|
82
|
+
...modifications,
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* Creates a report definition from a template.
|
|
87
|
+
*
|
|
88
|
+
* @remarks
|
|
89
|
+
* The template content is deep-copied; no reference to the template is kept, so the
|
|
90
|
+
* report stays frozen while the template evolves.
|
|
91
|
+
*
|
|
92
|
+
* @alpha
|
|
93
|
+
*/
|
|
94
|
+
export function newReportDefinitionFromTemplate(template, options, modifications) {
|
|
95
|
+
return {
|
|
96
|
+
type: "report",
|
|
97
|
+
title: options.title,
|
|
98
|
+
periodStart: options.periodStart,
|
|
99
|
+
periodEnd: options.periodEnd,
|
|
100
|
+
content: deepClone(template.content),
|
|
101
|
+
...modifications,
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Creates an ad-hoc report definition not based on any template.
|
|
106
|
+
*
|
|
107
|
+
* @alpha
|
|
108
|
+
*/
|
|
109
|
+
export function newAdHocReportDefinition(options, modifications) {
|
|
110
|
+
return {
|
|
111
|
+
type: "report",
|
|
112
|
+
title: options.title,
|
|
113
|
+
periodStart: options.periodStart,
|
|
114
|
+
periodEnd: options.periodEnd,
|
|
115
|
+
content: newReportContent(options.pages ?? []),
|
|
116
|
+
...modifications,
|
|
117
|
+
};
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* Convenience accessor for a report or template page by its localIdentifier.
|
|
121
|
+
*
|
|
122
|
+
* @alpha
|
|
123
|
+
*/
|
|
124
|
+
export function reportContentPage(reportOrTemplate, pageLocalIdentifier) {
|
|
125
|
+
return reportOrTemplate.content.pages.find((page) => page.localIdentifier === pageLocalIdentifier);
|
|
126
|
+
}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Node of a report page layout: a recursive row/column split tree (flexbox semantics)
|
|
3
|
+
* over a fixed page. Leaves assign their area to slots; the tree carries only geometry,
|
|
4
|
+
* slot content lives in {@link IReportPageBody.slots}.
|
|
5
|
+
*
|
|
6
|
+
* @alpha
|
|
7
|
+
*/
|
|
8
|
+
export type ReportPageLayoutNode = IReportLayoutSection | IReportLayoutSlotRef;
|
|
9
|
+
/**
|
|
10
|
+
* Fields common to all report layout nodes.
|
|
11
|
+
*
|
|
12
|
+
* @alpha
|
|
13
|
+
*/
|
|
14
|
+
export interface IReportLayoutNodeBase {
|
|
15
|
+
/**
|
|
16
|
+
* Fractional weight of this node inside its parent (flex-grow semantics).
|
|
17
|
+
* Defaults to 1. Example: sibling weights [2, 1] render a 2/3 + 1/3 split.
|
|
18
|
+
*/
|
|
19
|
+
weight?: number;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* A container splitting its area into children laid out along a direction.
|
|
23
|
+
*
|
|
24
|
+
* @alpha
|
|
25
|
+
*/
|
|
26
|
+
export interface IReportLayoutSection extends IReportLayoutNodeBase {
|
|
27
|
+
type: "section";
|
|
28
|
+
/**
|
|
29
|
+
* "row" lays children out horizontally, "column" vertically.
|
|
30
|
+
*/
|
|
31
|
+
direction: "row" | "column";
|
|
32
|
+
children: ReportPageLayoutNode[];
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* A leaf assigning its area to a slot. The slot fills the area completely.
|
|
36
|
+
*
|
|
37
|
+
* @alpha
|
|
38
|
+
*/
|
|
39
|
+
export interface IReportLayoutSlotRef extends IReportLayoutNodeBase {
|
|
40
|
+
type: "slotRef";
|
|
41
|
+
/**
|
|
42
|
+
* Local identifier of a slot in {@link IReportPageBody.slots}.
|
|
43
|
+
* A slotId with no matching slot renders as an empty area.
|
|
44
|
+
*/
|
|
45
|
+
slotId: string;
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Type-guard testing whether the provided object is an instance of {@link IReportLayoutSection}.
|
|
49
|
+
*
|
|
50
|
+
* @alpha
|
|
51
|
+
*/
|
|
52
|
+
export declare function isReportLayoutSection(obj: unknown): obj is IReportLayoutSection;
|
|
53
|
+
/**
|
|
54
|
+
* Type-guard testing whether the provided object is an instance of {@link IReportLayoutSlotRef}.
|
|
55
|
+
*
|
|
56
|
+
* @alpha
|
|
57
|
+
*/
|
|
58
|
+
export declare function isReportLayoutSlotRef(obj: unknown): obj is IReportLayoutSlotRef;
|
|
59
|
+
//# sourceMappingURL=layout.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"layout.d.ts","sourceRoot":"","sources":["../../src/reports/layout.ts"],"names":[],"mappings":"AAIA;;;;;;GAMG;AACH,MAAM,MAAM,oBAAoB,GAAG,oBAAoB,GAAG,oBAAoB,CAAC;AAE/E;;;;GAIG;AACH,MAAM,WAAW,qBAAqB;IAClC;;;OAGG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;CACnB;AAED;;;;GAIG;AACH,MAAM,WAAW,oBAAqB,SAAQ,qBAAqB;IAC/D,IAAI,EAAE,SAAS,CAAC;IAEhB;;OAEG;IACH,SAAS,EAAE,KAAK,GAAG,QAAQ,CAAC;IAE5B,QAAQ,EAAE,oBAAoB,EAAE,CAAC;CACpC;AAED;;;;GAIG;AACH,MAAM,WAAW,oBAAqB,SAAQ,qBAAqB;IAC/D,IAAI,EAAE,SAAS,CAAC;IAEhB;;;OAGG;IACH,MAAM,EAAE,MAAM,CAAC;CAClB;AAED;;;;GAIG;AACH,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,OAAO,GAAG,GAAG,IAAI,oBAAoB,CAE/E;AAED;;;;GAIG;AACH,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,OAAO,GAAG,GAAG,IAAI,oBAAoB,CAE/E"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
// (C) 2026 GoodData Corporation
|
|
2
|
+
import { isEmpty } from "lodash-es";
|
|
3
|
+
/**
|
|
4
|
+
* Type-guard testing whether the provided object is an instance of {@link IReportLayoutSection}.
|
|
5
|
+
*
|
|
6
|
+
* @alpha
|
|
7
|
+
*/
|
|
8
|
+
export function isReportLayoutSection(obj) {
|
|
9
|
+
return !isEmpty(obj) && obj.type === "section";
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Type-guard testing whether the provided object is an instance of {@link IReportLayoutSlotRef}.
|
|
13
|
+
*
|
|
14
|
+
* @alpha
|
|
15
|
+
*/
|
|
16
|
+
export function isReportLayoutSlotRef(obj) {
|
|
17
|
+
return !isEmpty(obj) && obj.type === "slotRef";
|
|
18
|
+
}
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
import { type IAuditableDates, type IAuditableUsers } from "../base/metadata.js";
|
|
2
|
+
import { type FilterContextItem } from "../dashboard/filterContext.js";
|
|
3
|
+
import { type ObjRef } from "../objRef/index.js";
|
|
4
|
+
import { type ReportPageLayoutNode } from "./layout.js";
|
|
5
|
+
import { type ReportSlot } from "./slot.js";
|
|
6
|
+
/**
|
|
7
|
+
* Body of a report page: geometry (flex split tree) plus the slots it places.
|
|
8
|
+
*
|
|
9
|
+
* @remarks
|
|
10
|
+
* This is both the content of the standalone {@link IReportPageLayout} object and the shape
|
|
11
|
+
* embedded in template/report content ({@link IReportContentPage}).
|
|
12
|
+
*
|
|
13
|
+
* There is no header/footer chrome: page title, description, footer, page numbers and
|
|
14
|
+
* logos are ordinary slots in the layout tree (text slots with `{{pageNumber}}`/`{{totalPages}}`,
|
|
15
|
+
* an image slot with `{{logo}}`). Every slot fills its layout area completely.
|
|
16
|
+
*
|
|
17
|
+
* @alpha
|
|
18
|
+
*/
|
|
19
|
+
export interface IReportPageBody {
|
|
20
|
+
/**
|
|
21
|
+
* Editor hint only (template galleries, default styling, AI context).
|
|
22
|
+
* Renderers must not branch layout logic on it — geometry always comes from `layout`.
|
|
23
|
+
*/
|
|
24
|
+
kind?: "cover" | "section" | "content";
|
|
25
|
+
/**
|
|
26
|
+
* Root of the page layout tree.
|
|
27
|
+
*/
|
|
28
|
+
layout: ReportPageLayoutNode;
|
|
29
|
+
/**
|
|
30
|
+
* All slots referenced by the layout, flat, keyed by localIdentifier.
|
|
31
|
+
*/
|
|
32
|
+
slots: ReportSlot[];
|
|
33
|
+
/**
|
|
34
|
+
* Page-level filters: merged over content-level filters (a filter targeting the
|
|
35
|
+
* same object replaces the inherited one); slot filters apply on top.
|
|
36
|
+
*/
|
|
37
|
+
filters?: FilterContextItem[];
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Stored content of the reportPage entity.
|
|
41
|
+
*
|
|
42
|
+
* @alpha
|
|
43
|
+
*/
|
|
44
|
+
export interface IReportPageLayoutContent extends IReportPageBody {
|
|
45
|
+
/**
|
|
46
|
+
* Content model version, for stored-content evolution.
|
|
47
|
+
*/
|
|
48
|
+
version: "1";
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Payload for creating or updating a report page.
|
|
52
|
+
*
|
|
53
|
+
* @alpha
|
|
54
|
+
*/
|
|
55
|
+
export interface IReportPageLayoutDefinition {
|
|
56
|
+
type: "reportPageLayout";
|
|
57
|
+
/**
|
|
58
|
+
* Present when updating an existing page.
|
|
59
|
+
*/
|
|
60
|
+
ref?: ObjRef;
|
|
61
|
+
title: string;
|
|
62
|
+
description?: string;
|
|
63
|
+
tags?: string[];
|
|
64
|
+
content: IReportPageLayoutContent;
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Reusable report page metadata object.
|
|
68
|
+
*
|
|
69
|
+
* @alpha
|
|
70
|
+
*/
|
|
71
|
+
export interface IReportPageLayout extends IReportPageLayoutDefinition, IAuditableDates, IAuditableUsers {
|
|
72
|
+
ref: ObjRef;
|
|
73
|
+
/**
|
|
74
|
+
* When true, the object comes from a parent workspace and is not editable
|
|
75
|
+
* in the current workspace.
|
|
76
|
+
*/
|
|
77
|
+
isLocked?: boolean;
|
|
78
|
+
/**
|
|
79
|
+
* Predefined page shipped with the product, populated by the SPI. Never sent to or
|
|
80
|
+
* stored on the backend; UI must disable deletion and editing of built-in pages.
|
|
81
|
+
*/
|
|
82
|
+
isBuiltIn?: boolean;
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Type-guard testing whether the provided object is an instance of {@link IReportPageLayoutDefinition}.
|
|
86
|
+
*
|
|
87
|
+
* @alpha
|
|
88
|
+
*/
|
|
89
|
+
export declare function isReportPageLayoutDefinition(obj: unknown): obj is IReportPageLayoutDefinition;
|
|
90
|
+
/**
|
|
91
|
+
* Type-guard testing whether the provided object is an instance of {@link IReportPageLayout}.
|
|
92
|
+
*
|
|
93
|
+
* @alpha
|
|
94
|
+
*/
|
|
95
|
+
export declare function isReportPageLayout(obj: unknown): obj is IReportPageLayout;
|
|
96
|
+
/**
|
|
97
|
+
* Type-guard testing whether the provided object is an instance of {@link IReportPageLayoutContent}.
|
|
98
|
+
*
|
|
99
|
+
* @alpha
|
|
100
|
+
*/
|
|
101
|
+
export declare function isReportPageLayoutContentV1(obj: unknown): obj is IReportPageLayoutContent;
|
|
102
|
+
/**
|
|
103
|
+
* Validation issue found in a report page body.
|
|
104
|
+
*
|
|
105
|
+
* @alpha
|
|
106
|
+
*/
|
|
107
|
+
export interface IReportPageBodyValidationIssue {
|
|
108
|
+
severity: "error" | "warning";
|
|
109
|
+
message: string;
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* Validates the structural invariants of a page body the type system cannot express:
|
|
113
|
+
* slot localIdentifiers are unique, layout weights are positive, every slot is placed
|
|
114
|
+
* by the layout, and every layout slotId resolves (unresolved ones are warnings —
|
|
115
|
+
* they render as empty areas).
|
|
116
|
+
*
|
|
117
|
+
* @alpha
|
|
118
|
+
*/
|
|
119
|
+
export declare function validateReportPageBody(body: IReportPageBody): IReportPageBodyValidationIssue[];
|
|
120
|
+
//# sourceMappingURL=pageLayout.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pageLayout.d.ts","sourceRoot":"","sources":["../../src/reports/pageLayout.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,KAAK,eAAe,EAAE,KAAK,eAAe,EAAE,MAAM,qBAAqB,CAAC;AACjF,OAAO,EAAE,KAAK,iBAAiB,EAAE,MAAM,+BAA+B,CAAC;AACvE,OAAO,EAAE,KAAK,MAAM,EAAY,MAAM,oBAAoB,CAAC;AAE3D,OAAO,EAAE,KAAK,oBAAoB,EAAgD,MAAM,aAAa,CAAC;AACtG,OAAO,EAAE,KAAK,UAAU,EAAE,MAAM,WAAW,CAAC;AAE5C;;;;;;;;;;;;GAYG;AACH,MAAM,WAAW,eAAe;IAC5B;;;OAGG;IACH,IAAI,CAAC,EAAE,OAAO,GAAG,SAAS,GAAG,SAAS,CAAC;IAEvC;;OAEG;IACH,MAAM,EAAE,oBAAoB,CAAC;IAE7B;;OAEG;IACH,KAAK,EAAE,UAAU,EAAE,CAAC;IAEpB;;;OAGG;IACH,OAAO,CAAC,EAAE,iBAAiB,EAAE,CAAC;CACjC;AAED;;;;GAIG;AACH,MAAM,WAAW,wBAAyB,SAAQ,eAAe;IAC7D;;OAEG;IACH,OAAO,EAAE,GAAG,CAAC;CAChB;AAED;;;;GAIG;AACH,MAAM,WAAW,2BAA2B;IACxC,IAAI,EAAE,kBAAkB,CAAC;IAEzB;;OAEG;IACH,GAAG,CAAC,EAAE,MAAM,CAAC;IAEb,KAAK,EAAE,MAAM,CAAC;IAEd,WAAW,CAAC,EAAE,MAAM,CAAC;IAErB,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAEhB,OAAO,EAAE,wBAAwB,CAAC;CACrC;AAED;;;;GAIG;AACH,MAAM,WAAW,iBAAkB,SAAQ,2BAA2B,EAAE,eAAe,EAAE,eAAe;IACpG,GAAG,EAAE,MAAM,CAAC;IAEZ;;;OAGG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC;IAEnB;;;OAGG;IACH,SAAS,CAAC,EAAE,OAAO,CAAC;CACvB;AAED;;;;GAIG;AACH,wBAAgB,4BAA4B,CAAC,GAAG,EAAE,OAAO,GAAG,GAAG,IAAI,2BAA2B,CAE7F;AAED;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,OAAO,GAAG,GAAG,IAAI,iBAAiB,CAEzE;AAED;;;;GAIG;AACH,wBAAgB,2BAA2B,CAAC,GAAG,EAAE,OAAO,GAAG,GAAG,IAAI,wBAAwB,CAOzF;AAED;;;;GAIG;AACH,MAAM,WAAW,8BAA8B;IAC3C,QAAQ,EAAE,OAAO,GAAG,SAAS,CAAC;IAC9B,OAAO,EAAE,MAAM,CAAC;CACnB;AAED;;;;;;;GAOG;AACH,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,eAAe,GAAG,8BAA8B,EAAE,CA8C9F"}
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
// (C) 2026 GoodData Corporation
|
|
2
|
+
import { isEmpty } from "lodash-es";
|
|
3
|
+
import { isObjRef } from "../objRef/index.js";
|
|
4
|
+
import { isReportLayoutSection, isReportLayoutSlotRef } from "./layout.js";
|
|
5
|
+
/**
|
|
6
|
+
* Type-guard testing whether the provided object is an instance of {@link IReportPageLayoutDefinition}.
|
|
7
|
+
*
|
|
8
|
+
* @alpha
|
|
9
|
+
*/
|
|
10
|
+
export function isReportPageLayoutDefinition(obj) {
|
|
11
|
+
return !isEmpty(obj) && obj.type === "reportPageLayout";
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Type-guard testing whether the provided object is an instance of {@link IReportPageLayout}.
|
|
15
|
+
*
|
|
16
|
+
* @alpha
|
|
17
|
+
*/
|
|
18
|
+
export function isReportPageLayout(obj) {
|
|
19
|
+
return isReportPageLayoutDefinition(obj) && isObjRef(obj.ref);
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Type-guard testing whether the provided object is an instance of {@link IReportPageLayoutContent}.
|
|
23
|
+
*
|
|
24
|
+
* @alpha
|
|
25
|
+
*/
|
|
26
|
+
export function isReportPageLayoutContentV1(obj) {
|
|
27
|
+
return (!isEmpty(obj) &&
|
|
28
|
+
obj.version === "1" &&
|
|
29
|
+
!isEmpty(obj.layout) &&
|
|
30
|
+
Array.isArray(obj.slots));
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Validates the structural invariants of a page body the type system cannot express:
|
|
34
|
+
* slot localIdentifiers are unique, layout weights are positive, every slot is placed
|
|
35
|
+
* by the layout, and every layout slotId resolves (unresolved ones are warnings —
|
|
36
|
+
* they render as empty areas).
|
|
37
|
+
*
|
|
38
|
+
* @alpha
|
|
39
|
+
*/
|
|
40
|
+
export function validateReportPageBody(body) {
|
|
41
|
+
const issues = [];
|
|
42
|
+
const slotIds = new Set();
|
|
43
|
+
for (const slot of body.slots) {
|
|
44
|
+
if (slotIds.has(slot.localIdentifier)) {
|
|
45
|
+
issues.push({
|
|
46
|
+
severity: "error",
|
|
47
|
+
message: `Duplicate slot localIdentifier "${slot.localIdentifier}".`,
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
slotIds.add(slot.localIdentifier);
|
|
51
|
+
}
|
|
52
|
+
const referencedIds = new Set();
|
|
53
|
+
const visit = (node) => {
|
|
54
|
+
if (node.weight !== undefined && !(node.weight > 0)) {
|
|
55
|
+
issues.push({
|
|
56
|
+
severity: "error",
|
|
57
|
+
message: `Layout node weight must be positive, got ${node.weight}.`,
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
if (isReportLayoutSlotRef(node)) {
|
|
61
|
+
referencedIds.add(node.slotId);
|
|
62
|
+
if (!slotIds.has(node.slotId)) {
|
|
63
|
+
issues.push({
|
|
64
|
+
severity: "warning",
|
|
65
|
+
message: `Layout references slot "${node.slotId}" which has no definition; it renders empty.`,
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
else if (isReportLayoutSection(node)) {
|
|
70
|
+
node.children.forEach(visit);
|
|
71
|
+
}
|
|
72
|
+
};
|
|
73
|
+
visit(body.layout);
|
|
74
|
+
for (const slotId of slotIds) {
|
|
75
|
+
if (!referencedIds.has(slotId)) {
|
|
76
|
+
issues.push({
|
|
77
|
+
severity: "warning",
|
|
78
|
+
message: `Slot "${slotId}" is not placed by the layout and never renders.`,
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
return issues;
|
|
83
|
+
}
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
import { type IAuditableDates, type IAuditableUsers } from "../base/metadata.js";
|
|
2
|
+
import { type ObjRef } from "../objRef/index.js";
|
|
3
|
+
import { type IReportContent } from "./content.js";
|
|
4
|
+
import { type ReportDateString } from "./variables.js";
|
|
5
|
+
/**
|
|
6
|
+
* Payload for creating or updating a report template.
|
|
7
|
+
*
|
|
8
|
+
* @alpha
|
|
9
|
+
*/
|
|
10
|
+
export interface IReportTemplateDefinition {
|
|
11
|
+
type: "reportTemplate";
|
|
12
|
+
/**
|
|
13
|
+
* Present when updating an existing template.
|
|
14
|
+
*/
|
|
15
|
+
ref?: ObjRef;
|
|
16
|
+
title: string;
|
|
17
|
+
description?: string;
|
|
18
|
+
tags?: string[];
|
|
19
|
+
content: IReportContent;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Report template metadata object.
|
|
23
|
+
*
|
|
24
|
+
* @alpha
|
|
25
|
+
*/
|
|
26
|
+
export interface IReportTemplate extends IReportTemplateDefinition, IAuditableDates, IAuditableUsers {
|
|
27
|
+
ref: ObjRef;
|
|
28
|
+
/**
|
|
29
|
+
* When true, the object comes from a parent workspace and is not editable
|
|
30
|
+
* in the current workspace.
|
|
31
|
+
*/
|
|
32
|
+
isLocked?: boolean;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Fields shared by report definitions and persisted reports.
|
|
36
|
+
*
|
|
37
|
+
* @alpha
|
|
38
|
+
*/
|
|
39
|
+
export interface IReportBase {
|
|
40
|
+
title: string;
|
|
41
|
+
description?: string;
|
|
42
|
+
tags?: string[];
|
|
43
|
+
/**
|
|
44
|
+
* Reported period start, ISO 8601 date (YYYY-MM-DD), inclusive.
|
|
45
|
+
*
|
|
46
|
+
* @remarks
|
|
47
|
+
* At execution time the period materializes as an absolute date filter on each
|
|
48
|
+
* visualization slot's dateDataSet (lowest precedence, per-slot opt-out via
|
|
49
|
+
* ignoreReportPeriod). Also available as `{{periodStart}}` in text.
|
|
50
|
+
*/
|
|
51
|
+
periodStart: ReportDateString;
|
|
52
|
+
/**
|
|
53
|
+
* Reported period end, ISO 8601 date (YYYY-MM-DD), inclusive.
|
|
54
|
+
*/
|
|
55
|
+
periodEnd: ReportDateString;
|
|
56
|
+
/**
|
|
57
|
+
* Content of the report. When created from a template the content is deep-copied
|
|
58
|
+
* and NO reference to the template is kept — the report stays frozen while pages
|
|
59
|
+
* and templates evolve.
|
|
60
|
+
*/
|
|
61
|
+
content: IReportContent;
|
|
62
|
+
/**
|
|
63
|
+
* Values for variables declared in content.variables, keyed by variable name.
|
|
64
|
+
*/
|
|
65
|
+
variableValues?: Record<string, string>;
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Payload for creating or updating a report.
|
|
69
|
+
*
|
|
70
|
+
* @alpha
|
|
71
|
+
*/
|
|
72
|
+
export interface IReportDefinition extends IReportBase {
|
|
73
|
+
type: "report";
|
|
74
|
+
/**
|
|
75
|
+
* Present when updating an existing report.
|
|
76
|
+
*/
|
|
77
|
+
ref?: ObjRef;
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Report metadata object.
|
|
81
|
+
*
|
|
82
|
+
* @alpha
|
|
83
|
+
*/
|
|
84
|
+
export interface IReport extends IReportDefinition, IAuditableDates, IAuditableUsers {
|
|
85
|
+
ref: ObjRef;
|
|
86
|
+
/**
|
|
87
|
+
* When true, the object comes from a parent workspace and is not editable
|
|
88
|
+
* in the current workspace.
|
|
89
|
+
*/
|
|
90
|
+
isLocked?: boolean;
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Type-guard testing whether the provided object is an instance of {@link IReportTemplateDefinition}.
|
|
94
|
+
*
|
|
95
|
+
* @alpha
|
|
96
|
+
*/
|
|
97
|
+
export declare function isReportTemplateDefinition(obj: unknown): obj is IReportTemplateDefinition;
|
|
98
|
+
/**
|
|
99
|
+
* Type-guard testing whether the provided object is an instance of {@link IReportTemplate}.
|
|
100
|
+
*
|
|
101
|
+
* @alpha
|
|
102
|
+
*/
|
|
103
|
+
export declare function isReportTemplate(obj: unknown): obj is IReportTemplate;
|
|
104
|
+
/**
|
|
105
|
+
* Type-guard testing whether the provided object is an instance of {@link IReportDefinition}.
|
|
106
|
+
*
|
|
107
|
+
* @alpha
|
|
108
|
+
*/
|
|
109
|
+
export declare function isReportDefinition(obj: unknown): obj is IReportDefinition;
|
|
110
|
+
/**
|
|
111
|
+
* Type-guard testing whether the provided object is an instance of {@link IReport}.
|
|
112
|
+
*
|
|
113
|
+
* @alpha
|
|
114
|
+
*/
|
|
115
|
+
export declare function isReport(obj: unknown): obj is IReport;
|
|
116
|
+
//# sourceMappingURL=report.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"report.d.ts","sourceRoot":"","sources":["../../src/reports/report.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,KAAK,eAAe,EAAE,KAAK,eAAe,EAAE,MAAM,qBAAqB,CAAC;AACjF,OAAO,EAAE,KAAK,MAAM,EAAY,MAAM,oBAAoB,CAAC;AAE3D,OAAO,EAAE,KAAK,cAAc,EAAE,MAAM,cAAc,CAAC;AACnD,OAAO,EAAE,KAAK,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAEvD;;;;GAIG;AACH,MAAM,WAAW,yBAAyB;IACtC,IAAI,EAAE,gBAAgB,CAAC;IAEvB;;OAEG;IACH,GAAG,CAAC,EAAE,MAAM,CAAC;IAEb,KAAK,EAAE,MAAM,CAAC;IAEd,WAAW,CAAC,EAAE,MAAM,CAAC;IAErB,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAEhB,OAAO,EAAE,cAAc,CAAC;CAC3B;AAED;;;;GAIG;AACH,MAAM,WAAW,eAAgB,SAAQ,yBAAyB,EAAE,eAAe,EAAE,eAAe;IAChG,GAAG,EAAE,MAAM,CAAC;IAEZ;;;OAGG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC;CACtB;AAED;;;;GAIG;AACH,MAAM,WAAW,WAAW;IACxB,KAAK,EAAE,MAAM,CAAC;IAEd,WAAW,CAAC,EAAE,MAAM,CAAC;IAErB,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAEhB;;;;;;;OAOG;IACH,WAAW,EAAE,gBAAgB,CAAC;IAE9B;;OAEG;IACH,SAAS,EAAE,gBAAgB,CAAC;IAE5B;;;;OAIG;IACH,OAAO,EAAE,cAAc,CAAC;IAExB;;OAEG;IACH,cAAc,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAC3C;AAED;;;;GAIG;AACH,MAAM,WAAW,iBAAkB,SAAQ,WAAW;IAClD,IAAI,EAAE,QAAQ,CAAC;IAEf;;OAEG;IACH,GAAG,CAAC,EAAE,MAAM,CAAC;CAChB;AAED;;;;GAIG;AACH,MAAM,WAAW,OAAQ,SAAQ,iBAAiB,EAAE,eAAe,EAAE,eAAe;IAChF,GAAG,EAAE,MAAM,CAAC;IAEZ;;;OAGG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC;CACtB;AAED;;;;GAIG;AACH,wBAAgB,0BAA0B,CAAC,GAAG,EAAE,OAAO,GAAG,GAAG,IAAI,yBAAyB,CAEzF;AAED;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,OAAO,GAAG,GAAG,IAAI,eAAe,CAErE;AAED;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,OAAO,GAAG,GAAG,IAAI,iBAAiB,CAEzE;AAED;;;;GAIG;AACH,wBAAgB,QAAQ,CAAC,GAAG,EAAE,OAAO,GAAG,GAAG,IAAI,OAAO,CAErD"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
// (C) 2026 GoodData Corporation
|
|
2
|
+
import { isEmpty } from "lodash-es";
|
|
3
|
+
import { isObjRef } from "../objRef/index.js";
|
|
4
|
+
/**
|
|
5
|
+
* Type-guard testing whether the provided object is an instance of {@link IReportTemplateDefinition}.
|
|
6
|
+
*
|
|
7
|
+
* @alpha
|
|
8
|
+
*/
|
|
9
|
+
export function isReportTemplateDefinition(obj) {
|
|
10
|
+
return !isEmpty(obj) && obj.type === "reportTemplate";
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Type-guard testing whether the provided object is an instance of {@link IReportTemplate}.
|
|
14
|
+
*
|
|
15
|
+
* @alpha
|
|
16
|
+
*/
|
|
17
|
+
export function isReportTemplate(obj) {
|
|
18
|
+
return isReportTemplateDefinition(obj) && isObjRef(obj.ref);
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Type-guard testing whether the provided object is an instance of {@link IReportDefinition}.
|
|
22
|
+
*
|
|
23
|
+
* @alpha
|
|
24
|
+
*/
|
|
25
|
+
export function isReportDefinition(obj) {
|
|
26
|
+
return !isEmpty(obj) && obj.type === "report";
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Type-guard testing whether the provided object is an instance of {@link IReport}.
|
|
30
|
+
*
|
|
31
|
+
* @alpha
|
|
32
|
+
*/
|
|
33
|
+
export function isReport(obj) {
|
|
34
|
+
return isReportDefinition(obj) && isObjRef(obj.ref);
|
|
35
|
+
}
|