@peter.prib/renderengine 0.2.6 → 0.2.7
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 +4 -0
- package/REFERENCE.md +180 -2
- package/dist/renderengine-workspace.umd.js +8704 -5310
- package/dist/renderengine.umd.js +5675 -3398
- package/examples/archimate.html +68 -66
- package/examples/data-model.html +223 -13
- package/package.json +1 -1
- package/src/bian.js +182 -0
- package/src/charting/DiagramEditor.js +5 -26
- package/src/charting/DiagramTypeRegistry.js +8 -2
- package/src/charting/ModelCheckDialog.js +63 -0
- package/src/charting/ModelChecker.js +26 -0
- package/src/charting/ViewTabStrip.js +94 -81
- package/src/charting/datamodel/BianLandscapeReader.js +185 -0
- package/src/charting/datamodel/BianSemanticApiReader.js +183 -0
- package/src/charting/datamodel/DataModel.js +356 -10
- package/src/charting/datamodel/DataModelChecker.js +92 -0
- package/src/charting/datamodel/DataModelCompared.js +127 -0
- package/src/charting/datamodel/DataModelFileFormat.js +33 -0
- package/src/charting/datamodel/DataModelPerspective.js +45 -0
- package/src/charting/datamodel/DataType.js +108 -0
- package/src/charting/datamodel/EnumerationType.js +51 -0
- package/src/charting/datamodel/ServiceDomain.js +177 -0
- package/src/charting/datamodel/ServiceLandscape.js +104 -0
- package/src/charting/datamodel/StructuredType.js +63 -0
- package/src/charting/datamodel/index.js +10 -0
- package/src/charting/diagramModel/MergeModelCommand.js +43 -37
- package/src/charting/diagramModel/OpenViewList.js +75 -0
- package/src/charting/diagramModel/ViewSetChecker.js +22 -34
- package/src/charting/diagrams/DataModelRelationshipStrategy.js +12 -4
- package/src/charting/diagrams/EdgeGeometry.js +578 -553
- package/src/charting/diagrams/GraphDiagram.js +11 -1
- package/src/charting/diagrams/NodeGeometry.js +169 -158
- package/src/charting/glyphs/PersonGlyph.js +24 -23
- package/src/index.js +2666 -2664
- package/src/workspace/EditorShell.js +166 -67
- package/src/workspace/PanelLayout.js +56 -0
- package/src/workspace/layout/TabsNode.js +205 -191
- package/src/workspace/parts/ArchimateCanvasPart.js +5 -7
- package/src/workspace/parts/DataModelPart.js +339 -29
- package/src/workspace/parts/DiagramEditorPart.js +2 -8
- package/src/workspace/parts/EditorPart.js +461 -407
- package/src/workspace/parts/ModelFile.js +216 -187
- package/src/workspace/parts/ModelsPart.js +483 -192
- package/src/workspace/storage/BackupFolder.js +145 -0
- package/src/workspace/storage/KeyValueStore.js +92 -0
- package/src/workspace/storage/ModelLibrary.js +65 -0
- package/src/workspace/workArea.js +417 -413
- package/src/yaml/YamlReader.js +372 -0
package/examples/archimate.html
CHANGED
|
@@ -1,66 +1,68 @@
|
|
|
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>ArchiMate Modeller</title>
|
|
7
|
-
</head>
|
|
8
|
-
<body>
|
|
9
|
-
<!-- Deliberately empty: the workbench and the modeller part are built from
|
|
10
|
-
JavaScript and JSON specs. A classic script (not type="module") so the
|
|
11
|
-
page also opens straight off disk. The modeller is the diagram editor's
|
|
12
|
-
canvas (ArchimateCanvasPart), one per model in a ModelsPart, so several
|
|
13
|
-
models can be open at once (File > New model, Open… in a new tab);
|
|
14
|
-
archimate-legacy.html keeps the graph-engine editor for comparison. -->
|
|
15
|
-
<script>
|
|
16
|
-
function runModeller() {
|
|
17
|
-
const { el, registerBuiltinParts, ArchimateCanvasPart } = RenderEngineWorkspace;
|
|
18
|
-
|
|
19
|
-
Object.assign(document.documentElement.style, { height: '100%' });
|
|
20
|
-
Object.assign(document.body.style, { margin: '0', height: '100%', display: 'flex' });
|
|
21
|
-
|
|
22
|
-
const ws = document.body.appendChild(el({
|
|
23
|
-
tag: 'ws-workspace',
|
|
24
|
-
attrs: { label: 'ArchiMate Modeller', theme: 'light' },
|
|
25
|
-
style: { flex: '1 1 auto', minHeight: '0' },
|
|
26
|
-
}));
|
|
27
|
-
registerBuiltinParts(ws);
|
|
28
|
-
ws.registerPart(ArchimateCanvasPart);
|
|
29
|
-
|
|
30
|
-
// The models open at once: a tab each. The first is this sample; New model makes empty ones.
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
{ id: '
|
|
39
|
-
{ id: '
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
{ source: '
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
</
|
|
66
|
-
|
|
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>ArchiMate Modeller</title>
|
|
7
|
+
</head>
|
|
8
|
+
<body>
|
|
9
|
+
<!-- Deliberately empty: the workbench and the modeller part are built from
|
|
10
|
+
JavaScript and JSON specs. A classic script (not type="module") so the
|
|
11
|
+
page also opens straight off disk. The modeller is the diagram editor's
|
|
12
|
+
canvas (ArchimateCanvasPart), one per model in a ModelsPart, so several
|
|
13
|
+
models can be open at once (File > New model, Open… in a new tab);
|
|
14
|
+
archimate-legacy.html keeps the graph-engine editor for comparison. -->
|
|
15
|
+
<script>
|
|
16
|
+
function runModeller() {
|
|
17
|
+
const { el, registerBuiltinParts, ArchimateCanvasPart } = RenderEngineWorkspace;
|
|
18
|
+
|
|
19
|
+
Object.assign(document.documentElement.style, { height: '100%' });
|
|
20
|
+
Object.assign(document.body.style, { margin: '0', height: '100%', display: 'flex' });
|
|
21
|
+
|
|
22
|
+
const ws = document.body.appendChild(el({
|
|
23
|
+
tag: 'ws-workspace',
|
|
24
|
+
attrs: { label: 'ArchiMate Modeller', theme: 'light' },
|
|
25
|
+
style: { flex: '1 1 auto', minHeight: '0' },
|
|
26
|
+
}));
|
|
27
|
+
registerBuiltinParts(ws);
|
|
28
|
+
ws.registerPart(ArchimateCanvasPart);
|
|
29
|
+
|
|
30
|
+
// The models open at once: a tab each. The first is this sample; New model makes empty ones.
|
|
31
|
+
// keep: every model is kept in this browser as it is edited, and those open reopen next time;
|
|
32
|
+
// File > This browser backs them up (to a folder chosen once, such as one OneDrive or Google Drive syncs).
|
|
33
|
+
ws.addParts([{
|
|
34
|
+
id: 'models', type: 'models', editorType: 'archimate-canvas', newModel: { analysis: true }, keep: true,
|
|
35
|
+
models: [{
|
|
36
|
+
id: 'modeller', name: 'Sample model', analysis: true,
|
|
37
|
+
elements: [
|
|
38
|
+
{ id: 'customer', name: 'Customer', layer: 'business', type: 'business-actor', icon: '👤' },
|
|
39
|
+
{ id: 'order', name: 'Order Process', layer: 'business', type: 'business-process' },
|
|
40
|
+
{ id: 'order-svc', name: 'Order Service', layer: 'application', type: 'application-service' },
|
|
41
|
+
{ id: 'db', name: 'Database', layer: 'technology', type: 'node', icon: '🗄️' },
|
|
42
|
+
],
|
|
43
|
+
relationships: [
|
|
44
|
+
{ source: 'customer', target: 'order', kind: 'assignment' },
|
|
45
|
+
{ source: 'order-svc', target: 'order', kind: 'serving' },
|
|
46
|
+
{ source: 'db', target: 'order-svc', kind: 'serving' },
|
|
47
|
+
],
|
|
48
|
+
views: [{
|
|
49
|
+
id: 'default',
|
|
50
|
+
name: 'Default View',
|
|
51
|
+
elementIds: ['customer', 'order', 'order-svc', 'db'],
|
|
52
|
+
layout: {
|
|
53
|
+
customer: { x: 80, y: 80 },
|
|
54
|
+
order: { x: 300, y: 80 },
|
|
55
|
+
'order-svc': { x: 300, y: 200 },
|
|
56
|
+
db: { x: 80, y: 200 },
|
|
57
|
+
},
|
|
58
|
+
}],
|
|
59
|
+
}],
|
|
60
|
+
}]);
|
|
61
|
+
|
|
62
|
+
ws.registerPerspective('Modelling', { type: 'part', partId: 'models' });
|
|
63
|
+
ws.activatePerspective('Modelling');
|
|
64
|
+
}
|
|
65
|
+
</script>
|
|
66
|
+
<script src="../dist/renderengine-workspace.umd.js" onload="runModeller()"></script>
|
|
67
|
+
</body>
|
|
68
|
+
</html>
|
package/examples/data-model.html
CHANGED
|
@@ -14,7 +14,9 @@
|
|
|
14
14
|
three levels, each its own schema, that do not map one to one (Party is a
|
|
15
15
|
Person or an Organisation, both kept in one party table; a Ledger is
|
|
16
16
|
Accounts and their Entries; a Participation realises Party, Arrangement and
|
|
17
|
-
Role;
|
|
17
|
+
Role; an Agreement (the contract) governs Arrangements (the terms a
|
|
18
|
+
product is provided on), as BIAN keeps them apart; a Product has features
|
|
19
|
+
and is subject to conditions, is priced over time and made of resources; a Business
|
|
18
20
|
Direction is measured by targets; a Rule stays a concept). Level shows each one, or Mapping: the three
|
|
19
21
|
side by side, joined where one realises another. Notation draws them in
|
|
20
22
|
Chen, Crow's Foot or UML. It uses every feature: all five cardinalities,
|
|
@@ -27,6 +29,20 @@
|
|
|
27
29
|
ASIC, Operations) says what they mean there, the rules that hold (notes)
|
|
28
30
|
and where and when it applies. Choosing a perspective brings its context.
|
|
29
31
|
Model ▸ makes, changes and removes your own perspectives and contexts.
|
|
32
|
+
A second base, Retail banking (BIAN), is a retail-banking slice at BIAN
|
|
33
|
+
level: its perspectives are BIAN service domains (Current Account, Consumer
|
|
34
|
+
Loan, Customer Agreement, Payment Order, the Party and Product directories),
|
|
35
|
+
each managing a control record broken down by behaviour qualifiers; seen
|
|
36
|
+
through one at the logical level they are marked, with a note of its
|
|
37
|
+
service operations. Model ▸ New service domain… makes one of your own.
|
|
38
|
+
The ontology is also the base: File ▸ New ▸ From base makes a model from a
|
|
39
|
+
copy of it, File ▸ Duplicate model copies the one in front, and Tools ▸
|
|
40
|
+
Compare with / Merge from compare or merge with the base or another open
|
|
41
|
+
model (Edit ▸ Undo takes a merge back).
|
|
42
|
+
File ▸ saves it as a .datamodel.json, opens one, makes a new model in a
|
|
43
|
+
tab of its own; every model is kept in this browser as it changes (and
|
|
44
|
+
reopens next time), and File ▸ This browser backs them up to a folder
|
|
45
|
+
chosen once, such as one OneDrive or Google Drive syncs.
|
|
30
46
|
Drag the boxes and notes; they stay put, level by level. Classic scripts,
|
|
31
47
|
so the page opens straight off disk; `npm run datamodel` opens it. -->
|
|
32
48
|
<script src="../dist/renderengine.umd.js"></script>
|
|
@@ -46,13 +62,19 @@
|
|
|
46
62
|
// Participation realises Party, Arrangement and Role at once; a Rule stays a concept.
|
|
47
63
|
const conceptual = {
|
|
48
64
|
entities: [
|
|
49
|
-
{ id: 'party', name: 'Party', ...at(0, 0), color: '#ede9fe', shape: 'person', labelPosition: 'below',
|
|
65
|
+
{ id: 'party', name: 'Party', ...at(0, 0), color: '#ede9fe', shape: 'person', labelPosition: 'below', details: { bian: 'Party' },
|
|
50
66
|
description: 'A person or legal actor that can act or hold rights.' },
|
|
51
67
|
{ id: 'role', name: 'Party Role', ...at(0, 1), color: '#fae8ff', shape: 'pill',
|
|
52
68
|
description: 'The part a party plays: customer, supplier, employee. A party has many, over time.' },
|
|
53
|
-
{ id: '
|
|
54
|
-
description: '
|
|
55
|
-
{ id: '
|
|
69
|
+
{ id: 'agreement', name: 'Agreement', ...at(1, 0), color: '#fef9c3', shape: 'contract-box', details: { bian: 'Agreement' },
|
|
70
|
+
description: 'The contract parties sign: the promises they agree on as one unit.' },
|
|
71
|
+
{ id: 'arrangement', name: 'Arrangement', ...at(0.6, 1.0), color: '#fef3c7', details: { bian: 'Arrangement' },
|
|
72
|
+
description: 'The terms a product is provided on, under an agreement: a subscription, an account, a loan, a lease.' },
|
|
73
|
+
{ id: 'feature', name: 'Product Feature', ...at(0, 1.5), color: '#d1fae5', details: { bian: 'Feature' },
|
|
74
|
+
description: 'A feature a product is made up of: interest, payments, an overdraft.' },
|
|
75
|
+
{ id: 'condition', name: 'Condition', ...at(2, 1.5), color: '#fee2e2', details: { bian: 'Condition' },
|
|
76
|
+
description: 'A fee, rate, limit or eligibility rule a product is subject to.' },
|
|
77
|
+
{ id: 'product', name: 'Product', ...at(1, 1.5), color: '#dcfce7', shape: 'product-box', details: { bian: 'Product' },
|
|
56
78
|
description: 'What the business offers and sells, under terms: a plan, a policy, a loan. The offer, not the things held.' },
|
|
57
79
|
{ id: 'resource', name: 'Resource', ...at(2, 0), color: '#dbeafe', shape: 'cube',
|
|
58
80
|
description: 'A physical or digital thing of value: product, asset, document, device.' },
|
|
@@ -71,7 +93,10 @@
|
|
|
71
93
|
],
|
|
72
94
|
relationships: [
|
|
73
95
|
{ source: 'party', target: 'role', name: 'plays', sourceCardinality: '1', targetCardinality: '0..*' },
|
|
74
|
-
{ id: '
|
|
96
|
+
{ id: 'signs', source: 'party', target: 'agreement', name: 'signs', sourceCardinality: '1..*', targetCardinality: '*' },
|
|
97
|
+
{ id: 'governs', source: 'agreement', target: 'arrangement', name: 'governs', sourceCardinality: '1', targetCardinality: '1..*' },
|
|
98
|
+
{ id: 'has-feature', source: 'product', target: 'feature', name: 'has', sourceCardinality: '1', targetCardinality: '0..*' },
|
|
99
|
+
{ id: 'subject-to', source: 'product', target: 'condition', name: 'is subject to', sourceCardinality: '*', targetCardinality: '*', identifying: false },
|
|
75
100
|
{ id: 'covers', source: 'arrangement', target: 'resource', name: 'governs', sourceCardinality: '*', targetCardinality: '*', identifying: false },
|
|
76
101
|
{ source: 'place', target: 'resource', name: 'locates', sourceCardinality: '0..1', targetCardinality: '0..*', identifying: false },
|
|
77
102
|
{ source: 'event', target: 'arrangement', name: 'changes', sourceCardinality: '0..*', targetCardinality: '0..1', identifying: false },
|
|
@@ -93,7 +118,10 @@
|
|
|
93
118
|
{ id: 'person', name: 'Person', ...at(0, 0), attributes: [attr('party id', 'PK'), attr('given name'), attr('family name'), attr('born on')] },
|
|
94
119
|
{ id: 'organisation', name: 'Organisation', ...at(1, 0), attributes: [attr('party id', 'PK'), attr('legal name'), attr('registration number')] },
|
|
95
120
|
{ 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('
|
|
121
|
+
{ id: 'arrangement', name: 'Arrangement', ...at(2, 0), attributes: [attr('arrangement id', 'PK'), attr('agreement id', 'FK'), attr('type', 'FK'), attr('starts'), attr('ends')] },
|
|
122
|
+
{ id: 'agreement', name: 'Agreement', ...at(1, 3), attributes: [attr('agreement id', 'PK'), attr('party id', 'FK'), attr('signed on'), attr('terms')] },
|
|
123
|
+
{ id: 'product-feature', name: 'Product Feature', ...at(2, 3), attributes: [attr('product id', 'PK FK'), attr('feature', 'PK'), attr('value')] },
|
|
124
|
+
{ id: 'condition', name: 'Condition', ...at(3, 3), attributes: [attr('condition code', 'PK'), attr('kind'), attr('rate'), attr('applies to', 'FK')] },
|
|
97
125
|
{ 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
126
|
{ 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
127
|
{ id: 'place', name: 'Place', ...at(4, 0), attributes: [attr('place id', 'PK'), attr('name'), attr('location'), attr('time zone')] },
|
|
@@ -120,6 +148,9 @@
|
|
|
120
148
|
{ source: 'event', target: 'ledger-entry', name: 'is recorded in', sourceCardinality: '1', targetCardinality: '1..*' },
|
|
121
149
|
{ source: 'account', target: 'ledger-entry', name: 'is posted with', sourceCardinality: '1', targetCardinality: '0..*', identifying: false },
|
|
122
150
|
{ source: 'scheme', target: 'code', name: 'holds', sourceCardinality: '1', targetCardinality: '1..*' },
|
|
151
|
+
{ source: 'agreement', target: 'arrangement', name: 'governs', sourceCardinality: '1', targetCardinality: '1..*' },
|
|
152
|
+
{ source: 'product', target: 'product-feature', name: 'has', sourceCardinality: '1', targetCardinality: '0..*' },
|
|
153
|
+
{ source: 'condition', target: 'product', name: 'applies to', sourceCardinality: '*', targetCardinality: '*', identifying: false },
|
|
123
154
|
{ source: 'product', target: 'arrangement', name: 'is sold as', sourceCardinality: '1', targetCardinality: '0..*', identifying: false },
|
|
124
155
|
{ source: 'product', target: 'product-price', name: 'is priced by', sourceCardinality: '1', targetCardinality: '1..*' },
|
|
125
156
|
{ source: 'product', target: 'product-component', name: 'is made of', sourceCardinality: '1', targetCardinality: '0..*' },
|
|
@@ -168,6 +199,15 @@
|
|
|
168
199
|
{ id: 'product_price', name: 'product_price', ...at(4, 1), attributes: [
|
|
169
200
|
attr('product_id', 'PK FK', 'BIGINT'), attr('valid_from', 'PK', 'DATE'), attr('amount', '', 'DECIMAL(12,2)'), attr('currency', '', 'CHAR(3)'),
|
|
170
201
|
] },
|
|
202
|
+
{ id: 'agreement', name: 'agreement', ...at(0, 3), attributes: [
|
|
203
|
+
attr('agreement_id', 'PK', 'BIGINT'), attr('party_id', 'FK', 'BIGINT'), attr('signed_on', '', 'DATE'), attr('terms', '', 'JSONB'),
|
|
204
|
+
] },
|
|
205
|
+
{ id: 'product_feature', name: 'product_feature', ...at(1, 3), attributes: [
|
|
206
|
+
attr('product_id', 'PK FK', 'BIGINT'), attr('feature', 'PK', 'VARCHAR(40)'), attr('value', '', 'TEXT'),
|
|
207
|
+
] },
|
|
208
|
+
{ id: 'condition', name: 'condition', ...at(2, 3), attributes: [
|
|
209
|
+
attr('condition_code', 'PK', 'VARCHAR(20)'), attr('kind', '', 'VARCHAR(12)'), attr('rate', '', 'DECIMAL(9,4)'), attr('product_id', 'FK', 'BIGINT'),
|
|
210
|
+
] },
|
|
171
211
|
{ id: 'business_direction', name: 'business_direction', ...at(0, 2), attributes: [
|
|
172
212
|
attr('direction_id', 'PK', 'BIGINT'), attr('kind', '', 'VARCHAR(20)'), attr('statement', '', 'TEXT'),
|
|
173
213
|
attr('parent_id', 'FK', 'BIGINT'), attr('horizon', '', 'DATE'),
|
|
@@ -196,6 +236,9 @@
|
|
|
196
236
|
{ source: 'product', target: 'arrangement', name: 'is sold as', sourceCardinality: '1', targetCardinality: '0..*', identifying: false },
|
|
197
237
|
{ source: 'product', target: 'product_price', name: 'is priced by', sourceCardinality: '1', targetCardinality: '1..*' },
|
|
198
238
|
{ source: 'business_direction', target: 'direction_target', name: 'is measured by', sourceCardinality: '1', targetCardinality: '0..*' },
|
|
239
|
+
{ source: 'agreement', target: 'arrangement', name: 'governs', sourceCardinality: '1', targetCardinality: '1..*' },
|
|
240
|
+
{ source: 'product', target: 'product_feature', name: 'has', sourceCardinality: '1', targetCardinality: '0..*' },
|
|
241
|
+
{ source: 'product', target: 'condition', name: 'is subject to', sourceCardinality: '1', targetCardinality: '0..*', identifying: false },
|
|
199
242
|
{ source: 'product', target: 'direction_target', name: 'is aimed at by', sourceCardinality: '0..1', targetCardinality: '0..*', identifying: false },
|
|
200
243
|
],
|
|
201
244
|
};
|
|
@@ -209,6 +252,7 @@
|
|
|
209
252
|
['ledger', 'account'], ['ledger', 'ledger-entry'], ['classification', 'scheme'], ['classification', 'code'],
|
|
210
253
|
['product', 'product'], ['product', 'product-price'], ['product', 'product-component'], ['resource', 'product-component'],
|
|
211
254
|
['direction', 'direction'], ['direction', 'target'],
|
|
255
|
+
['agreement', 'agreement'], ['feature', 'product-feature'], ['condition', 'condition'],
|
|
212
256
|
] },
|
|
213
257
|
{ from: 'logical', to: 'physical', pairs: [
|
|
214
258
|
['person', 'party'], ['organisation', 'party'], ['party-role', 'party_role'], ['participation', 'arrangement_party'],
|
|
@@ -217,6 +261,7 @@
|
|
|
217
261
|
['scheme', 'classification'], ['code', 'classification'],
|
|
218
262
|
['product', 'product'], ['product-component', 'product'], ['product-price', 'product_price'],
|
|
219
263
|
['direction', 'business_direction'], ['target', 'direction_target'],
|
|
264
|
+
['agreement', 'agreement'], ['product-feature', 'product_feature'], ['condition', 'condition'],
|
|
220
265
|
] },
|
|
221
266
|
];
|
|
222
267
|
|
|
@@ -224,13 +269,13 @@
|
|
|
224
269
|
const perspectives = [
|
|
225
270
|
{
|
|
226
271
|
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' },
|
|
272
|
+
entities: ['party', 'role', 'agreement', 'arrangement', 'product', 'resource', 'event', 'ledger'],
|
|
273
|
+
names: { party: 'Customer', role: 'Subscriber', agreement: 'Contract', arrangement: 'Subscription', product: 'Plan', resource: 'Device', event: 'Usage', ledger: 'Billing' },
|
|
229
274
|
relationshipNames: { covers: 'includes', records: 'is billed in' },
|
|
230
275
|
},
|
|
231
276
|
{
|
|
232
277
|
id: 'regulatory', name: 'Regulatory', context: 'regulatory', description: 'What a regulator holds us to',
|
|
233
|
-
entities: ['party', 'arrangement', 'event', 'ledger', 'rule', 'classification', 'place'],
|
|
278
|
+
entities: ['party', 'agreement', 'arrangement', 'event', 'ledger', 'rule', 'classification', 'place'],
|
|
234
279
|
names: { party: 'Legal Entity', arrangement: 'Compliance Obligation', event: 'Reportable Event', ledger: 'Audit Trail', rule: 'Regulation', place: 'Jurisdiction' },
|
|
235
280
|
relationshipNames: { imposes: 'imposes', records: 'is evidenced by' },
|
|
236
281
|
},
|
|
@@ -306,6 +351,160 @@
|
|
|
306
351
|
},
|
|
307
352
|
];
|
|
308
353
|
|
|
354
|
+
// A retail-banking slice at BIAN level: BIAN service domains (each a kind of perspective) over the
|
|
355
|
+
// concepts, each managing its control record, broken down by behaviour qualifiers, at the logical level.
|
|
356
|
+
// Illustrative: the service domains and patterns are BIAN's; the attributes are a sketch.
|
|
357
|
+
const grid = (column, row) => ({ x: 130 + column * 290, y: 100 + row * 230 });
|
|
358
|
+
const banking = {
|
|
359
|
+
name: 'Retail banking (BIAN)',
|
|
360
|
+
levels: {
|
|
361
|
+
conceptual: {
|
|
362
|
+
entities: [
|
|
363
|
+
{ id: 'party', name: 'Party', details: { bian: 'Party' }, ...grid(0, 0), shape: 'person', labelPosition: 'below', color: '#ede9fe', description: 'A person or organisation the bank deals with.' },
|
|
364
|
+
{ id: 'agreement', name: 'Agreement', details: { bian: 'Agreement' }, ...grid(1, 0), shape: 'contract-box', color: '#fef9c3', description: 'The contract a customer signs with the bank: the promises both parties agree on.' },
|
|
365
|
+
{ id: 'arrangement', name: 'Arrangement', details: { bian: 'Arrangement' }, ...grid(2, 0), color: '#fef3c7', description: 'The terms a product is provided on, under an agreement: an account, a loan.' },
|
|
366
|
+
{ id: 'product', name: 'Product', details: { bian: 'Product' }, ...grid(3, 0), shape: 'product-box', color: '#dcfce7', description: 'What the bank offers: a current account, a consumer loan.' },
|
|
367
|
+
{ id: 'condition', name: 'Condition', details: { bian: 'Condition' }, ...grid(3, 1), color: '#fee2e2', description: 'A fee, rate or eligibility rule a product or arrangement is subject to.' },
|
|
368
|
+
{ id: 'payment', name: 'Payment', ...grid(2, 1), shape: 'ellipse', color: '#dbeafe', description: 'Money moved from one account to another.' },
|
|
369
|
+
],
|
|
370
|
+
relationships: [
|
|
371
|
+
{ source: 'party', target: 'agreement', name: 'signs', sourceCardinality: '1..*', targetCardinality: '*' },
|
|
372
|
+
{ source: 'agreement', target: 'arrangement', name: 'governs', sourceCardinality: '1', targetCardinality: '1..*' },
|
|
373
|
+
{ source: 'arrangement', target: 'product', name: 'provides', sourceCardinality: '*', targetCardinality: '1', identifying: false },
|
|
374
|
+
{ source: 'product', target: 'condition', name: 'is subject to', sourceCardinality: '*', targetCardinality: '*', identifying: false },
|
|
375
|
+
{ source: 'arrangement', target: 'payment', name: 'makes', sourceCardinality: '1', targetCardinality: '0..*', identifying: false },
|
|
376
|
+
],
|
|
377
|
+
},
|
|
378
|
+
logical: {
|
|
379
|
+
entities: [
|
|
380
|
+
{ id: 'party-entry', name: 'Party Reference Data Directory Entry', ...grid(0, 0), attributes: [attr('party id', 'PK'), attr('legal name'), attr('kind')] },
|
|
381
|
+
{ id: 'party-reference', name: 'Reference', ...grid(0, 1), attributes: [attr('party id', 'PK FK'), attr('tax number'), attr('passport')] },
|
|
382
|
+
{ id: 'demographics', name: 'Demographics', ...grid(0, 2), attributes: [attr('party id', 'PK FK'), attr('born on'), attr('occupation')] },
|
|
383
|
+
{ id: 'customer-agreement', name: 'Customer Agreement', ...grid(1, 0), attributes: [attr('agreement id', 'PK'), attr('party id', 'FK'), attr('signed on'), attr('status')] },
|
|
384
|
+
{ id: 'agreement-term', name: 'Agreement Term', ...grid(1, 1), attributes: [attr('agreement id', 'PK FK'), attr('term', 'PK'), attr('value')] },
|
|
385
|
+
{ id: 'current-account', name: 'Current Account Facility', ...grid(2, 0), attributes: [attr('arrangement id', 'PK'), attr('agreement id', 'FK'), attr('product id', 'FK'), attr('account number', '', 'Account Identification'), attr('account type', '', 'Current Account Type'), attr('currency', '', 'Currency Code'), attr('balance', '', 'Amount'), attr('opened on')] },
|
|
386
|
+
{ id: 'interest', name: 'Interest', ...grid(2, 1), attributes: [attr('arrangement id', 'PK FK'), attr('rate'), attr('accrual basis')] },
|
|
387
|
+
{ id: 'account-payments', name: 'Payments', ...grid(2, 2), attributes: [attr('arrangement id', 'PK FK'), attr('mandate', 'PK'), attr('kind'), attr('amount', '', 'Amount')] },
|
|
388
|
+
{ id: 'service-fees', name: 'Service Fees', ...grid(2, 3), attributes: [attr('arrangement id', 'PK FK'), attr('fee code', 'PK'), attr('amount', '', 'Amount')] },
|
|
389
|
+
{ id: 'consumer-loan', name: 'Consumer Loan Facility', ...grid(3, 0), attributes: [attr('arrangement id', 'PK'), attr('agreement id', 'FK'), attr('product id', 'FK'), attr('principal', '', 'Amount'), attr('term months')] },
|
|
390
|
+
{ id: 'disbursement', name: 'Disbursement', ...grid(3, 1), attributes: [attr('arrangement id', 'PK FK'), attr('paid on', 'PK'), attr('amount', '', 'Amount')] },
|
|
391
|
+
{ id: 'repayment', name: 'Repayment', ...grid(3, 2), attributes: [attr('arrangement id', 'PK FK'), attr('due on', 'PK'), attr('amount', '', 'Amount'), attr('paid')] },
|
|
392
|
+
{ id: 'payment-order', name: 'Payment Order Procedure', ...grid(4, 0), attributes: [attr('payment id', 'PK'), attr('from arrangement', 'FK'), attr('to account', '', 'Account Identification'), attr('amount', '', 'Amount'), attr('status', '', 'Payment Status')] },
|
|
393
|
+
{ id: 'compliance-check', name: 'Compliance Check', ...grid(4, 1), attributes: [attr('payment id', 'PK FK'), attr('outcome'), attr('checked at')] },
|
|
394
|
+
{ id: 'transfer', name: 'Transfer', ...grid(4, 2), attributes: [attr('payment id', 'PK FK'), attr('scheme'), attr('settled at')] },
|
|
395
|
+
{ id: 'product-entry', name: 'Product Directory Entry', ...grid(5, 0), attributes: [attr('product id', 'PK'), attr('name'), attr('line')] },
|
|
396
|
+
{ id: 'product-feature', name: 'Features', ...grid(5, 1), attributes: [attr('product id', 'PK FK'), attr('feature', 'PK'), attr('value')] },
|
|
397
|
+
{ id: 'product-condition', name: 'Conditions', ...grid(5, 2), attributes: [attr('product id', 'PK FK'), attr('condition', 'PK'), attr('rule')] },
|
|
398
|
+
],
|
|
399
|
+
relationships: [
|
|
400
|
+
{ source: 'party-entry', target: 'party-reference', name: 'has', sourceCardinality: '1', targetCardinality: '0..1' },
|
|
401
|
+
{ source: 'party-entry', target: 'demographics', name: 'has', sourceCardinality: '1', targetCardinality: '0..1' },
|
|
402
|
+
{ source: 'party-entry', target: 'customer-agreement', name: 'signs', sourceCardinality: '1', targetCardinality: '0..*', identifying: false },
|
|
403
|
+
{ source: 'customer-agreement', target: 'agreement-term', name: 'has', sourceCardinality: '1', targetCardinality: '1..*' },
|
|
404
|
+
{ source: 'customer-agreement', target: 'current-account', name: 'governs', sourceCardinality: '1', targetCardinality: '0..*', identifying: false },
|
|
405
|
+
{ source: 'customer-agreement', target: 'consumer-loan', name: 'governs', sourceCardinality: '1', targetCardinality: '0..*', identifying: false },
|
|
406
|
+
{ source: 'current-account', target: 'interest', name: 'has', sourceCardinality: '1', targetCardinality: '0..1' },
|
|
407
|
+
{ source: 'current-account', target: 'account-payments', name: 'has', sourceCardinality: '1', targetCardinality: '0..*' },
|
|
408
|
+
{ source: 'current-account', target: 'service-fees', name: 'has', sourceCardinality: '1', targetCardinality: '0..*' },
|
|
409
|
+
{ source: 'consumer-loan', target: 'disbursement', name: 'has', sourceCardinality: '1', targetCardinality: '1..*' },
|
|
410
|
+
{ source: 'consumer-loan', target: 'repayment', name: 'has', sourceCardinality: '1', targetCardinality: '1..*' },
|
|
411
|
+
{ source: 'current-account', target: 'payment-order', name: 'pays by', sourceCardinality: '1', targetCardinality: '0..*', identifying: false },
|
|
412
|
+
{ source: 'payment-order', target: 'compliance-check', name: 'has', sourceCardinality: '1', targetCardinality: '0..1' },
|
|
413
|
+
{ source: 'payment-order', target: 'transfer', name: 'has', sourceCardinality: '1', targetCardinality: '0..1' },
|
|
414
|
+
{ source: 'product-entry', target: 'product-feature', name: 'has', sourceCardinality: '1', targetCardinality: '0..*' },
|
|
415
|
+
{ source: 'product-entry', target: 'product-condition', name: 'has', sourceCardinality: '1', targetCardinality: '0..*' },
|
|
416
|
+
{ source: 'product-entry', target: 'current-account', name: 'is provided as', sourceCardinality: '1', targetCardinality: '0..*', identifying: false },
|
|
417
|
+
{ source: 'product-entry', target: 'consumer-loan', name: 'is provided as', sourceCardinality: '1', targetCardinality: '0..*', identifying: false },
|
|
418
|
+
],
|
|
419
|
+
},
|
|
420
|
+
physical: {
|
|
421
|
+
entities: [
|
|
422
|
+
{ id: 'party', name: 'party', ...grid(0, 0), attributes: [attr('party_id', 'PK', 'BIGINT'), attr('legal_name', '', 'VARCHAR(200)'), attr('party_kind', '', 'CHAR(1)'), attr('tax_number', '', 'VARCHAR(20)'), attr('born_on', '', 'DATE'), attr('details', '', 'JSONB')] },
|
|
423
|
+
{ id: 'customer_agreement', name: 'customer_agreement', ...grid(1, 0), attributes: [attr('agreement_id', 'PK', 'BIGINT'), attr('party_id', 'FK', 'BIGINT'), attr('signed_on', '', 'DATE'), attr('status', '', 'VARCHAR(12)'), attr('terms', '', 'JSONB')] },
|
|
424
|
+
{ id: 'account', name: 'account', ...grid(2, 0), attributes: [attr('arrangement_id', 'PK', 'BIGINT'), attr('agreement_id', 'FK', 'BIGINT'), attr('product_id', 'FK', 'BIGINT'), attr('kind', '', 'CHAR(1)'), attr('balance', '', 'DECIMAL(18,2)'), attr('opened_on', '', 'DATE')] },
|
|
425
|
+
{ id: 'account_interest', name: 'account_interest', ...grid(2, 1), attributes: [attr('arrangement_id', 'PK FK', 'BIGINT'), attr('rate', '', 'DECIMAL(7,4)'), attr('basis', '', 'VARCHAR(10)')] },
|
|
426
|
+
{ id: 'account_mandate', name: 'account_mandate', ...grid(2, 2), attributes: [attr('arrangement_id', 'PK FK', 'BIGINT'), attr('mandate', 'PK', 'VARCHAR(30)'), attr('kind', '', 'VARCHAR(12)'), attr('amount', '', 'DECIMAL(18,2)')] },
|
|
427
|
+
{ id: 'account_fee', name: 'account_fee', ...grid(2, 3), attributes: [attr('arrangement_id', 'PK FK', 'BIGINT'), attr('fee_code', 'PK', 'VARCHAR(12)'), attr('amount', '', 'DECIMAL(12,2)')] },
|
|
428
|
+
{ id: 'loan_schedule', name: 'loan_schedule', ...grid(3, 1), attributes: [attr('arrangement_id', 'PK FK', 'BIGINT'), attr('due_on', 'PK', 'DATE'), attr('kind', '', 'CHAR(1)'), attr('amount', '', 'DECIMAL(18,2)'), attr('paid', '', 'BOOLEAN')] },
|
|
429
|
+
{ id: 'payment_order', name: 'payment_order', ...grid(4, 0), attributes: [attr('payment_id', 'PK', 'BIGINT'), attr('from_arrangement', 'FK', 'BIGINT'), attr('to_account', '', 'VARCHAR(34)'), attr('amount', '', 'DECIMAL(18,2)'), attr('status', '', 'VARCHAR(12)'), attr('steps', '', 'JSONB')] },
|
|
430
|
+
{ id: 'product', name: 'product', ...grid(5, 0), attributes: [attr('product_id', 'PK', 'BIGINT'), attr('name', '', 'VARCHAR(120)'), attr('line', '', 'VARCHAR(20)'), attr('features', '', 'JSONB'), attr('conditions', '', 'JSONB')] },
|
|
431
|
+
],
|
|
432
|
+
relationships: [
|
|
433
|
+
{ source: 'party', target: 'customer_agreement', name: 'signs', sourceCardinality: '1', targetCardinality: '0..*', identifying: false },
|
|
434
|
+
{ source: 'customer_agreement', target: 'account', name: 'governs', sourceCardinality: '1', targetCardinality: '0..*', identifying: false },
|
|
435
|
+
{ source: 'account', target: 'account_interest', name: 'has', sourceCardinality: '1', targetCardinality: '0..1' },
|
|
436
|
+
{ source: 'account', target: 'account_mandate', name: 'has', sourceCardinality: '1', targetCardinality: '0..*' },
|
|
437
|
+
{ source: 'account', target: 'account_fee', name: 'has', sourceCardinality: '1', targetCardinality: '0..*' },
|
|
438
|
+
{ source: 'account', target: 'loan_schedule', name: 'schedules', sourceCardinality: '1', targetCardinality: '0..*' },
|
|
439
|
+
{ source: 'account', target: 'payment_order', name: 'pays by', sourceCardinality: '1', targetCardinality: '0..*', identifying: false },
|
|
440
|
+
{ source: 'product', target: 'account', name: 'is provided as', sourceCardinality: '1', targetCardinality: '0..*', identifying: false },
|
|
441
|
+
],
|
|
442
|
+
},
|
|
443
|
+
},
|
|
444
|
+
// Many to one: both arrangements in one account table, a loan's schedule in one table,
|
|
445
|
+
// a party's reference data and demographics in its own row.
|
|
446
|
+
mappings: [
|
|
447
|
+
{ from: 'conceptual', to: 'logical', pairs: [
|
|
448
|
+
['party', 'party-entry'], ['party', 'party-reference'], ['party', 'demographics'],
|
|
449
|
+
['agreement', 'customer-agreement'], ['agreement', 'agreement-term'],
|
|
450
|
+
['arrangement', 'current-account'], ['arrangement', 'consumer-loan'], ['arrangement', 'interest'],
|
|
451
|
+
['arrangement', 'account-payments'], ['arrangement', 'disbursement'], ['arrangement', 'repayment'],
|
|
452
|
+
['condition', 'service-fees'], ['condition', 'product-condition'], ['condition', 'agreement-term'],
|
|
453
|
+
['payment', 'payment-order'], ['payment', 'compliance-check'], ['payment', 'transfer'], ['payment', 'account-payments'],
|
|
454
|
+
['product', 'product-entry'], ['product', 'product-feature'],
|
|
455
|
+
] },
|
|
456
|
+
{ from: 'logical', to: 'physical', pairs: [
|
|
457
|
+
['party-entry', 'party'], ['party-reference', 'party'], ['demographics', 'party'],
|
|
458
|
+
['customer-agreement', 'customer_agreement'], ['agreement-term', 'customer_agreement'],
|
|
459
|
+
['current-account', 'account'], ['consumer-loan', 'account'], ['interest', 'account_interest'],
|
|
460
|
+
['account-payments', 'account_mandate'], ['service-fees', 'account_fee'],
|
|
461
|
+
['disbursement', 'loan_schedule'], ['repayment', 'loan_schedule'],
|
|
462
|
+
['payment-order', 'payment_order'], ['compliance-check', 'payment_order'], ['transfer', 'payment_order'],
|
|
463
|
+
['product-entry', 'product'], ['product-feature', 'product'], ['product-condition', 'product'],
|
|
464
|
+
] },
|
|
465
|
+
],
|
|
466
|
+
/* Data types, as BIAN's semantic APIs have them (github.com/bian-official/public, Apache-2.0):
|
|
467
|
+
an enumeration's values with what each means, a structure's fields, the ISO 20022 type each is. */
|
|
468
|
+
dataTypes: [
|
|
469
|
+
{ kind: 'enumeration', id: 'current-account-type', name: 'Current Account Type', description: "BIAN's Currentaccounttypevalues (some of them).", values: [
|
|
470
|
+
{ name: 'PersonalCurrentAccount', description: 'For a person.' },
|
|
471
|
+
{ name: 'BusinessCurrentAccount', description: 'Supports business transactions, payroll, invoicing, often with higher transaction limits.' },
|
|
472
|
+
{ name: 'StudentCurrentAccount', description: 'Tailored for students, usually with no fees, free overdraft, and student-related perks.' },
|
|
473
|
+
{ name: 'JointCurrentAccount', description: 'Shared between two or more account holders with equal access.' },
|
|
474
|
+
{ name: 'ForeignCurrencyCurrentAccount', description: 'Maintains balances in foreign currencies for international needs.' },
|
|
475
|
+
{ name: 'BasicBankAccount', description: 'Minimal feature account, no overdraft, designed for financial inclusion.' },
|
|
476
|
+
] },
|
|
477
|
+
{ kind: 'enumeration', id: 'payment-status', name: 'Payment Status', values: ['Pending', 'Accepted', 'Rejected', 'Completed', 'Cancelled'] },
|
|
478
|
+
{ kind: 'structure', id: 'amount', name: 'Amount', description: 'An amount of money in a currency.', iso20022: 'ActiveCurrencyAndAmount', fields: [
|
|
479
|
+
{ name: 'value', type: 'Decimal' }, { name: 'currency', type: 'Currency Code' },
|
|
480
|
+
] },
|
|
481
|
+
{ id: 'currency-code', name: 'Currency Code', basedOn: 'Text', description: 'A currency, as ISO 4217 codes it.', iso20022: 'CurrencyCode' },
|
|
482
|
+
{ id: 'account-identification', name: 'Account Identification', basedOn: 'Text', description: 'An account number in any suitable form (an IBAN).', iso20022: 'AccountIdentification' },
|
|
483
|
+
],
|
|
484
|
+
perspectives: [
|
|
485
|
+
{ kind: 'service-domain', id: 'sd-current-account', name: 'Current Account', businessArea: 'Operations and Execution', businessDomain: 'Loans and Deposits',
|
|
486
|
+
asset: 'Current Account', pattern: 'Fulfill', entities: ['arrangement', 'product', 'condition'], controlRecord: 'current-account',
|
|
487
|
+
qualifiers: [{ name: 'Interest', entity: 'interest' }, { name: 'Payments', entity: 'account-payments' }, { name: 'Service Fees', entity: 'service-fees' }] },
|
|
488
|
+
{ kind: 'service-domain', id: 'sd-consumer-loan', name: 'Consumer Loan', businessArea: 'Operations and Execution', businessDomain: 'Loans and Deposits',
|
|
489
|
+
asset: 'Consumer Loan', pattern: 'Fulfill', entities: ['arrangement', 'product'], controlRecord: 'consumer-loan',
|
|
490
|
+
qualifiers: [{ name: 'Disbursement', entity: 'disbursement' }, { name: 'Repayment', entity: 'repayment' }] },
|
|
491
|
+
{ kind: 'service-domain', id: 'sd-customer-agreement', name: 'Customer Agreement', businessArea: 'Sales and Service', businessDomain: 'Customer Management',
|
|
492
|
+
asset: 'Customer', pattern: 'Agree Terms', entities: ['party', 'agreement'], controlRecord: 'customer-agreement',
|
|
493
|
+
qualifiers: [{ name: 'Terms', entity: 'agreement-term' }] },
|
|
494
|
+
{ kind: 'service-domain', id: 'sd-payment-order', name: 'Payment Order', businessArea: 'Operations and Execution', businessDomain: 'Payments',
|
|
495
|
+
asset: 'Payment Order', pattern: 'Process', entities: ['payment', 'arrangement'], controlRecord: 'payment-order',
|
|
496
|
+
qualifiers: [{ name: 'Compliance Check', entity: 'compliance-check' }, { name: 'Transfer', entity: 'transfer' }] },
|
|
497
|
+
{ kind: 'service-domain', id: 'sd-party-directory', name: 'Party Reference Data Directory', businessArea: 'Sales and Service', businessDomain: 'Customer Management',
|
|
498
|
+
asset: 'Party Reference Data', pattern: 'Catalog', entities: ['party'], controlRecord: 'party-entry',
|
|
499
|
+
qualifiers: [{ name: 'Reference', entity: 'party-reference' }, { name: 'Demographics', entity: 'demographics' }] },
|
|
500
|
+
{ kind: 'service-domain', id: 'sd-product-directory', name: 'Product Directory', businessArea: 'Reference Data', businessDomain: 'Product Management',
|
|
501
|
+
asset: 'Product', pattern: 'Catalog', entities: ['product', 'condition'], controlRecord: 'product-entry',
|
|
502
|
+
qualifiers: [{ name: 'Features', entity: 'product-feature' }, { name: 'Conditions', entity: 'product-condition' }] },
|
|
503
|
+
],
|
|
504
|
+
contexts: [],
|
|
505
|
+
level: 'logical', notation: 'crowsfoot',
|
|
506
|
+
};
|
|
507
|
+
|
|
309
508
|
const ws = document.body.appendChild(el({
|
|
310
509
|
tag: 'ws-workspace',
|
|
311
510
|
attrs: { label: 'Data Model', theme: 'light' },
|
|
@@ -313,11 +512,22 @@
|
|
|
313
512
|
}));
|
|
314
513
|
registerBuiltinParts(ws);
|
|
315
514
|
ws.registerPart(DataModelPart);
|
|
316
|
-
|
|
317
|
-
|
|
515
|
+
// Several data models open at once, a tab each (File > New model). keep: each is kept in this browser
|
|
516
|
+
// as it changes and reopens next time; File > This browser backs them up (to a folder chosen once,
|
|
517
|
+
// such as one OneDrive or Google Drive syncs). File > Save writes a .datamodel.json.
|
|
518
|
+
// The enterprise ontology is the base: kept as given, File > New > From base makes a model from a
|
|
519
|
+
// copy of it, and Tools > Compare with / Merge from offer it beside the other open models.
|
|
520
|
+
const ontology = {
|
|
521
|
+
name: 'Enterprise ontology',
|
|
318
522
|
levels: { conceptual, logical, physical }, mappings, perspectives, contexts, level: 'conceptual', notation: 'crowsfoot',
|
|
523
|
+
};
|
|
524
|
+
ws.addParts([{
|
|
525
|
+
id: 'models', type: 'models', editorType: 'data-model', keep: true,
|
|
526
|
+
newModel: { name: 'New data model', level: 'conceptual' },
|
|
527
|
+
bases: [ontology, banking],
|
|
528
|
+
models: [{ id: 'model', ...ontology }],
|
|
319
529
|
}]);
|
|
320
|
-
ws.registerPerspective('Data model', { type: 'part', partId: '
|
|
530
|
+
ws.registerPerspective('Data model', { type: 'part', partId: 'models' });
|
|
321
531
|
ws.activatePerspective('Data model');
|
|
322
532
|
</script>
|
|
323
533
|
</body>
|
package/package.json
CHANGED