@peter.prib/renderengine 0.2.4 → 0.2.6
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/README.md +215 -213
- package/REFERENCE.md +99 -7
- package/dist/renderengine-workspace.umd.js +13168 -11966
- package/dist/renderengine.umd.js +7439 -6472
- package/examples/data-model.html +324 -0
- package/package.json +70 -68
- package/src/charting/CheckboxTreeSelector.js +373 -304
- package/src/charting/DiagramEditor.js +3372 -3330
- package/src/charting/DiagramTypeRegistry.js +365 -326
- package/src/charting/Palette.js +119 -119
- package/src/charting/TemplateCatalog.js +61 -59
- package/src/charting/archimate/ArchimateCanvasEditor.js +825 -815
- package/src/charting/archimate/ArchimateElementTemplate.js +208 -195
- package/src/charting/datamodel/DataModel.js +299 -0
- package/src/charting/datamodel/DataModelContext.js +108 -0
- package/src/charting/datamodel/DataModelPerspective.js +84 -0
- package/src/charting/datamodel/LevelMapping.js +38 -0
- package/src/charting/datamodel/LevelSchema.js +41 -0
- package/src/charting/datamodel/index.js +5 -0
- package/src/charting/diagrams/DataModelDiagram.js +160 -86
- package/src/charting/diagrams/DataModelRelationshipStrategy.js +86 -38
- package/src/charting/diagrams/nesting.js +31 -0
- package/src/charting/modelTree/ModelTree.js +202 -164
- package/src/charting/modelTree/ModelTreePanel.js +36 -3
- package/src/charting/modelTree/TreeViewMode.js +131 -110
- package/src/charting/modelTree/modes/FlatTreeMode.js +32 -46
- package/src/charting/modelTree/modes/LayerGroupedTreeMode.js +47 -62
- package/src/charting/modelTree/modes/TypeGroupedTreeMode.js +46 -60
- package/src/datamodel.js +132 -122
- package/src/diagramCatalog.js +35 -30
- package/src/index.js +6 -1
- package/src/workspace/index.js +1 -0
- package/src/workspace/parts/ArchimateCanvasPart.js +5 -2
- package/src/workspace/parts/ChartPart.js +6 -1
- package/src/workspace/parts/DataModelPart.js +234 -0
|
@@ -0,0 +1,324 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="UTF-8">
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
6
|
+
<title>Data Model</title>
|
|
7
|
+
<style>
|
|
8
|
+
html, body { margin: 0; height: 100%; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif; }
|
|
9
|
+
body { display: flex; flex-direction: column; }
|
|
10
|
+
</style>
|
|
11
|
+
</head>
|
|
12
|
+
<body>
|
|
13
|
+
<!-- A data model (DataModelPart) in the workbench: the enterprise ontology at
|
|
14
|
+
three levels, each its own schema, that do not map one to one (Party is a
|
|
15
|
+
Person or an Organisation, both kept in one party table; a Ledger is
|
|
16
|
+
Accounts and their Entries; a Participation realises Party, Arrangement and
|
|
17
|
+
Role; a Product is priced over time and made of resources; a Business
|
|
18
|
+
Direction is measured by targets; a Rule stays a concept). Level shows each one, or Mapping: the three
|
|
19
|
+
side by side, joined where one realises another. Notation draws them in
|
|
20
|
+
Chen, Crow's Foot or UML. It uses every feature: all five cardinalities,
|
|
21
|
+
identifying (solid) and non-identifying (dashed) relationships, primary,
|
|
22
|
+
foreign and composite keys, each column type group, a shape, colour and
|
|
23
|
+
description per concept.
|
|
24
|
+
One schema, read many ways: a perspective (Customer, Regulatory,
|
|
25
|
+
Operations) shows the concepts a stakeholder sees under their names, and
|
|
26
|
+
at the other levels what realises them; a context (Retail AU, Regulatory
|
|
27
|
+
ASIC, Operations) says what they mean there, the rules that hold (notes)
|
|
28
|
+
and where and when it applies. Choosing a perspective brings its context.
|
|
29
|
+
Model ▸ makes, changes and removes your own perspectives and contexts.
|
|
30
|
+
Drag the boxes and notes; they stay put, level by level. Classic scripts,
|
|
31
|
+
so the page opens straight off disk; `npm run datamodel` opens it. -->
|
|
32
|
+
<script src="../dist/renderengine.umd.js"></script>
|
|
33
|
+
<script src="../dist/renderengine-workspace.umd.js"></script>
|
|
34
|
+
<script>
|
|
35
|
+
const { el, registerBuiltinParts, DataModelPart } = window.RenderEngineWorkspace;
|
|
36
|
+
|
|
37
|
+
/** An attribute: `name`, then 'PK' / 'FK' / 'PK FK', and at the physical level a column type. */
|
|
38
|
+
const attr = (name, keys = '', type) => ({
|
|
39
|
+
name, ...(type && { type }), ...(keys.includes('PK') && { isPK: true }), ...(keys.includes('FK') && { isFK: true }),
|
|
40
|
+
});
|
|
41
|
+
/** Where a box sits on its level's diagram: a grid of columns and rows. */
|
|
42
|
+
const at = (column, row, rowHeight = 250) => ({ x: 130 + column * 300, y: 100 + row * rowHeight });
|
|
43
|
+
|
|
44
|
+
// Each level is its own schema. They do not map one to one: Party is a Person or an
|
|
45
|
+
// Organisation, both kept in one party table; a Ledger is Accounts and their Entries; a
|
|
46
|
+
// Participation realises Party, Arrangement and Role at once; a Rule stays a concept.
|
|
47
|
+
const conceptual = {
|
|
48
|
+
entities: [
|
|
49
|
+
{ id: 'party', name: 'Party', ...at(0, 0), color: '#ede9fe', shape: 'person', labelPosition: 'below',
|
|
50
|
+
description: 'A person or legal actor that can act or hold rights.' },
|
|
51
|
+
{ id: 'role', name: 'Party Role', ...at(0, 1), color: '#fae8ff', shape: 'pill',
|
|
52
|
+
description: 'The part a party plays: customer, supplier, employee. A party has many, over time.' },
|
|
53
|
+
{ id: 'arrangement', name: 'Arrangement', ...at(1, 0), color: '#fef9c3', shape: 'contract-box',
|
|
54
|
+
description: 'A contract, agreement, subscription, membership, policy or lease.' },
|
|
55
|
+
{ id: 'product', name: 'Product', ...at(1, 1.5), color: '#dcfce7', shape: 'product-box',
|
|
56
|
+
description: 'What the business offers and sells, under terms: a plan, a policy, a loan. The offer, not the things held.' },
|
|
57
|
+
{ id: 'resource', name: 'Resource', ...at(2, 0), color: '#dbeafe', shape: 'cube',
|
|
58
|
+
description: 'A physical or digital thing of value: product, asset, document, device.' },
|
|
59
|
+
{ id: 'place', name: 'Place', ...at(3, 0), color: '#ffedd5', shape: 'pin', labelPosition: 'below',
|
|
60
|
+
description: 'Where things happen or exist: a building, a room, a cloud region.' },
|
|
61
|
+
{ id: 'event', name: 'Event', ...at(2, 1), color: '#dcfce7', shape: 'ellipse',
|
|
62
|
+
description: 'A change of state the business cares about: an order placed, a payment made.' },
|
|
63
|
+
{ id: 'ledger', name: 'Ledger', ...at(2, 2), color: '#f1f5f9', shape: 'cylinder',
|
|
64
|
+
description: 'The quantitative impact of events, posted to accounts.' },
|
|
65
|
+
{ id: 'classification', name: 'Classification', ...at(3, 1), color: '#ccfbf1', shape: 'hexagon',
|
|
66
|
+
description: 'A code in a scheme that types or grades parties, resources, events and arrangements.' },
|
|
67
|
+
{ id: 'direction', name: 'Business Direction', ...at(1.3, 2.3), color: '#fef3c7', shape: 'target', labelPosition: 'below',
|
|
68
|
+
description: 'Where the business means to go: goals, strategies, plans, policies, and the targets that measure them.' },
|
|
69
|
+
{ id: 'rule', name: 'Rule', ...at(0.2, 2.3), color: '#fee2e2', shape: 'principle',
|
|
70
|
+
description: 'A condition that governs arrangements and events. Kept conceptual: rules are policy, not tables.' },
|
|
71
|
+
],
|
|
72
|
+
relationships: [
|
|
73
|
+
{ source: 'party', target: 'role', name: 'plays', sourceCardinality: '1', targetCardinality: '0..*' },
|
|
74
|
+
{ id: 'enters', source: 'party', target: 'arrangement', name: 'enters', sourceCardinality: '1..*', targetCardinality: '*' },
|
|
75
|
+
{ id: 'covers', source: 'arrangement', target: 'resource', name: 'governs', sourceCardinality: '*', targetCardinality: '*', identifying: false },
|
|
76
|
+
{ source: 'place', target: 'resource', name: 'locates', sourceCardinality: '0..1', targetCardinality: '0..*', identifying: false },
|
|
77
|
+
{ source: 'event', target: 'arrangement', name: 'changes', sourceCardinality: '0..*', targetCardinality: '0..1', identifying: false },
|
|
78
|
+
{ source: 'event', target: 'resource', name: 'changes', sourceCardinality: '0..*', targetCardinality: '0..1', identifying: false },
|
|
79
|
+
{ id: 'records', source: 'event', target: 'ledger', name: 'is recorded in', sourceCardinality: '1', targetCardinality: '1..*' },
|
|
80
|
+
{ source: 'classification', target: 'event', name: 'types', sourceCardinality: '1', targetCardinality: '0..*', identifying: false },
|
|
81
|
+
{ id: 'is-for', source: 'arrangement', target: 'product', name: 'is for', sourceCardinality: '*', targetCardinality: '1', identifying: false },
|
|
82
|
+
{ id: 'packages', source: 'product', target: 'resource', name: 'packages', sourceCardinality: '*', targetCardinality: '*', identifying: false },
|
|
83
|
+
{ source: 'classification', target: 'product', name: 'groups', sourceCardinality: '1', targetCardinality: '0..*', identifying: false },
|
|
84
|
+
{ id: 'shapes', source: 'direction', target: 'product', name: 'shapes', sourceCardinality: '*', targetCardinality: '*', identifying: false },
|
|
85
|
+
{ source: 'direction', target: 'rule', name: 'is enforced by', sourceCardinality: '1', targetCardinality: '0..*', identifying: false },
|
|
86
|
+
{ id: 'imposes', source: 'rule', target: 'arrangement', name: 'governs', sourceCardinality: '*', targetCardinality: '*', identifying: false },
|
|
87
|
+
{ source: 'rule', target: 'event', name: 'validates', sourceCardinality: '*', targetCardinality: '*', identifying: false },
|
|
88
|
+
],
|
|
89
|
+
};
|
|
90
|
+
|
|
91
|
+
const logical = {
|
|
92
|
+
entities: [
|
|
93
|
+
{ id: 'person', name: 'Person', ...at(0, 0), attributes: [attr('party id', 'PK'), attr('given name'), attr('family name'), attr('born on')] },
|
|
94
|
+
{ id: 'organisation', name: 'Organisation', ...at(1, 0), attributes: [attr('party id', 'PK'), attr('legal name'), attr('registration number')] },
|
|
95
|
+
{ id: 'party-role', name: 'Party Role', ...at(0, 1), attributes: [attr('party id', 'PK FK'), attr('role code', 'PK FK'), attr('valid from'), attr('valid to')] },
|
|
96
|
+
{ id: 'arrangement', name: 'Arrangement', ...at(2, 0), attributes: [attr('arrangement id', 'PK'), attr('type', 'FK'), attr('terms'), attr('starts'), attr('ends')] },
|
|
97
|
+
{ id: 'participation', name: 'Participation', ...at(1, 1), attributes: [attr('arrangement id', 'PK FK'), attr('party id', 'PK FK'), attr('role code', 'FK'), attr('share')] },
|
|
98
|
+
{ id: 'resource', name: 'Resource', ...at(3, 0), attributes: [attr('resource id', 'PK'), attr('type', 'FK'), attr('place id', 'FK'), attr('serial number'), attr('specification')] },
|
|
99
|
+
{ id: 'place', name: 'Place', ...at(4, 0), attributes: [attr('place id', 'PK'), attr('name'), attr('location'), attr('time zone')] },
|
|
100
|
+
{ id: 'event', name: 'Event', ...at(3, 1), attributes: [attr('event id', 'PK'), attr('type', 'FK'), attr('occurred at'), attr('arrangement id', 'FK'), attr('resource id', 'FK'), attr('payload')] },
|
|
101
|
+
{ id: 'product', name: 'Product', ...at(2, 1), attributes: [attr('product id', 'PK'), attr('name'), attr('line', 'FK'), attr('launched on'), attr('retired on')] },
|
|
102
|
+
{ id: 'product-price', name: 'Product Price', ...at(1, 2), attributes: [attr('product id', 'PK FK'), attr('valid from', 'PK'), attr('amount'), attr('currency')] },
|
|
103
|
+
{ id: 'product-component', name: 'Product Component', ...at(5, 0), attributes: [attr('product id', 'PK FK'), attr('resource id', 'PK FK'), attr('quantity')] },
|
|
104
|
+
{ id: 'direction', name: 'Business Direction', ...at(0, 2), attributes: [attr('direction id', 'PK'), attr('kind'), attr('statement'), attr('parent id', 'FK'), attr('horizon')] },
|
|
105
|
+
{ id: 'target', name: 'Target', ...at(5, 1), attributes: [attr('direction id', 'PK FK'), attr('measure', 'PK'), attr('product id', 'FK'), attr('value'), attr('unit'), attr('due on')] },
|
|
106
|
+
{ id: 'account', name: 'Account', ...at(2, 2), attributes: [attr('account code', 'PK'), attr('name'), attr('kind')] },
|
|
107
|
+
{ id: 'ledger-entry', name: 'Ledger Entry', ...at(3, 2), attributes: [attr('event id', 'PK FK'), attr('line', 'PK'), attr('account code', 'FK'), attr('amount'), attr('posted on')] },
|
|
108
|
+
{ id: 'scheme', name: 'Classification Scheme', ...at(4, 1), attributes: [attr('scheme', 'PK'), attr('owner')] },
|
|
109
|
+
{ id: 'code', name: 'Classification Code', ...at(4, 2), attributes: [attr('scheme', 'PK FK'), attr('code', 'PK'), attr('label'), attr('parent code', 'FK')] },
|
|
110
|
+
],
|
|
111
|
+
relationships: [
|
|
112
|
+
{ source: 'person', target: 'party-role', name: 'plays', sourceCardinality: '1', targetCardinality: '0..*' },
|
|
113
|
+
{ source: 'organisation', target: 'party-role', name: 'plays', sourceCardinality: '1', targetCardinality: '0..*' },
|
|
114
|
+
{ source: 'arrangement', target: 'participation', name: 'has', sourceCardinality: '1', targetCardinality: '1..*' },
|
|
115
|
+
{ source: 'party-role', target: 'participation', name: 'takes part as', sourceCardinality: '1', targetCardinality: '*', identifying: false },
|
|
116
|
+
{ source: 'arrangement', target: 'resource', name: 'governs', sourceCardinality: '*', targetCardinality: '*', identifying: false },
|
|
117
|
+
{ source: 'place', target: 'resource', name: 'locates', sourceCardinality: '0..1', targetCardinality: '0..*', identifying: false },
|
|
118
|
+
{ source: 'event', target: 'arrangement', name: 'changes', sourceCardinality: '0..*', targetCardinality: '0..1', identifying: false },
|
|
119
|
+
{ source: 'event', target: 'resource', name: 'changes', sourceCardinality: '0..*', targetCardinality: '0..1', identifying: false },
|
|
120
|
+
{ source: 'event', target: 'ledger-entry', name: 'is recorded in', sourceCardinality: '1', targetCardinality: '1..*' },
|
|
121
|
+
{ source: 'account', target: 'ledger-entry', name: 'is posted with', sourceCardinality: '1', targetCardinality: '0..*', identifying: false },
|
|
122
|
+
{ source: 'scheme', target: 'code', name: 'holds', sourceCardinality: '1', targetCardinality: '1..*' },
|
|
123
|
+
{ source: 'product', target: 'arrangement', name: 'is sold as', sourceCardinality: '1', targetCardinality: '0..*', identifying: false },
|
|
124
|
+
{ source: 'product', target: 'product-price', name: 'is priced by', sourceCardinality: '1', targetCardinality: '1..*' },
|
|
125
|
+
{ source: 'product', target: 'product-component', name: 'is made of', sourceCardinality: '1', targetCardinality: '0..*' },
|
|
126
|
+
{ source: 'resource', target: 'product-component', name: 'goes into', sourceCardinality: '1', targetCardinality: '0..*' },
|
|
127
|
+
{ source: 'direction', target: 'target', name: 'is measured by', sourceCardinality: '1', targetCardinality: '0..*' },
|
|
128
|
+
{ source: 'product', target: 'target', name: 'is aimed at by', sourceCardinality: '0..1', targetCardinality: '0..*', identifying: false },
|
|
129
|
+
{ source: 'code', target: 'event', name: 'types', sourceCardinality: '1', targetCardinality: '0..*', identifying: false },
|
|
130
|
+
],
|
|
131
|
+
};
|
|
132
|
+
|
|
133
|
+
const physical = {
|
|
134
|
+
entities: [
|
|
135
|
+
{ id: 'party', name: 'party', ...at(0, 0), attributes: [
|
|
136
|
+
attr('party_id', 'PK', 'BIGINT'), attr('party_kind', '', 'CHAR(1)'), attr('display_name', '', 'VARCHAR(200)'),
|
|
137
|
+
attr('born_on', '', 'DATE'), attr('registration_no', '', 'VARCHAR(20)'), attr('is_active', '', 'BOOLEAN'),
|
|
138
|
+
] },
|
|
139
|
+
{ id: 'party_role', name: 'party_role', ...at(0, 1), attributes: [
|
|
140
|
+
attr('party_id', 'PK FK', 'BIGINT'), attr('role_code', 'PK FK', 'VARCHAR(20)'), attr('valid_from', '', 'DATE'), attr('valid_to', '', 'DATE'),
|
|
141
|
+
] },
|
|
142
|
+
{ id: 'arrangement', name: 'arrangement', ...at(1, 0), attributes: [
|
|
143
|
+
attr('arrangement_id', 'PK', 'BIGINT'), attr('type_code', 'FK', 'VARCHAR(20)'), attr('terms', '', 'JSONB'), attr('starts_on', '', 'DATE'), attr('ends_on', '', 'DATE'),
|
|
144
|
+
] },
|
|
145
|
+
{ id: 'arrangement_party', name: 'arrangement_party', ...at(1, 1), attributes: [
|
|
146
|
+
attr('arrangement_id', 'PK FK', 'BIGINT'), attr('party_id', 'PK FK', 'BIGINT'), attr('role_code', 'FK', 'VARCHAR(20)'), attr('share_pct', '', 'NUMERIC(5,2)'),
|
|
147
|
+
] },
|
|
148
|
+
{ id: 'resource', name: 'resource', ...at(2, 0), attributes: [
|
|
149
|
+
attr('resource_id', 'PK', 'BIGINT'), attr('type_code', 'FK', 'VARCHAR(20)'), attr('place_id', 'FK', 'BIGINT'), attr('serial_no', '', 'VARCHAR(60)'), attr('spec', '', 'JSON'),
|
|
150
|
+
] },
|
|
151
|
+
{ id: 'place', name: 'place', ...at(3, 0), attributes: [
|
|
152
|
+
// GEOGRAPHY is no type group the drawing knows: it shows as unknown (grey).
|
|
153
|
+
attr('place_id', 'PK', 'BIGINT'), attr('name', '', 'TEXT'), attr('location', '', 'GEOGRAPHY'), attr('tz', '', 'VARCHAR(40)'),
|
|
154
|
+
] },
|
|
155
|
+
{ id: 'business_event', name: 'business_event', ...at(2, 1), attributes: [
|
|
156
|
+
attr('event_id', 'PK', 'BIGINT'), attr('type_code', 'FK', 'VARCHAR(20)'), attr('occurred_at', '', 'TIMESTAMP'),
|
|
157
|
+
attr('arrangement_id', 'FK', 'BIGINT'), attr('resource_id', 'FK', 'BIGINT'),
|
|
158
|
+
] },
|
|
159
|
+
{ id: 'event_payload', name: 'event_payload', ...at(1, 2), attributes: [attr('event_id', 'PK FK', 'BIGINT'), attr('payload', '', 'JSONB')] },
|
|
160
|
+
{ id: 'ledger_entry', name: 'ledger_entry', ...at(2, 2), attributes: [
|
|
161
|
+
attr('event_id', 'PK FK', 'BIGINT'), attr('line_no', 'PK', 'SMALLINT'), attr('account_code', 'FK', 'VARCHAR(20)'),
|
|
162
|
+
attr('amount', '', 'DECIMAL(18,2)'), attr('posted_on', '', 'DATE'),
|
|
163
|
+
] },
|
|
164
|
+
{ id: 'product', name: 'product', ...at(4, 0), attributes: [
|
|
165
|
+
attr('product_id', 'PK', 'BIGINT'), attr('name', '', 'VARCHAR(120)'), attr('line_code', 'FK', 'VARCHAR(20)'),
|
|
166
|
+
attr('launched_on', '', 'DATE'), attr('retired_on', '', 'DATE'), attr('components', '', 'JSONB'),
|
|
167
|
+
] },
|
|
168
|
+
{ id: 'product_price', name: 'product_price', ...at(4, 1), attributes: [
|
|
169
|
+
attr('product_id', 'PK FK', 'BIGINT'), attr('valid_from', 'PK', 'DATE'), attr('amount', '', 'DECIMAL(12,2)'), attr('currency', '', 'CHAR(3)'),
|
|
170
|
+
] },
|
|
171
|
+
{ id: 'business_direction', name: 'business_direction', ...at(0, 2), attributes: [
|
|
172
|
+
attr('direction_id', 'PK', 'BIGINT'), attr('kind', '', 'VARCHAR(20)'), attr('statement', '', 'TEXT'),
|
|
173
|
+
attr('parent_id', 'FK', 'BIGINT'), attr('horizon', '', 'DATE'),
|
|
174
|
+
] },
|
|
175
|
+
{ id: 'direction_target', name: 'direction_target', ...at(4, 2), attributes: [
|
|
176
|
+
attr('direction_id', 'PK FK', 'BIGINT'), attr('measure', 'PK', 'VARCHAR(40)'), attr('product_id', 'FK', 'BIGINT'),
|
|
177
|
+
attr('value', '', 'NUMERIC(14,2)'), attr('unit', '', 'VARCHAR(10)'), attr('due_on', '', 'DATE'),
|
|
178
|
+
] },
|
|
179
|
+
{ id: 'account', name: 'account', ...at(3, 2), attributes: [attr('account_code', 'PK', 'VARCHAR(20)'), attr('name', '', 'TEXT'), attr('kind', '', 'CHAR(1)')] },
|
|
180
|
+
{ id: 'classification', name: 'classification', ...at(3, 1), attributes: [
|
|
181
|
+
attr('scheme', 'PK', 'VARCHAR(40)'), attr('code', 'PK', 'VARCHAR(20)'), attr('label', '', 'TEXT'),
|
|
182
|
+
attr('parent_code', 'FK', 'VARCHAR(20)'), attr('notes'), // no type at all: unknown too
|
|
183
|
+
] },
|
|
184
|
+
],
|
|
185
|
+
relationships: [
|
|
186
|
+
{ source: 'party', target: 'party_role', name: 'plays', sourceCardinality: '1', targetCardinality: '0..*' },
|
|
187
|
+
{ source: 'arrangement', target: 'arrangement_party', name: 'has', sourceCardinality: '1', targetCardinality: '1..*' },
|
|
188
|
+
{ source: 'party_role', target: 'arrangement_party', name: 'takes part as', sourceCardinality: '1', targetCardinality: '*', identifying: false },
|
|
189
|
+
{ source: 'place', target: 'resource', name: 'locates', sourceCardinality: '0..1', targetCardinality: '0..*', identifying: false },
|
|
190
|
+
{ source: 'business_event', target: 'arrangement', name: 'changes', sourceCardinality: '0..*', targetCardinality: '0..1', identifying: false },
|
|
191
|
+
{ source: 'business_event', target: 'resource', name: 'changes', sourceCardinality: '0..*', targetCardinality: '0..1', identifying: false },
|
|
192
|
+
{ source: 'business_event', target: 'event_payload', name: 'carries', sourceCardinality: '1', targetCardinality: '0..1' },
|
|
193
|
+
{ source: 'business_event', target: 'ledger_entry', name: 'is recorded in', sourceCardinality: '1', targetCardinality: '1..*' },
|
|
194
|
+
{ source: 'account', target: 'ledger_entry', name: 'is posted with', sourceCardinality: '1', targetCardinality: '0..*', identifying: false },
|
|
195
|
+
{ source: 'classification', target: 'business_event', name: 'types', sourceCardinality: '1', targetCardinality: '0..*', identifying: false },
|
|
196
|
+
{ source: 'product', target: 'arrangement', name: 'is sold as', sourceCardinality: '1', targetCardinality: '0..*', identifying: false },
|
|
197
|
+
{ source: 'product', target: 'product_price', name: 'is priced by', sourceCardinality: '1', targetCardinality: '1..*' },
|
|
198
|
+
{ source: 'business_direction', target: 'direction_target', name: 'is measured by', sourceCardinality: '1', targetCardinality: '0..*' },
|
|
199
|
+
{ source: 'product', target: 'direction_target', name: 'is aimed at by', sourceCardinality: '0..1', targetCardinality: '0..*', identifying: false },
|
|
200
|
+
],
|
|
201
|
+
};
|
|
202
|
+
|
|
203
|
+
// How the levels map: [concept, logical entity], then [logical entity, table]; any number either way.
|
|
204
|
+
const mappings = [
|
|
205
|
+
{ from: 'conceptual', to: 'logical', pairs: [
|
|
206
|
+
['party', 'person'], ['party', 'organisation'], ['role', 'party-role'],
|
|
207
|
+
['party', 'participation'], ['arrangement', 'participation'], ['role', 'participation'],
|
|
208
|
+
['arrangement', 'arrangement'], ['resource', 'resource'], ['place', 'place'], ['event', 'event'],
|
|
209
|
+
['ledger', 'account'], ['ledger', 'ledger-entry'], ['classification', 'scheme'], ['classification', 'code'],
|
|
210
|
+
['product', 'product'], ['product', 'product-price'], ['product', 'product-component'], ['resource', 'product-component'],
|
|
211
|
+
['direction', 'direction'], ['direction', 'target'],
|
|
212
|
+
] },
|
|
213
|
+
{ from: 'logical', to: 'physical', pairs: [
|
|
214
|
+
['person', 'party'], ['organisation', 'party'], ['party-role', 'party_role'], ['participation', 'arrangement_party'],
|
|
215
|
+
['arrangement', 'arrangement'], ['resource', 'resource'], ['place', 'place'],
|
|
216
|
+
['event', 'business_event'], ['event', 'event_payload'], ['account', 'account'], ['ledger-entry', 'ledger_entry'],
|
|
217
|
+
['scheme', 'classification'], ['code', 'classification'],
|
|
218
|
+
['product', 'product'], ['product-component', 'product'], ['product-price', 'product_price'],
|
|
219
|
+
['direction', 'business_direction'], ['target', 'direction_target'],
|
|
220
|
+
] },
|
|
221
|
+
];
|
|
222
|
+
|
|
223
|
+
// Perspectives: who is looking, which entities they see and what they call them.
|
|
224
|
+
const perspectives = [
|
|
225
|
+
{
|
|
226
|
+
id: 'customer', name: 'Customer', context: 'retail', description: 'How a customer sees us: what they subscribe to and pay for',
|
|
227
|
+
entities: ['party', 'role', 'arrangement', 'product', 'resource', 'event', 'ledger'],
|
|
228
|
+
names: { party: 'Customer', role: 'Subscriber', arrangement: 'Subscription', product: 'Plan', resource: 'Device', event: 'Usage', ledger: 'Billing' },
|
|
229
|
+
relationshipNames: { covers: 'includes', records: 'is billed in' },
|
|
230
|
+
},
|
|
231
|
+
{
|
|
232
|
+
id: 'regulatory', name: 'Regulatory', context: 'regulatory', description: 'What a regulator holds us to',
|
|
233
|
+
entities: ['party', 'arrangement', 'event', 'ledger', 'rule', 'classification', 'place'],
|
|
234
|
+
names: { party: 'Legal Entity', arrangement: 'Compliance Obligation', event: 'Reportable Event', ledger: 'Audit Trail', rule: 'Regulation', place: 'Jurisdiction' },
|
|
235
|
+
relationshipNames: { imposes: 'imposes', records: 'is evidenced by' },
|
|
236
|
+
},
|
|
237
|
+
{
|
|
238
|
+
id: 'operations', name: 'Operations', context: 'operations', description: 'What we run and maintain, where',
|
|
239
|
+
entities: ['resource', 'place', 'event', 'ledger', 'classification'],
|
|
240
|
+
names: { resource: 'Asset', place: 'Site', event: 'Work Order', ledger: 'Cost Ledger' },
|
|
241
|
+
},
|
|
242
|
+
{
|
|
243
|
+
id: 'executive', name: 'Executive', context: 'strategy', description: 'Where we are going, with what offers, and how we measure it',
|
|
244
|
+
entities: ['direction', 'product', 'ledger', 'party', 'classification'],
|
|
245
|
+
names: { direction: 'Strategy', product: 'Offering', ledger: 'Financials', party: 'Market', classification: 'Product Line' },
|
|
246
|
+
relationshipNames: { shapes: 'invests in' },
|
|
247
|
+
},
|
|
248
|
+
];
|
|
249
|
+
|
|
250
|
+
// Contexts: what the entities mean there, the rules that hold (each a note on its entities), where and when.
|
|
251
|
+
const contexts = [
|
|
252
|
+
{
|
|
253
|
+
id: 'retail', name: 'Retail (AU)', jurisdiction: 'AU', validFrom: '2024-07-01',
|
|
254
|
+
description: 'Selling subscriptions to consumers and small businesses',
|
|
255
|
+
meanings: {
|
|
256
|
+
party: 'Someone who buys from us: a person or a small business.',
|
|
257
|
+
arrangement: 'A recurring subscription, billed monthly.',
|
|
258
|
+
ledger: 'Invoices and payments: what a customer owes and has paid.',
|
|
259
|
+
product: 'A plan a customer subscribes to, at a monthly price.',
|
|
260
|
+
},
|
|
261
|
+
constraints: [
|
|
262
|
+
{ id: 'gst', text: 'Prices include GST (10%)', applies: ['ledger', 'product'], x: 1030, y: 600 },
|
|
263
|
+
{ id: 'one-price', text: 'A product has one current price', applies: ['product'], x: 730, y: 790 },
|
|
264
|
+
{ id: 'one-payer', text: 'A subscription has exactly one paying customer', applies: ['arrangement', 'party'], x: 280, y: 225 },
|
|
265
|
+
],
|
|
266
|
+
},
|
|
267
|
+
{
|
|
268
|
+
id: 'regulatory', name: 'Regulatory (ASIC)', jurisdiction: 'AU', validFrom: '2024-01-01', validTo: '2030-12-31',
|
|
269
|
+
description: 'Corporate and financial-services regulation',
|
|
270
|
+
meanings: {
|
|
271
|
+
party: 'A legal entity, identified by its ABN or ACN.',
|
|
272
|
+
arrangement: 'An obligation a regulator can enforce.',
|
|
273
|
+
event: 'An event that must be reported.',
|
|
274
|
+
ledger: 'The audit trail: immutable, kept seven years.',
|
|
275
|
+
rule: 'A regulation or licence condition.',
|
|
276
|
+
},
|
|
277
|
+
constraints: [
|
|
278
|
+
{ id: 'immutable', text: 'Entries are never changed: a correction is a new entry', applies: ['ledger'], x: 1030, y: 600 },
|
|
279
|
+
{ id: 'retention', text: 'Records are kept for 7 years', applies: ['ledger', 'event'], x: 1030, y: 780 },
|
|
280
|
+
{ id: 'identified', text: 'Every legal entity has an ABN or ACN', applies: ['party'], x: 280, y: 225 },
|
|
281
|
+
],
|
|
282
|
+
},
|
|
283
|
+
{
|
|
284
|
+
id: 'operations', name: 'Operations', description: 'Running and maintaining assets on sites',
|
|
285
|
+
meanings: {
|
|
286
|
+
resource: 'A maintained asset: plant, vehicle, device.',
|
|
287
|
+
place: 'A site where assets are kept and work is done.',
|
|
288
|
+
event: 'A work order, an inspection or a sensor reading.',
|
|
289
|
+
},
|
|
290
|
+
constraints: [
|
|
291
|
+
{ id: 'one-site', text: 'Every asset is at exactly one site', applies: ['resource', 'place'], x: 880, y: 225 },
|
|
292
|
+
],
|
|
293
|
+
},
|
|
294
|
+
{
|
|
295
|
+
id: 'strategy', name: 'Strategy FY27', validFrom: '2026-07-01', validTo: '2027-06-30',
|
|
296
|
+
description: 'The plan for the financial year: what we offer, and the targets it is held to',
|
|
297
|
+
meanings: {
|
|
298
|
+
direction: 'A goal or strategy of the plan, with the targets that measure it.',
|
|
299
|
+
product: 'An offering in the portfolio, kept, grown or retired as the plan says.',
|
|
300
|
+
ledger: 'The financial results the targets are read from.',
|
|
301
|
+
},
|
|
302
|
+
constraints: [
|
|
303
|
+
{ id: 'every-target', text: 'Every offering has a revenue target', applies: ['product', 'direction'], x: 730, y: 790 },
|
|
304
|
+
{ id: 'review', text: 'Targets are reviewed each quarter', applies: ['direction'], x: 130, y: 860 },
|
|
305
|
+
],
|
|
306
|
+
},
|
|
307
|
+
];
|
|
308
|
+
|
|
309
|
+
const ws = document.body.appendChild(el({
|
|
310
|
+
tag: 'ws-workspace',
|
|
311
|
+
attrs: { label: 'Data Model', theme: 'light' },
|
|
312
|
+
style: { flex: '1 1 auto', minHeight: '0' },
|
|
313
|
+
}));
|
|
314
|
+
registerBuiltinParts(ws);
|
|
315
|
+
ws.registerPart(DataModelPart);
|
|
316
|
+
ws.addParts([{
|
|
317
|
+
id: 'model', type: 'data-model', title: 'Enterprise ontology',
|
|
318
|
+
levels: { conceptual, logical, physical }, mappings, perspectives, contexts, level: 'conceptual', notation: 'crowsfoot',
|
|
319
|
+
}]);
|
|
320
|
+
ws.registerPerspective('Data model', { type: 'part', partId: 'model' });
|
|
321
|
+
ws.activatePerspective('Data model');
|
|
322
|
+
</script>
|
|
323
|
+
</body>
|
|
324
|
+
</html>
|
package/package.json
CHANGED
|
@@ -1,68 +1,70 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "@peter.prib/renderengine",
|
|
3
|
-
"version": "0.2.
|
|
4
|
-
"description": "ArchiMate modeller, diagram editor and chart library for the browser, with no runtime dependencies.",
|
|
5
|
-
"type": "module",
|
|
6
|
-
"main": "src/index.js",
|
|
7
|
-
"module": "src/index.js",
|
|
8
|
-
"browser": "dist/renderengine.umd.js",
|
|
9
|
-
"exports": {
|
|
10
|
-
".": "./src/index.js",
|
|
11
|
-
"./workspace": "./src/workspace/index.js",
|
|
12
|
-
"./src/*": "./src/*",
|
|
13
|
-
"./dist/*": "./dist/*",
|
|
14
|
-
"./package.json": "./package.json"
|
|
15
|
-
},
|
|
16
|
-
"files": [
|
|
17
|
-
"src/",
|
|
18
|
-
"dist/*.umd.js",
|
|
19
|
-
"examples/archimate.html",
|
|
20
|
-
"examples/diagram-editor.html",
|
|
21
|
-
"
|
|
22
|
-
"
|
|
23
|
-
"
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
"
|
|
28
|
-
"
|
|
29
|
-
"
|
|
30
|
-
"
|
|
31
|
-
"
|
|
32
|
-
"
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
"
|
|
38
|
-
"
|
|
39
|
-
"
|
|
40
|
-
"
|
|
41
|
-
"
|
|
42
|
-
"
|
|
43
|
-
"
|
|
44
|
-
"
|
|
45
|
-
"
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
"
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
"rollup": "^
|
|
67
|
-
|
|
68
|
-
|
|
1
|
+
{
|
|
2
|
+
"name": "@peter.prib/renderengine",
|
|
3
|
+
"version": "0.2.6",
|
|
4
|
+
"description": "ArchiMate modeller, diagram editor and chart library for the browser, with no runtime dependencies.",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "src/index.js",
|
|
7
|
+
"module": "src/index.js",
|
|
8
|
+
"browser": "dist/renderengine.umd.js",
|
|
9
|
+
"exports": {
|
|
10
|
+
".": "./src/index.js",
|
|
11
|
+
"./workspace": "./src/workspace/index.js",
|
|
12
|
+
"./src/*": "./src/*",
|
|
13
|
+
"./dist/*": "./dist/*",
|
|
14
|
+
"./package.json": "./package.json"
|
|
15
|
+
},
|
|
16
|
+
"files": [
|
|
17
|
+
"src/",
|
|
18
|
+
"dist/*.umd.js",
|
|
19
|
+
"examples/archimate.html",
|
|
20
|
+
"examples/diagram-editor.html",
|
|
21
|
+
"examples/data-model.html",
|
|
22
|
+
"README.md",
|
|
23
|
+
"REFERENCE.md",
|
|
24
|
+
"LICENSE"
|
|
25
|
+
],
|
|
26
|
+
"scripts": {
|
|
27
|
+
"start": "node scripts/open.mjs examples/archimate.html",
|
|
28
|
+
"archimate": "node scripts/open.mjs examples/archimate.html",
|
|
29
|
+
"diagram": "node scripts/open.mjs examples/diagram-editor.html",
|
|
30
|
+
"datamodel": "node scripts/open.mjs examples/data-model.html",
|
|
31
|
+
"test": "node --test --test-timeout=10000 ./test/*.js ./test/charting/*.js ./test/charting/charts/*.js ./test/charting/diagrams/*.js ./test/charting/shapes/*.js",
|
|
32
|
+
"build": "rollup -c",
|
|
33
|
+
"prepublishOnly": "npm test && npm run build",
|
|
34
|
+
"screenshots": "node scripts/screenshots/screenshots.mjs"
|
|
35
|
+
},
|
|
36
|
+
"keywords": [
|
|
37
|
+
"archimate",
|
|
38
|
+
"archi",
|
|
39
|
+
"diagram",
|
|
40
|
+
"diagram-editor",
|
|
41
|
+
"modelling",
|
|
42
|
+
"charts",
|
|
43
|
+
"svg",
|
|
44
|
+
"canvas",
|
|
45
|
+
"render",
|
|
46
|
+
"engine",
|
|
47
|
+
"graphics"
|
|
48
|
+
],
|
|
49
|
+
"author": "Peter Prib <peter.prib@gmail.com>",
|
|
50
|
+
"license": "MIT",
|
|
51
|
+
"repository": {
|
|
52
|
+
"type": "git",
|
|
53
|
+
"url": "git+https://gitlab.com/peter.prib/renderengine.git"
|
|
54
|
+
},
|
|
55
|
+
"homepage": "https://gitlab.com/peter.prib/renderengine#readme",
|
|
56
|
+
"bugs": {
|
|
57
|
+
"url": "https://gitlab.com/peter.prib/renderengine/-/issues"
|
|
58
|
+
},
|
|
59
|
+
"engines": {
|
|
60
|
+
"node": ">=18"
|
|
61
|
+
},
|
|
62
|
+
"publishConfig": {
|
|
63
|
+
"access": "public"
|
|
64
|
+
},
|
|
65
|
+
"devDependencies": {
|
|
66
|
+
"@rollup/plugin-commonjs": "^25.0.8",
|
|
67
|
+
"@rollup/plugin-node-resolve": "^15.3.1",
|
|
68
|
+
"rollup": "^3.30.0"
|
|
69
|
+
}
|
|
70
|
+
}
|