@arcgis/coding-components 4.29.0-beta.47 → 4.29.0-beta.49
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/dist/arcgis-coding-components/arcgis-coding-components.esm.js +1 -1
- package/dist/arcgis-coding-components/assets/code-editor/arcade.worker.js +13 -13
- package/dist/arcgis-coding-components/index.esm.js +1 -1
- package/dist/arcgis-coding-components/{p-10a322ec.js → p-0d616249.js} +9 -9
- package/dist/arcgis-coding-components/p-2c0d6f15.js +2 -0
- package/dist/arcgis-coding-components/{p-71faf9a4.js → p-5802524a.js} +1 -1
- package/dist/arcgis-coding-components/{p-9eabda86.js → p-5ddccf04.js} +1 -1
- package/dist/arcgis-coding-components/p-7475f3a6.js +1 -0
- package/dist/arcgis-coding-components/{p-e6ede32d.js → p-7d8caba9.js} +1 -1
- package/dist/arcgis-coding-components/{p-f7d7d78d.js → p-9f6db08a.js} +1 -1
- package/dist/arcgis-coding-components/{p-e475e6cd.js → p-aefe77ce.js} +1 -1
- package/dist/arcgis-coding-components/p-ce2be55e.entry.js +1 -0
- package/dist/arcgis-coding-components/{p-ce586a8c.js → p-d425a387.js} +1 -1
- package/dist/arcgis-coding-components/{p-c084ada8.js → p-ff21f230.js} +1 -1
- package/dist/cjs/{arcade-defaults-8445d852.js → arcade-defaults-2d513b59.js} +1534 -1534
- package/dist/cjs/arcade-mode-6219f1b8.js +599 -0
- package/dist/cjs/arcgis-arcade-api_6.cjs.entry.js +1404 -1408
- package/dist/cjs/arcgis-coding-components.cjs.js +2 -2
- package/dist/cjs/{cssMode-e63287bb.js → cssMode-1ec48254.js} +2 -2
- package/dist/cjs/{html-c0d4db3b.js → html-0e1741fe.js} +2 -2
- package/dist/cjs/{htmlMode-fdc44d57.js → htmlMode-279d3c29.js} +2 -2
- package/dist/cjs/{index-6a382a34.js → index-ac186201.js} +67 -24
- package/dist/cjs/index.cjs.js +2 -2
- package/dist/cjs/{javascript-a419d064.js → javascript-04f1bce0.js} +3 -3
- package/dist/cjs/{jsonMode-73aee5d2.js → jsonMode-59322f7a.js} +2 -2
- package/dist/cjs/loader.cjs.js +1 -1
- package/dist/cjs/{tsMode-37d1b053.js → tsMode-17561f70.js} +2 -2
- package/dist/cjs/{typescript-53f9f36a.js → typescript-b7da8629.js} +2 -2
- package/dist/components/arcade-api.js +160 -160
- package/dist/components/arcade-contribution.js +60 -60
- package/dist/components/arcade-defaults.js +1240 -1240
- package/dist/components/arcade-mode.js +514 -513
- package/dist/components/arcade-results.js +426 -430
- package/dist/components/arcade-suggestions.js +130 -132
- package/dist/components/arcade-variables.js +157 -155
- package/dist/components/arcgis-arcade-api.d.ts +2 -2
- package/dist/components/arcgis-arcade-editor.d.ts +2 -2
- package/dist/components/arcgis-arcade-editor.js +391 -391
- package/dist/components/arcgis-arcade-results.d.ts +2 -2
- package/dist/components/arcgis-arcade-suggestions.d.ts +2 -2
- package/dist/components/arcgis-arcade-variables.d.ts +2 -2
- package/dist/components/arcgis-code-editor.d.ts +2 -2
- package/dist/components/code-editor.js +251 -251
- package/dist/components/fields.js +69 -69
- package/dist/components/functional-components.js +1 -1
- package/dist/components/index2.js +2 -2
- package/dist/components/markdown.js +28 -28
- package/dist/components/utilities.js +20 -20
- package/dist/esm/{arcade-defaults-d7893362.js → arcade-defaults-0bafa696.js} +1534 -1534
- package/dist/esm/arcade-mode-c17a1fa1.js +595 -0
- package/dist/esm/arcgis-arcade-api_6.entry.js +1404 -1408
- package/dist/esm/arcgis-coding-components.js +3 -3
- package/dist/esm/{cssMode-b1771f92.js → cssMode-3d18bd2b.js} +2 -2
- package/dist/esm/{html-af635d52.js → html-2bce5d77.js} +2 -2
- package/dist/esm/{htmlMode-3021c301.js → htmlMode-69d56956.js} +2 -2
- package/dist/esm/{index-fd6b2fd8.js → index-022fb97b.js} +67 -24
- package/dist/esm/index.js +2 -2
- package/dist/esm/{javascript-70589186.js → javascript-ded5c9d7.js} +3 -3
- package/dist/esm/{jsonMode-cb509b79.js → jsonMode-0bf84cb2.js} +2 -2
- package/dist/esm/loader.js +2 -2
- package/dist/esm/{tsMode-ed90c9aa.js → tsMode-15d4e936.js} +2 -2
- package/dist/esm/{typescript-db8a0b18.js → typescript-cc4d00f0.js} +2 -2
- package/dist/types/components/arcade-api/arcade-api.d.ts +40 -40
- package/dist/types/components/arcade-api/t9n-types.d.ts +6 -6
- package/dist/types/components/arcade-editor/arcade-editor.d.ts +127 -127
- package/dist/types/components/arcade-editor/t9n-types.d.ts +6 -6
- package/dist/types/components/arcade-results/arcade-results.d.ts +47 -47
- package/dist/types/components/arcade-results/t9n-types.d.ts +11 -11
- package/dist/types/components/arcade-suggestions/arcade-suggestions.d.ts +34 -34
- package/dist/types/components/arcade-suggestions/t9n-types.d.ts +4 -4
- package/dist/types/components/arcade-variables/arcade-variables.d.ts +41 -41
- package/dist/types/components/arcade-variables/t9n-types.d.ts +6 -6
- package/dist/types/components/code-editor/code-editor.d.ts +73 -73
- package/dist/types/stencil-public-runtime.d.ts +8 -0
- package/dist/types/utils/arcade-executor.d.ts +79 -79
- package/dist/types/utils/arcade-monaco/arcade-defaults.d.ts +66 -66
- package/dist/types/utils/arcade-monaco/arcade-language-features.d.ts +23 -23
- package/dist/types/utils/arcade-monaco/arcade-mode.d.ts +9 -9
- package/dist/types/utils/arcade-monaco/arcade-theme.d.ts +7 -7
- package/dist/types/utils/arcade-monaco/arcade-worker-manager.d.ts +9 -9
- package/dist/types/utils/arcade-monaco/arcade.worker.d.ts +12 -12
- package/dist/types/utils/arcade-monaco/types.d.ts +29 -29
- package/dist/types/utils/editor-suggestions.d.ts +24 -24
- package/dist/types/utils/functional-components.d.ts +1 -1
- package/dist/types/utils/markdown.d.ts +1 -1
- package/dist/types/utils/profile/editor-profile.d.ts +185 -185
- package/dist/types/utils/profile/types.d.ts +101 -101
- package/dist/types/utils/utilities.d.ts +1 -1
- package/package.json +7 -7
- package/dist/arcgis-coding-components/p-5d670bd2.js +0 -2
- package/dist/arcgis-coding-components/p-9e242e76.js +0 -1
- package/dist/arcgis-coding-components/p-ccdf0ac1.entry.js +0 -1
- package/dist/cjs/arcade-mode-b77afcc9.js +0 -598
- package/dist/esm/arcade-mode-70e22d22.js +0 -594
|
@@ -6,398 +6,398 @@ import { D, G, q, H, x, N } from './index2.js';
|
|
|
6
6
|
import { getAssetPath } from '@stencil/core/internal/client';
|
|
7
7
|
|
|
8
8
|
async function newPortalItem(definition) {
|
|
9
|
-
|
|
10
|
-
|
|
9
|
+
const PortalItem = await importPortalPortalItem();
|
|
10
|
+
return new PortalItem(definition);
|
|
11
11
|
}
|
|
12
12
|
async function newFeatureLayer(definition) {
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
13
|
+
const FeatureLayer = await importLayersFeatureLayer();
|
|
14
|
+
// Fix title for the layer. Instead of defaulting to the map viewer style.
|
|
15
|
+
return new FeatureLayer({ ...definition, sublayerTitleMode: "service-name" });
|
|
16
16
|
}
|
|
17
17
|
async function newWebMap(definition) {
|
|
18
|
-
|
|
19
|
-
|
|
18
|
+
const WebMap = await importWebMap();
|
|
19
|
+
return new WebMap(definition);
|
|
20
20
|
}
|
|
21
21
|
function isSupportedLayerInstance(item) {
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
22
|
+
return (!!item &&
|
|
23
|
+
typeof item === "object" &&
|
|
24
|
+
typeof item.declaredClass === "string" &&
|
|
25
|
+
item.declaredClass.startsWith("esri.layers."));
|
|
26
26
|
}
|
|
27
27
|
function isFeatureSetInstance(item) {
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
28
|
+
return (!!item &&
|
|
29
|
+
typeof item === "object" &&
|
|
30
|
+
typeof item.declaredClass === "string" &&
|
|
31
|
+
item.declaredClass === "esri.rest.support.FeatureSet");
|
|
32
32
|
}
|
|
33
33
|
function isFeatureLayerInstance(item) {
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
34
|
+
return (!!item &&
|
|
35
|
+
typeof item === "object" &&
|
|
36
|
+
typeof item.declaredClass === "string" &&
|
|
37
|
+
item.declaredClass === "esri.layers.FeatureLayer");
|
|
38
38
|
}
|
|
39
39
|
function isGroupLayerInstance(item) {
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
40
|
+
return (!!item &&
|
|
41
|
+
typeof item === "object" &&
|
|
42
|
+
typeof item.declaredClass === "string" &&
|
|
43
|
+
item.declaredClass === "esri.layers.GroupLayer");
|
|
44
44
|
}
|
|
45
45
|
function isWebMapInstance(item) {
|
|
46
|
-
|
|
46
|
+
return (!!item && typeof item === "object" && typeof item.declaredClass === "string" && item.declaredClass === "esri.WebMap");
|
|
47
47
|
}
|
|
48
48
|
function isPortalItemDefinition(item) {
|
|
49
|
-
|
|
49
|
+
return !!item && typeof item === "object" && item.portalItem != null;
|
|
50
50
|
}
|
|
51
51
|
function isFeatureLayerItemDefinition(item) {
|
|
52
|
-
|
|
52
|
+
return !!item && typeof item === "object" && item.portalItem != null;
|
|
53
53
|
}
|
|
54
54
|
function isFieldsDefinition(item) {
|
|
55
|
-
|
|
55
|
+
return !!item && typeof item === "object" && Array.isArray(item.fields) && !("declaredClass" in item);
|
|
56
56
|
}
|
|
57
57
|
function isUrlDefinition(item) {
|
|
58
|
-
|
|
58
|
+
return !!item && typeof item === "object" && typeof item.url === "string" && !("declaredClass" in item);
|
|
59
59
|
}
|
|
60
60
|
function isPredefinedProfile(item) {
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
61
|
+
return (!!item &&
|
|
62
|
+
typeof item === "object" &&
|
|
63
|
+
typeof item.id === "string" &&
|
|
64
|
+
typeof item.definitions === "object" &&
|
|
65
|
+
!Array.isArray(item.definitions));
|
|
66
66
|
}
|
|
67
67
|
|
|
68
68
|
function resolveIntlPath(dictionary, path) {
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
69
|
+
if (!dictionary) {
|
|
70
|
+
return "";
|
|
71
|
+
}
|
|
72
|
+
const pathSegments = path.split(".");
|
|
73
|
+
let pathSegment = pathSegments.shift();
|
|
74
|
+
let entry = dictionary;
|
|
75
|
+
while (entry && pathSegment) {
|
|
76
|
+
// @ts-expect-error
|
|
77
|
+
entry = entry[pathSegment];
|
|
78
|
+
pathSegment = pathSegments.shift();
|
|
79
|
+
}
|
|
80
|
+
return typeof entry === "string" ? entry : path;
|
|
81
81
|
}
|
|
82
82
|
function isTypesCapabaleLayer(item) {
|
|
83
|
-
|
|
83
|
+
return !!item?.typeIdField;
|
|
84
84
|
}
|
|
85
85
|
function isDomainsCapableLayer(item) {
|
|
86
|
-
|
|
86
|
+
return typeof item?.getFieldDomain === "function";
|
|
87
87
|
}
|
|
88
88
|
function isRelationshipsCapableLayer(item) {
|
|
89
|
-
|
|
89
|
+
return Array.isArray(item?.relationships) && typeof item?.url === "string";
|
|
90
90
|
}
|
|
91
91
|
function isTableCapableLayer(item) {
|
|
92
|
-
|
|
92
|
+
return typeof item?.isTable === "boolean";
|
|
93
93
|
}
|
|
94
94
|
function isLoadableSource(item) {
|
|
95
|
-
|
|
95
|
+
return typeof item?.load === "function";
|
|
96
96
|
}
|
|
97
97
|
//#endregion
|
|
98
98
|
//#region Support Functions
|
|
99
99
|
async function getRelatedFeatureLayer(layer, relationship) {
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
100
|
+
if (!relationship) {
|
|
101
|
+
return null;
|
|
102
|
+
}
|
|
103
|
+
const url = `${layer.url}/${relationship.relatedTableId}`;
|
|
104
|
+
const relatedFeatureLayer = await supportedSourceFromDefinition({ url });
|
|
105
|
+
if (!isFeatureLayerInstance(relatedFeatureLayer)) {
|
|
106
|
+
return null;
|
|
107
|
+
}
|
|
108
|
+
return relatedFeatureLayer;
|
|
109
109
|
}
|
|
110
110
|
function sortFields(layer) {
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
111
|
+
return (firstField, secondField) => {
|
|
112
|
+
if (firstField.type === "oid") {
|
|
113
|
+
return -1;
|
|
114
|
+
}
|
|
115
|
+
if (secondField.type === "oid") {
|
|
116
|
+
return 1;
|
|
117
|
+
}
|
|
118
|
+
if (isTypesCapabaleLayer(layer)) {
|
|
119
|
+
if (firstField.name === layer.typeIdField) {
|
|
120
|
+
return -1;
|
|
121
|
+
}
|
|
122
|
+
if (secondField.name === layer.typeIdField) {
|
|
123
|
+
return 1;
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
return firstField.name.localeCompare(secondField.name, "en", { sensitivity: "base" });
|
|
127
|
+
};
|
|
128
128
|
}
|
|
129
129
|
function getSubtypesProperties(profile, types, field) {
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
130
|
+
// Try the coded domain first
|
|
131
|
+
const group = getDomainValuesProperties(profile, field.domain, { code: "subtypes" });
|
|
132
|
+
if (group) {
|
|
133
|
+
return group;
|
|
134
|
+
}
|
|
135
|
+
// No coded domain for the subtypes, we will manufacture it
|
|
136
|
+
const values = types.map((t) => new ValueVariable({ profile, label: `${t.id}`, description: t.name, snippet: `"${t.id}"` }));
|
|
137
|
+
return new GroupOfVariables(profile, { code: "subtypes" }, values);
|
|
138
138
|
}
|
|
139
139
|
function getDomainValuesProperties(profile, domain, label) {
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
140
|
+
if (!domain || domain.type !== "coded-value") {
|
|
141
|
+
return null;
|
|
142
|
+
}
|
|
143
|
+
const values = domain.codedValues.map((v) => new ValueVariable({
|
|
144
|
+
profile,
|
|
145
|
+
label: `${v.code}`,
|
|
146
|
+
description: v.name,
|
|
147
|
+
snippet: `"${v.code}"`,
|
|
148
|
+
filterDescription: true
|
|
149
|
+
}));
|
|
150
|
+
return new GroupOfVariables(profile, label, values);
|
|
151
151
|
}
|
|
152
152
|
function getDomainValuesBySubtypeGroup(profile, types, field) {
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
153
|
+
const variables = [];
|
|
154
|
+
types.forEach((t) => {
|
|
155
|
+
let domain = t.domains?.[field.name];
|
|
156
|
+
if (!domain) {
|
|
157
|
+
return;
|
|
158
|
+
}
|
|
159
|
+
if (domain.type === "inherited") {
|
|
160
|
+
domain = field.domain;
|
|
161
|
+
return;
|
|
162
|
+
}
|
|
163
|
+
const domainValuesGroup = getDomainValuesProperties(profile, domain, {
|
|
164
|
+
code: "domainvaluesfortypeformat",
|
|
165
|
+
formatValues: {
|
|
166
|
+
fieldName: field.alias ?? field.name,
|
|
167
|
+
typeName: t.name
|
|
168
|
+
}
|
|
169
|
+
});
|
|
170
|
+
if (!domainValuesGroup) {
|
|
171
|
+
return;
|
|
172
|
+
}
|
|
173
|
+
const label = `${t.id}`;
|
|
174
|
+
const snippet = `"${t.id}""`;
|
|
175
|
+
const subtypeDictionary = new DictionaryVariable({ profile, label, snippet });
|
|
176
|
+
subtypeDictionary.variables = [domainValuesGroup];
|
|
177
|
+
variables.push(subtypeDictionary);
|
|
169
178
|
});
|
|
170
|
-
if (!
|
|
171
|
-
|
|
172
|
-
}
|
|
173
|
-
|
|
174
|
-
const snippet = `"${t.id}""`;
|
|
175
|
-
const subtypeDictionary = new DictionaryVariable({ profile, label, snippet });
|
|
176
|
-
subtypeDictionary.variables = [domainValuesGroup];
|
|
177
|
-
variables.push(subtypeDictionary);
|
|
178
|
-
});
|
|
179
|
-
if (!variables.length) {
|
|
180
|
-
return null;
|
|
181
|
-
}
|
|
182
|
-
return new GroupOfVariables(profile, { code: "domainvaluesbysubtypes" }, variables);
|
|
179
|
+
if (!variables.length) {
|
|
180
|
+
return null;
|
|
181
|
+
}
|
|
182
|
+
return new GroupOfVariables(profile, { code: "domainvaluesbysubtypes" }, variables);
|
|
183
183
|
}
|
|
184
184
|
// const validIdentifierExpr = new RegExp(/^[a-z_$][\w$]*$/gi);
|
|
185
|
-
const validIdentifierExpr =
|
|
185
|
+
const validIdentifierExpr = /^[a-z_$][a-z0-9_$]*$/giu;
|
|
186
186
|
function getMemberExpressionProperty(prop, includeDot = true) {
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
187
|
+
if (prop.match(validIdentifierExpr)) {
|
|
188
|
+
return `${includeDot ? "." : ""}${prop}`;
|
|
189
|
+
}
|
|
190
|
+
return `["${prop}"]`;
|
|
191
191
|
}
|
|
192
192
|
function assembleMemberExpression(obj, prop) {
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
193
|
+
if (!obj) {
|
|
194
|
+
return prop;
|
|
195
|
+
}
|
|
196
|
+
return `${obj}${getMemberExpressionProperty(prop)}`;
|
|
197
197
|
}
|
|
198
198
|
//#endregion
|
|
199
199
|
//#region Sources
|
|
200
200
|
async function supportedSourceFromDefinition(definition) {
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
201
|
+
if (!definition) {
|
|
202
|
+
return null;
|
|
203
|
+
}
|
|
204
|
+
let source = null;
|
|
205
|
+
if (isSupportedLayerInstance(definition) || isFeatureSetInstance(definition) || isFieldsDefinition(definition)) {
|
|
206
|
+
source = definition;
|
|
207
|
+
}
|
|
208
|
+
else {
|
|
209
|
+
source = await newFeatureLayer(definition);
|
|
210
|
+
if (!isFeatureLayerInstance(source)) {
|
|
211
|
+
console.error("Invalid FeatureSetDefinition", definition);
|
|
212
|
+
return null;
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
if (!source) {
|
|
216
|
+
console.error("Invalid FeatureSetDefinition", definition);
|
|
217
|
+
return null;
|
|
218
|
+
}
|
|
219
|
+
if (isLoadableSource(source)) {
|
|
220
|
+
await source.load();
|
|
221
|
+
}
|
|
222
|
+
return source;
|
|
223
223
|
}
|
|
224
224
|
async function serviceMetaData(url) {
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
225
|
+
url += "/layers";
|
|
226
|
+
const request = await importRequest();
|
|
227
|
+
const response = await request(url, { responseType: "json", query: { f: "json" } });
|
|
228
|
+
const data = {
|
|
229
|
+
layers: response.data?.layers ?? [],
|
|
230
|
+
tables: response.data?.tables ?? []
|
|
231
|
+
};
|
|
232
|
+
const queryCapability = url.endsWith("MapServer/layers") ? "data" : "query";
|
|
233
|
+
const layers = filterFeatureLayerInfos(data.layers, queryCapability);
|
|
234
|
+
const tables = filterFeatureLayerInfos(data.tables, queryCapability);
|
|
235
|
+
return { layers, tables };
|
|
236
236
|
}
|
|
237
237
|
function filterFeatureLayerInfos(layers, queryCapability) {
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
238
|
+
return layers.filter((layer) => {
|
|
239
|
+
if (layer.type !== "Feature Layer" && layer.type !== "Table") {
|
|
240
|
+
return false;
|
|
241
|
+
}
|
|
242
|
+
const capabilities = layer.capabilities
|
|
243
|
+
? layer.capabilities
|
|
244
|
+
.toLowerCase()
|
|
245
|
+
.split(",")
|
|
246
|
+
.map((value) => value.trim())
|
|
247
|
+
: [];
|
|
248
|
+
return capabilities.includes(queryCapability);
|
|
249
|
+
});
|
|
250
250
|
}
|
|
251
251
|
//#endregion
|
|
252
252
|
//#region Functions to Editor Variables to a language service variables
|
|
253
253
|
async function variablesToLSVariable(editorVariables, kind = CompletionItemKind.Variable) {
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
254
|
+
if (!editorVariables) {
|
|
255
|
+
return [];
|
|
256
|
+
}
|
|
257
|
+
const properties = await Promise.all(editorVariables.map(async (editorVariable) => {
|
|
258
|
+
switch (editorVariable.type) {
|
|
259
|
+
case "dictionary":
|
|
260
|
+
return dictionaryToLSDictionary(editorVariable, kind);
|
|
261
|
+
case "feature":
|
|
262
|
+
return featureToLSFeature(editorVariable, kind);
|
|
263
|
+
default:
|
|
264
|
+
return variableToLSVariable(editorVariable, kind);
|
|
265
|
+
}
|
|
266
|
+
}));
|
|
267
|
+
return properties.filter((p) => p);
|
|
268
268
|
}
|
|
269
269
|
function variableToLSVariable(editorVariable, kind) {
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
270
|
+
const { name, type } = editorVariable;
|
|
271
|
+
const description = editorVariable.getDescription();
|
|
272
|
+
return {
|
|
273
|
+
name,
|
|
274
|
+
description,
|
|
275
|
+
type,
|
|
276
|
+
completion: {
|
|
277
|
+
label: name,
|
|
278
|
+
detail: name,
|
|
279
|
+
insertText: name,
|
|
280
|
+
insertTextMode: InsertTextMode.asIs,
|
|
281
|
+
insertTextFormat: InsertTextFormat.PlainText,
|
|
282
|
+
kind,
|
|
283
|
+
documentation: { kind: "markdown", value: description }
|
|
284
|
+
}
|
|
285
|
+
};
|
|
286
286
|
}
|
|
287
287
|
async function featureToLSFeature(editorFeature, kind) {
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
insertTextMode: InsertTextMode.asIs,
|
|
297
|
-
insertTextFormat: InsertTextFormat.PlainText,
|
|
298
|
-
kind
|
|
299
|
-
};
|
|
300
|
-
const result = {
|
|
301
|
-
name,
|
|
302
|
-
description,
|
|
303
|
-
type: "dictionary",
|
|
304
|
-
properties: [],
|
|
305
|
-
completion: resultCompletion
|
|
306
|
-
};
|
|
307
|
-
// No source definition, then it will be a feature without any known fields
|
|
308
|
-
if (!source) {
|
|
309
|
-
return result;
|
|
310
|
-
}
|
|
311
|
-
// Create properties for the fields and the aliases
|
|
312
|
-
// Also improve the feature completion documentation
|
|
313
|
-
let featureCompletionDescription = description;
|
|
314
|
-
const fieldProfileValues = [];
|
|
315
|
-
const aliasProfileValues = [];
|
|
316
|
-
supportedFields(source.fields).forEach((field) => {
|
|
317
|
-
let fieldCompletionDescription = `**${field.name}** \n${field.type}`;
|
|
318
|
-
if (field.description) {
|
|
319
|
-
fieldCompletionDescription += ` \n'${field.description}`;
|
|
320
|
-
}
|
|
321
|
-
if (featureCompletionDescription) {
|
|
322
|
-
featureCompletionDescription += " \n \n";
|
|
323
|
-
}
|
|
324
|
-
featureCompletionDescription += `**${field.name}** (${field.alias ?? field.name}) \n${field.type}`;
|
|
325
|
-
if (field.description) {
|
|
326
|
-
featureCompletionDescription += ` \n'${field.description}`;
|
|
327
|
-
}
|
|
328
|
-
// The property for the field
|
|
329
|
-
const type = fieldTypeToArcadeType(field);
|
|
330
|
-
const insertText = getMemberExpressionProperty(field.name, false);
|
|
331
|
-
fieldProfileValues.push({
|
|
332
|
-
name: field.name,
|
|
333
|
-
description: field.alias || field.name,
|
|
334
|
-
type,
|
|
335
|
-
completion: {
|
|
336
|
-
label: field.name,
|
|
337
|
-
detail: field.alias || field.name,
|
|
338
|
-
insertText,
|
|
339
|
-
insertTextMode: InsertTextMode.asIs,
|
|
340
|
-
insertTextFormat: InsertTextFormat.PlainText,
|
|
341
|
-
kind: CompletionItemKind.Field,
|
|
342
|
-
documentation: { kind: "markdown", value: fieldCompletionDescription }
|
|
343
|
-
}
|
|
344
|
-
});
|
|
345
|
-
if (!field.alias || field.alias.toLowerCase() === field.name.toLowerCase()) {
|
|
346
|
-
return;
|
|
347
|
-
}
|
|
348
|
-
// The property for the alias if different than the field name
|
|
349
|
-
let aliasCompletionDescription = `**${field.alias}** \n${field.type}`;
|
|
350
|
-
if (field.description) {
|
|
351
|
-
aliasCompletionDescription += ` \n'${field.description}`;
|
|
352
|
-
}
|
|
353
|
-
aliasProfileValues.push({
|
|
354
|
-
name: field.alias,
|
|
355
|
-
description: field.name,
|
|
356
|
-
type,
|
|
357
|
-
completion: {
|
|
358
|
-
label: field.alias,
|
|
359
|
-
detail: field.name,
|
|
360
|
-
insertText,
|
|
288
|
+
// Get the source for the definition
|
|
289
|
+
const source = await editorFeature.loadSource();
|
|
290
|
+
const { name } = editorFeature;
|
|
291
|
+
const description = editorFeature.getDescription();
|
|
292
|
+
const resultCompletion = {
|
|
293
|
+
label: name,
|
|
294
|
+
detail: name,
|
|
295
|
+
insertText: name,
|
|
361
296
|
insertTextMode: InsertTextMode.asIs,
|
|
362
297
|
insertTextFormat: InsertTextFormat.PlainText,
|
|
363
|
-
kind
|
|
364
|
-
|
|
365
|
-
|
|
298
|
+
kind
|
|
299
|
+
};
|
|
300
|
+
const result = {
|
|
301
|
+
name,
|
|
302
|
+
description,
|
|
303
|
+
type: "dictionary",
|
|
304
|
+
properties: [],
|
|
305
|
+
completion: resultCompletion
|
|
306
|
+
};
|
|
307
|
+
// No source definition, then it will be a feature without any known fields
|
|
308
|
+
if (!source) {
|
|
309
|
+
return result;
|
|
310
|
+
}
|
|
311
|
+
// Create properties for the fields and the aliases
|
|
312
|
+
// Also improve the feature completion documentation
|
|
313
|
+
let featureCompletionDescription = description;
|
|
314
|
+
const fieldProfileValues = [];
|
|
315
|
+
const aliasProfileValues = [];
|
|
316
|
+
supportedFields(source.fields).forEach((field) => {
|
|
317
|
+
let fieldCompletionDescription = `**${field.name}** \n${field.type}`;
|
|
318
|
+
if (field.description) {
|
|
319
|
+
fieldCompletionDescription += ` \n'${field.description}`;
|
|
320
|
+
}
|
|
321
|
+
if (featureCompletionDescription) {
|
|
322
|
+
featureCompletionDescription += " \n \n";
|
|
323
|
+
}
|
|
324
|
+
featureCompletionDescription += `**${field.name}** (${field.alias ?? field.name}) \n${field.type}`;
|
|
325
|
+
if (field.description) {
|
|
326
|
+
featureCompletionDescription += ` \n'${field.description}`;
|
|
327
|
+
}
|
|
328
|
+
// The property for the field
|
|
329
|
+
const type = fieldTypeToArcadeType(field);
|
|
330
|
+
const insertText = getMemberExpressionProperty(field.name, false);
|
|
331
|
+
fieldProfileValues.push({
|
|
332
|
+
name: field.name,
|
|
333
|
+
description: field.alias || field.name,
|
|
334
|
+
type,
|
|
335
|
+
completion: {
|
|
336
|
+
label: field.name,
|
|
337
|
+
detail: field.alias || field.name,
|
|
338
|
+
insertText,
|
|
339
|
+
insertTextMode: InsertTextMode.asIs,
|
|
340
|
+
insertTextFormat: InsertTextFormat.PlainText,
|
|
341
|
+
kind: CompletionItemKind.Field,
|
|
342
|
+
documentation: { kind: "markdown", value: fieldCompletionDescription }
|
|
343
|
+
}
|
|
344
|
+
});
|
|
345
|
+
if (!field.alias || field.alias.toLowerCase() === field.name.toLowerCase()) {
|
|
346
|
+
return;
|
|
347
|
+
}
|
|
348
|
+
// The property for the alias if different than the field name
|
|
349
|
+
let aliasCompletionDescription = `**${field.alias}** \n${field.type}`;
|
|
350
|
+
if (field.description) {
|
|
351
|
+
aliasCompletionDescription += ` \n'${field.description}`;
|
|
352
|
+
}
|
|
353
|
+
aliasProfileValues.push({
|
|
354
|
+
name: field.alias,
|
|
355
|
+
description: field.name,
|
|
356
|
+
type,
|
|
357
|
+
completion: {
|
|
358
|
+
label: field.alias,
|
|
359
|
+
detail: field.name,
|
|
360
|
+
insertText,
|
|
361
|
+
insertTextMode: InsertTextMode.asIs,
|
|
362
|
+
insertTextFormat: InsertTextFormat.PlainText,
|
|
363
|
+
kind: CompletionItemKind.Field,
|
|
364
|
+
documentation: { kind: "markdown", value: aliasCompletionDescription }
|
|
365
|
+
}
|
|
366
|
+
});
|
|
366
367
|
});
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
return result;
|
|
368
|
+
result.properties = [...fieldProfileValues, ...aliasProfileValues];
|
|
369
|
+
resultCompletion.documentation = { kind: "markdown", value: featureCompletionDescription };
|
|
370
|
+
return result;
|
|
371
371
|
}
|
|
372
372
|
async function dictionaryToLSDictionary(editorDictionary, kind) {
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
373
|
+
const { name, dictionaryVariables: variables } = editorDictionary;
|
|
374
|
+
const description = editorDictionary.getDescription();
|
|
375
|
+
const completionDescription = variables.reduce((previous, p) => {
|
|
376
|
+
if (previous !== "") {
|
|
377
|
+
previous += " \n \n";
|
|
378
|
+
}
|
|
379
|
+
previous += `**${p.name}** \n${p.type}`;
|
|
380
|
+
const description = p.getDescription();
|
|
381
|
+
if (description) {
|
|
382
|
+
previous += ` \n${description}`;
|
|
383
|
+
}
|
|
384
|
+
return previous;
|
|
385
|
+
}, description ?? "");
|
|
386
|
+
return {
|
|
387
|
+
name,
|
|
388
|
+
description,
|
|
389
|
+
type: "dictionary",
|
|
390
|
+
properties: await variablesToLSVariable(variables, CompletionItemKind.Field),
|
|
391
|
+
completion: {
|
|
392
|
+
label: name,
|
|
393
|
+
detail: name,
|
|
394
|
+
insertText: name,
|
|
395
|
+
insertTextMode: InsertTextMode.asIs,
|
|
396
|
+
insertTextFormat: InsertTextFormat.PlainText,
|
|
397
|
+
kind,
|
|
398
|
+
documentation: { kind: "markdown", value: completionDescription }
|
|
399
|
+
}
|
|
400
|
+
};
|
|
401
401
|
}
|
|
402
402
|
/**
|
|
403
403
|
* Represents a item in the EditorProfile. The profile is converted into an optimized way for
|
|
@@ -405,107 +405,107 @@ async function dictionaryToLSDictionary(editorDictionary, kind) {
|
|
|
405
405
|
* structures are created such as groups.
|
|
406
406
|
*/
|
|
407
407
|
class ProfileItemBase {
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
408
|
+
constructor(_profile, _label, description) {
|
|
409
|
+
this._profile = _profile;
|
|
410
|
+
this._label = _label;
|
|
411
|
+
this.description = description;
|
|
412
|
+
this.filterDescription = false;
|
|
413
|
+
}
|
|
414
|
+
/**
|
|
415
|
+
* Returns the label string.
|
|
416
|
+
*/
|
|
417
|
+
getLabel() {
|
|
418
|
+
if (this._label == null) {
|
|
419
|
+
return "";
|
|
420
|
+
}
|
|
421
|
+
if (typeof this._label === "string") {
|
|
422
|
+
// Some of our variables can start with a $ sign.
|
|
423
|
+
// If the component is under RTL, the string is messed up.
|
|
424
|
+
// It is converted from $feature to feature$, This is not acceptable since the label
|
|
425
|
+
// represents a variable name. We are adding in front of the $ sign a right to left mark.
|
|
426
|
+
return q(this._label);
|
|
427
|
+
}
|
|
428
|
+
return H(this._profile?.intlStrings?.[this._label.code], this._label.formatValues);
|
|
429
|
+
}
|
|
430
|
+
/**
|
|
431
|
+
* Returns the description string.
|
|
432
|
+
*/
|
|
433
|
+
getDescription() {
|
|
434
|
+
if (this.description == null) {
|
|
435
|
+
return "";
|
|
436
|
+
}
|
|
437
|
+
if (typeof this.description === "string") {
|
|
438
|
+
return this.description;
|
|
439
|
+
}
|
|
440
|
+
return H(this._profile?.intlStrings?.[this.description.code ?? ""], this.description.formatValues);
|
|
441
|
+
}
|
|
442
|
+
/**
|
|
443
|
+
* Returns true if the item pass the filter test
|
|
444
|
+
*/
|
|
445
|
+
passFilter(filterExpression) {
|
|
446
|
+
if (!filterExpression) {
|
|
447
|
+
return true;
|
|
448
|
+
}
|
|
449
|
+
if (filterExpression.test(this.getLabel())) {
|
|
450
|
+
return true;
|
|
451
|
+
}
|
|
452
|
+
return this.filterDescription && filterExpression.test(this.getDescription());
|
|
453
|
+
}
|
|
454
454
|
}
|
|
455
455
|
/**
|
|
456
456
|
* The base class for profile variables representation in the EditorProfile.
|
|
457
457
|
*/
|
|
458
458
|
class VariableBase extends ProfileItemBase {
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
459
|
+
constructor(props) {
|
|
460
|
+
super(props.profile, props.label, props.description ?? props.declaration?.description);
|
|
461
|
+
this.declaration = props.declaration ?? {};
|
|
462
|
+
this.name = props.declaration?.name ?? "";
|
|
463
|
+
this.snippet = props.snippet || "";
|
|
464
|
+
this.nonInteractive = props.nonInteractive ?? false;
|
|
465
|
+
this.filterDescription = props.filterDescription ?? false;
|
|
466
|
+
this.icon = props.icon;
|
|
467
|
+
}
|
|
468
468
|
}
|
|
469
469
|
/**
|
|
470
470
|
* Represents the IProfileValue.
|
|
471
471
|
*/
|
|
472
472
|
class ValueVariable extends VariableBase {
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
473
|
+
constructor(props) {
|
|
474
|
+
super(props);
|
|
475
|
+
this.type = "text";
|
|
476
|
+
this.isCollection = false;
|
|
477
|
+
this.type = props?.declaration?.type ?? "text";
|
|
478
|
+
}
|
|
479
|
+
getDescription() {
|
|
480
|
+
if (this.description == null) {
|
|
481
|
+
return resolveIntlPath(this._profile?.intlStrings, this.type.toLowerCase()) ?? "";
|
|
482
|
+
}
|
|
483
|
+
return super.getDescription();
|
|
484
|
+
}
|
|
485
|
+
toProfileVariableDefinition() {
|
|
486
|
+
return { type: this.type, name: "", ...this.declaration };
|
|
487
|
+
}
|
|
488
488
|
}
|
|
489
489
|
/**
|
|
490
490
|
* Represents the IProfileArray. The main difference is that the IProfileValue type
|
|
491
491
|
* is used as valueType.
|
|
492
492
|
*/
|
|
493
493
|
class ArrayVariable extends VariableBase {
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
494
|
+
constructor(props) {
|
|
495
|
+
super(props);
|
|
496
|
+
this.type = "array";
|
|
497
|
+
this.isCollection = false;
|
|
498
|
+
this.elementType = props.declaration?.elementType ?? { type: "number", name: "number" };
|
|
499
|
+
}
|
|
500
|
+
getDescription() {
|
|
501
|
+
if (this.description == null) {
|
|
502
|
+
return resolveIntlPath(this._profile?.intlStrings, this.type.toLowerCase()) ?? "";
|
|
503
|
+
}
|
|
504
|
+
return super.getDescription();
|
|
505
|
+
}
|
|
506
|
+
toProfileVariableDefinition() {
|
|
507
|
+
return { type: this.type, elementType: this.elementType, name: "", ...this.declaration };
|
|
508
|
+
}
|
|
509
509
|
}
|
|
510
510
|
/**
|
|
511
511
|
* Represents a collection of items. The collection of items can be synchronous or
|
|
@@ -514,595 +514,595 @@ class ArrayVariable extends VariableBase {
|
|
|
514
514
|
* collection is ready or not.
|
|
515
515
|
*/
|
|
516
516
|
class CollectionBasedVariable extends VariableBase {
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
517
|
+
constructor(props) {
|
|
518
|
+
super(props);
|
|
519
|
+
this.isCollection = true;
|
|
520
|
+
this._loaded = true;
|
|
521
|
+
/**
|
|
522
|
+
* The collection of items used to display the profile.
|
|
523
|
+
* If the collection is asynchronous, the 'load' function should
|
|
524
|
+
* be called first before using the items.
|
|
525
|
+
*/
|
|
526
|
+
this.variables = [];
|
|
527
|
+
}
|
|
521
528
|
/**
|
|
522
|
-
*
|
|
523
|
-
* If the collection is asynchronous, the 'load' function should
|
|
524
|
-
* be called first before using the items.
|
|
529
|
+
* Returns true if the collection has been loaded
|
|
525
530
|
*/
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
return null;
|
|
546
|
-
}
|
|
547
|
-
get informationType() {
|
|
548
|
-
return "";
|
|
549
|
-
}
|
|
531
|
+
get loaded() {
|
|
532
|
+
return this._loaded;
|
|
533
|
+
}
|
|
534
|
+
/**
|
|
535
|
+
* Loads the items if the collection is asynchronous.
|
|
536
|
+
* If the colleciton is synchronous then the function is a no-op.
|
|
537
|
+
*/
|
|
538
|
+
async loadSource() {
|
|
539
|
+
return;
|
|
540
|
+
}
|
|
541
|
+
/**
|
|
542
|
+
* Returns an url to the associated information
|
|
543
|
+
*/
|
|
544
|
+
get informationUrl() {
|
|
545
|
+
return null;
|
|
546
|
+
}
|
|
547
|
+
get informationType() {
|
|
548
|
+
return "";
|
|
549
|
+
}
|
|
550
550
|
}
|
|
551
551
|
class GroupOfVariables extends ProfileItemBase {
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
552
|
+
constructor(profile, label, variables = []) {
|
|
553
|
+
super(profile, label);
|
|
554
|
+
this.variables = variables;
|
|
555
|
+
this.type = "group";
|
|
556
|
+
this.isCollection = true;
|
|
557
|
+
}
|
|
558
|
+
passFilter() {
|
|
559
|
+
return true;
|
|
560
|
+
}
|
|
561
561
|
}
|
|
562
562
|
class DictionaryVariable extends CollectionBasedVariable {
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
});
|
|
593
|
-
return properties;
|
|
594
|
-
}
|
|
595
|
-
createVariableInstance(declaration) {
|
|
596
|
-
const snippet = assembleMemberExpression(this.snippet, declaration.name);
|
|
597
|
-
switch (declaration.type) {
|
|
598
|
-
case "number":
|
|
599
|
-
case "text":
|
|
600
|
-
case "boolean":
|
|
601
|
-
case "date":
|
|
602
|
-
case "geometry":
|
|
603
|
-
return new ValueVariable({ profile: this._profile, declaration, label: snippet, snippet });
|
|
604
|
-
case "feature":
|
|
605
|
-
return new FeatureVariable({ profile: this._profile, declaration, label: snippet, snippet });
|
|
606
|
-
case "featureSet":
|
|
607
|
-
return new FeatureSetVariable({ profile: this._profile, declaration, label: snippet, snippet }, [
|
|
608
|
-
new ValueVariable({ profile: this._profile, label: snippet, description: "", snippet })
|
|
609
|
-
]);
|
|
610
|
-
case "featureSetCollection":
|
|
611
|
-
return new FeatureSetCollectionVariable({
|
|
612
|
-
profile: this._profile,
|
|
613
|
-
declaration,
|
|
614
|
-
label: snippet,
|
|
615
|
-
snippet
|
|
616
|
-
});
|
|
617
|
-
case "dictionary":
|
|
618
|
-
return new DictionaryVariable({
|
|
619
|
-
profile: this._profile,
|
|
620
|
-
declaration,
|
|
621
|
-
label: snippet,
|
|
622
|
-
snippet
|
|
623
|
-
});
|
|
624
|
-
case "array":
|
|
625
|
-
return new ArrayVariable({
|
|
626
|
-
profile: this._profile,
|
|
627
|
-
declaration,
|
|
628
|
-
label: snippet,
|
|
629
|
-
snippet
|
|
563
|
+
constructor(props) {
|
|
564
|
+
super(props);
|
|
565
|
+
this.type = "dictionary";
|
|
566
|
+
/**
|
|
567
|
+
* The variables that the dictionary holds. It is different than the variables.
|
|
568
|
+
* The variables may contain grouping.
|
|
569
|
+
*/
|
|
570
|
+
this.dictionaryVariables = [];
|
|
571
|
+
this.loadPropertyDeclarations(props?.declaration?.properties);
|
|
572
|
+
// If we have a snippet then wrap the properties in a group and use the snippet as the heading
|
|
573
|
+
// This is not applicable for root Dictionary such as Profile
|
|
574
|
+
if (this.snippet && this.dictionaryVariables.length) {
|
|
575
|
+
this.variables = [new GroupOfVariables(this._profile, this.snippet, this.dictionaryVariables)];
|
|
576
|
+
}
|
|
577
|
+
}
|
|
578
|
+
loadPropertyDeclarations(declarations) {
|
|
579
|
+
this.dictionaryVariables = this.createVariableInstances(declarations);
|
|
580
|
+
this.variables = this.dictionaryVariables;
|
|
581
|
+
}
|
|
582
|
+
createVariableInstances(declarations) {
|
|
583
|
+
if (!Array.isArray(declarations)) {
|
|
584
|
+
return [];
|
|
585
|
+
}
|
|
586
|
+
const properties = [];
|
|
587
|
+
declarations.forEach((declaration) => {
|
|
588
|
+
const variable = this.createVariableInstance(declaration);
|
|
589
|
+
if (variable) {
|
|
590
|
+
properties.push(variable);
|
|
591
|
+
}
|
|
630
592
|
});
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
593
|
+
return properties;
|
|
594
|
+
}
|
|
595
|
+
createVariableInstance(declaration) {
|
|
596
|
+
const snippet = assembleMemberExpression(this.snippet, declaration.name);
|
|
597
|
+
switch (declaration.type) {
|
|
598
|
+
case "number":
|
|
599
|
+
case "text":
|
|
600
|
+
case "boolean":
|
|
601
|
+
case "date":
|
|
602
|
+
case "geometry":
|
|
603
|
+
return new ValueVariable({ profile: this._profile, declaration, label: snippet, snippet });
|
|
604
|
+
case "feature":
|
|
605
|
+
return new FeatureVariable({ profile: this._profile, declaration, label: snippet, snippet });
|
|
606
|
+
case "featureSet":
|
|
607
|
+
return new FeatureSetVariable({ profile: this._profile, declaration, label: snippet, snippet }, [
|
|
608
|
+
new ValueVariable({ profile: this._profile, label: snippet, description: "", snippet })
|
|
609
|
+
]);
|
|
610
|
+
case "featureSetCollection":
|
|
611
|
+
return new FeatureSetCollectionVariable({
|
|
612
|
+
profile: this._profile,
|
|
613
|
+
declaration,
|
|
614
|
+
label: snippet,
|
|
615
|
+
snippet
|
|
616
|
+
});
|
|
617
|
+
case "dictionary":
|
|
618
|
+
return new DictionaryVariable({
|
|
619
|
+
profile: this._profile,
|
|
620
|
+
declaration,
|
|
621
|
+
label: snippet,
|
|
622
|
+
snippet
|
|
623
|
+
});
|
|
624
|
+
case "array":
|
|
625
|
+
return new ArrayVariable({
|
|
626
|
+
profile: this._profile,
|
|
627
|
+
declaration,
|
|
628
|
+
label: snippet,
|
|
629
|
+
snippet
|
|
630
|
+
});
|
|
631
|
+
default:
|
|
632
|
+
console.error("Invalid profile variable", declaration);
|
|
633
|
+
return null;
|
|
634
|
+
}
|
|
635
|
+
}
|
|
636
|
+
toProfileVariableDefinition() {
|
|
637
|
+
return {
|
|
638
|
+
type: this.type,
|
|
639
|
+
name: "",
|
|
640
|
+
...this.declaration,
|
|
641
|
+
properties: this.dictionaryVariables.map((variable) => variable.toProfileVariableDefinition())
|
|
642
|
+
};
|
|
634
643
|
}
|
|
635
|
-
}
|
|
636
|
-
toProfileVariableDefinition() {
|
|
637
|
-
return {
|
|
638
|
-
type: this.type,
|
|
639
|
-
name: "",
|
|
640
|
-
...this.declaration,
|
|
641
|
-
properties: this.dictionaryVariables.map((variable) => variable.toProfileVariableDefinition())
|
|
642
|
-
};
|
|
643
|
-
}
|
|
644
644
|
}
|
|
645
645
|
class SourceBasedVariable extends CollectionBasedVariable {
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
646
|
+
constructor(props, relationshipsProperties) {
|
|
647
|
+
super(props);
|
|
648
|
+
this.relationshipsProperties = relationshipsProperties;
|
|
649
|
+
this._source = null;
|
|
650
|
+
this._loaded = false;
|
|
651
|
+
this._definition = props?.declaration?.definition;
|
|
652
|
+
}
|
|
653
|
+
get title() {
|
|
654
|
+
return this._source?.title ?? "";
|
|
655
|
+
}
|
|
656
|
+
get url() {
|
|
657
|
+
return this._definition?.url ?? "";
|
|
658
|
+
}
|
|
659
|
+
get informationUrl() {
|
|
660
|
+
if (!this.loaded) {
|
|
661
|
+
return null;
|
|
662
|
+
}
|
|
663
|
+
const url = this._source?.url;
|
|
664
|
+
if (!url) {
|
|
665
|
+
return null;
|
|
666
|
+
}
|
|
667
|
+
const layerId = this._source?.layerId ?? "";
|
|
668
|
+
return `${url}/${layerId}`;
|
|
669
|
+
}
|
|
670
|
+
get informationType() {
|
|
671
|
+
return this._profile?.intlStrings?.layer ?? "layer";
|
|
672
|
+
}
|
|
673
|
+
loadSource() {
|
|
674
|
+
if (D(this._loadPromise) && G(this._loadPromise)) {
|
|
675
|
+
return this._loadPromise;
|
|
676
|
+
}
|
|
677
|
+
this._loadPromise = this._loadSource();
|
|
678
|
+
return this._loadPromise;
|
|
679
|
+
}
|
|
680
|
+
_getFieldProperty(field) {
|
|
681
|
+
// Check if the field is the type id field or of the field has a coded domain.
|
|
682
|
+
// If it has then the property will be an exanpdable property (dictionary).
|
|
683
|
+
// Otherwise just return a simple value property.
|
|
684
|
+
const subtypesOrDomainValuesDictionary = this._getSubtypesOrDomainValuesDictionary(field);
|
|
685
|
+
if (subtypesOrDomainValuesDictionary) {
|
|
686
|
+
return subtypesOrDomainValuesDictionary;
|
|
687
|
+
}
|
|
688
|
+
// Create the value property
|
|
689
|
+
const valueSnippet = this.type === "feature" ? assembleMemberExpression(this.snippet, field.name) : field.name;
|
|
690
|
+
return new ValueVariable({
|
|
691
|
+
profile: this._profile,
|
|
692
|
+
label: valueSnippet,
|
|
693
|
+
description: field.alias ?? field.name,
|
|
694
|
+
snippet: valueSnippet,
|
|
695
|
+
icon: fieldTypeToIconName(field),
|
|
696
|
+
filterDescription: true
|
|
697
|
+
});
|
|
698
|
+
}
|
|
699
|
+
_getSubtypesOrDomainValuesDictionary(field) {
|
|
700
|
+
if (!isDomainsCapableLayer(this._source)) {
|
|
701
|
+
return null;
|
|
702
|
+
}
|
|
703
|
+
// Create the domain dictionary, we may not use it
|
|
704
|
+
const valueSnippet = this.type === "feature" ? assembleMemberExpression(this.snippet, field.name) : field.name;
|
|
705
|
+
const domainDictionary = new DictionaryVariable({
|
|
706
|
+
profile: this._profile,
|
|
707
|
+
label: valueSnippet,
|
|
708
|
+
description: field.alias ?? field.name,
|
|
709
|
+
snippet: valueSnippet,
|
|
710
|
+
icon: "form-dropdown"
|
|
711
|
+
});
|
|
712
|
+
// Add the header group
|
|
713
|
+
const headerGroup = new GroupOfVariables(this._profile, field.alias ?? field.name, [
|
|
714
|
+
new ValueVariable({
|
|
715
|
+
profile: this._profile,
|
|
716
|
+
label: valueSnippet,
|
|
717
|
+
description: "",
|
|
718
|
+
snippet: valueSnippet
|
|
719
|
+
})
|
|
720
|
+
]);
|
|
721
|
+
domainDictionary.variables = [headerGroup];
|
|
722
|
+
// If it is the subtype field then get its coded domain values
|
|
723
|
+
if (isTypesCapabaleLayer(this._source) && field.name === this._source.typeIdField) {
|
|
724
|
+
const subtypesGroup = getSubtypesProperties(this._profile, this._source.types, field);
|
|
725
|
+
domainDictionary.variables.push(subtypesGroup);
|
|
726
|
+
return domainDictionary;
|
|
727
|
+
}
|
|
728
|
+
// Since its' not the subtype field then add the snippet for the domain name
|
|
729
|
+
if (this.type === "feature") {
|
|
730
|
+
const domainNameSnippet = `DomainName(${this.snippet}, "${field.name}")`;
|
|
731
|
+
headerGroup.variables.push(new ValueVariable({
|
|
732
|
+
profile: this._profile,
|
|
733
|
+
label: domainNameSnippet,
|
|
734
|
+
description: "",
|
|
735
|
+
snippet: domainNameSnippet
|
|
736
|
+
}));
|
|
737
|
+
}
|
|
738
|
+
if (isTypesCapabaleLayer(this._source)) {
|
|
739
|
+
// Check if all the domains for the field in the types are inherited.
|
|
740
|
+
// If it is we can simplify the structure by avoiding splitting in subtypes
|
|
741
|
+
const allInherited = this._source.types.every((t) => t.domains?.[field.name]?.type === "inherited");
|
|
742
|
+
if (!allInherited) {
|
|
743
|
+
// We have domains per subtype
|
|
744
|
+
// We need to go thru each types and create a dictionary.
|
|
745
|
+
const domainValuesBySubtypeGroup = getDomainValuesBySubtypeGroup(this._profile, this._source.types, field);
|
|
746
|
+
if (!domainValuesBySubtypeGroup) {
|
|
747
|
+
return null;
|
|
748
|
+
}
|
|
749
|
+
domainDictionary.variables.push(domainValuesBySubtypeGroup);
|
|
750
|
+
return domainDictionary;
|
|
751
|
+
}
|
|
752
|
+
}
|
|
753
|
+
// Either we have types but all the domains are inherited or we don't have types
|
|
754
|
+
const domainValuesGroup = getDomainValuesProperties(this._profile, this._source.getFieldDomain?.(field.name), {
|
|
755
|
+
code: "domainvalues"
|
|
756
|
+
});
|
|
757
|
+
if (!domainValuesGroup) {
|
|
758
|
+
return null;
|
|
759
|
+
}
|
|
760
|
+
domainDictionary.variables.push(domainValuesGroup);
|
|
750
761
|
return domainDictionary;
|
|
751
|
-
}
|
|
752
762
|
}
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
label: relatedLayer.title,
|
|
787
|
-
description: "",
|
|
788
|
-
nonInteractive: true
|
|
789
|
-
}, [new ValueVariable({ profile: this._profile, label: snippet, description: "", snippet })], { exposeRelationships: true, sourceTableId: source.layerId });
|
|
790
|
-
}));
|
|
791
|
-
relationshipsGroup.variables = relationshipItems.filter(D);
|
|
792
|
-
if (!relationshipsGroup.variables.length) {
|
|
793
|
-
return null;
|
|
763
|
+
async _getRelationshipsProperty() {
|
|
764
|
+
// We need the data store to find the relationship feature layers
|
|
765
|
+
if (!this.relationshipsProperties?.exposeRelationships || !this._profile?.supportFeatureSetFunctions) {
|
|
766
|
+
return null;
|
|
767
|
+
}
|
|
768
|
+
const source = this._source;
|
|
769
|
+
if (!isRelationshipsCapableLayer(source)) {
|
|
770
|
+
return null;
|
|
771
|
+
}
|
|
772
|
+
const relationshipsGroup = new GroupOfVariables(this._profile, { code: "relationships" });
|
|
773
|
+
const relationshipItems = await Promise.all(source.relationships.map(async (relationship) => {
|
|
774
|
+
const relatedLayer = await getRelatedFeatureLayer(source, relationship);
|
|
775
|
+
if (!isFeatureLayerInstance(relatedLayer)) {
|
|
776
|
+
return null;
|
|
777
|
+
}
|
|
778
|
+
if (relationship.relatedTableId === this.relationshipsProperties?.sourceTableId) {
|
|
779
|
+
// We don't want to show the reverse relationship
|
|
780
|
+
return null;
|
|
781
|
+
}
|
|
782
|
+
const snippet = `FeatureSetByRelationshipName(${this.snippet}, "${relationship.name}")`;
|
|
783
|
+
return new FeatureSetVariable({
|
|
784
|
+
profile: this._profile,
|
|
785
|
+
declaration: { definition: relatedLayer },
|
|
786
|
+
label: relatedLayer.title,
|
|
787
|
+
description: "",
|
|
788
|
+
nonInteractive: true
|
|
789
|
+
}, [new ValueVariable({ profile: this._profile, label: snippet, description: "", snippet })], { exposeRelationships: true, sourceTableId: source.layerId });
|
|
790
|
+
}));
|
|
791
|
+
relationshipsGroup.variables = relationshipItems.filter(D);
|
|
792
|
+
if (!relationshipsGroup.variables.length) {
|
|
793
|
+
return null;
|
|
794
|
+
}
|
|
795
|
+
return relationshipsGroup;
|
|
794
796
|
}
|
|
795
|
-
return relationshipsGroup;
|
|
796
|
-
}
|
|
797
797
|
}
|
|
798
798
|
class FeatureVariable extends SourceBasedVariable {
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
}
|
|
803
|
-
get title() {
|
|
804
|
-
if (isSupportedLayerInstance(this._source)) {
|
|
805
|
-
return this._source.title;
|
|
806
|
-
}
|
|
807
|
-
return { code: "feature" };
|
|
808
|
-
}
|
|
809
|
-
async _loadSource() {
|
|
810
|
-
if (this.loaded) {
|
|
811
|
-
return this._source;
|
|
799
|
+
constructor(props) {
|
|
800
|
+
super(props, { exposeRelationships: true });
|
|
801
|
+
this.type = "feature";
|
|
812
802
|
}
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
// The title group and snippet
|
|
819
|
-
const title = isSupportedLayerInstance(this._source) ? this._source.title : "";
|
|
820
|
-
this.variables.push(new GroupOfVariables(this._profile, title, [
|
|
821
|
-
new ValueVariable({
|
|
822
|
-
profile: this._profile,
|
|
823
|
-
label: this.snippet,
|
|
824
|
-
description: "",
|
|
825
|
-
snippet: this.snippet
|
|
826
|
-
})
|
|
827
|
-
]));
|
|
828
|
-
// The collection of feature attribute values
|
|
829
|
-
const valuesGroup = new GroupOfVariables(this._profile, { code: "values" });
|
|
830
|
-
this.variables.push(valuesGroup);
|
|
831
|
-
// Add the geometry if it's a feature layer and not a table
|
|
832
|
-
if (isTableCapableLayer(this._source) && !this._source.isTable) {
|
|
833
|
-
const snippet = `Geometry(${this.snippet})`;
|
|
834
|
-
const geometryProperty = new ValueVariable({
|
|
835
|
-
profile: this._profile,
|
|
836
|
-
declaration: { name: snippet },
|
|
837
|
-
label: snippet,
|
|
838
|
-
description: "Geometry",
|
|
839
|
-
snippet,
|
|
840
|
-
icon: "shapes",
|
|
841
|
-
filterDescription: true
|
|
842
|
-
});
|
|
843
|
-
valuesGroup.variables.push(geometryProperty);
|
|
844
|
-
}
|
|
845
|
-
this._source.fields.sort(sortFields(this._source)).forEach((field) => {
|
|
846
|
-
valuesGroup.variables.push(this._getFieldProperty(field));
|
|
847
|
-
});
|
|
848
|
-
// The relatonships
|
|
849
|
-
const relationshipsGroup = await this._getRelationshipsProperty();
|
|
850
|
-
if (relationshipsGroup) {
|
|
851
|
-
this.variables.push(relationshipsGroup);
|
|
852
|
-
}
|
|
803
|
+
get title() {
|
|
804
|
+
if (isSupportedLayerInstance(this._source)) {
|
|
805
|
+
return this._source.title;
|
|
806
|
+
}
|
|
807
|
+
return { code: "feature" };
|
|
853
808
|
}
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
809
|
+
async _loadSource() {
|
|
810
|
+
if (this.loaded) {
|
|
811
|
+
return this._source;
|
|
812
|
+
}
|
|
813
|
+
try {
|
|
814
|
+
this._source = await supportedSourceFromDefinition(this._definition);
|
|
815
|
+
if (!this._source) {
|
|
816
|
+
throw new Error("Invalid definition");
|
|
817
|
+
}
|
|
818
|
+
// The title group and snippet
|
|
819
|
+
const title = isSupportedLayerInstance(this._source) ? this._source.title : "";
|
|
820
|
+
this.variables.push(new GroupOfVariables(this._profile, title, [
|
|
821
|
+
new ValueVariable({
|
|
822
|
+
profile: this._profile,
|
|
823
|
+
label: this.snippet,
|
|
824
|
+
description: "",
|
|
825
|
+
snippet: this.snippet
|
|
826
|
+
})
|
|
827
|
+
]));
|
|
828
|
+
// The collection of feature attribute values
|
|
829
|
+
const valuesGroup = new GroupOfVariables(this._profile, { code: "values" });
|
|
830
|
+
this.variables.push(valuesGroup);
|
|
831
|
+
// Add the geometry if it's a feature layer and not a table
|
|
832
|
+
if (isTableCapableLayer(this._source) && !this._source.isTable) {
|
|
833
|
+
const snippet = `Geometry(${this.snippet})`;
|
|
834
|
+
const geometryProperty = new ValueVariable({
|
|
835
|
+
profile: this._profile,
|
|
836
|
+
declaration: { name: snippet },
|
|
837
|
+
label: snippet,
|
|
838
|
+
description: "Geometry",
|
|
839
|
+
snippet,
|
|
840
|
+
icon: "shapes",
|
|
841
|
+
filterDescription: true
|
|
842
|
+
});
|
|
843
|
+
valuesGroup.variables.push(geometryProperty);
|
|
844
|
+
}
|
|
845
|
+
this._source.fields.sort(sortFields(this._source)).forEach((field) => {
|
|
846
|
+
valuesGroup.variables.push(this._getFieldProperty(field));
|
|
847
|
+
});
|
|
848
|
+
// The relatonships
|
|
849
|
+
const relationshipsGroup = await this._getRelationshipsProperty();
|
|
850
|
+
if (relationshipsGroup) {
|
|
851
|
+
this.variables.push(relationshipsGroup);
|
|
852
|
+
}
|
|
853
|
+
}
|
|
854
|
+
catch (e) {
|
|
855
|
+
console.error("Loading issue", e, this);
|
|
856
|
+
this._source = null;
|
|
857
|
+
}
|
|
858
|
+
finally {
|
|
859
|
+
this._loaded = true;
|
|
860
|
+
}
|
|
861
|
+
return this._source;
|
|
857
862
|
}
|
|
858
|
-
|
|
859
|
-
|
|
863
|
+
toProfileVariableDefinition() {
|
|
864
|
+
return { type: this.type, name: "", ...this.declaration, definition: this._definition };
|
|
860
865
|
}
|
|
861
|
-
return this._source;
|
|
862
|
-
}
|
|
863
|
-
toProfileVariableDefinition() {
|
|
864
|
-
return { type: this.type, name: "", ...this.declaration, definition: this._definition };
|
|
865
|
-
}
|
|
866
866
|
}
|
|
867
867
|
class FeatureSetVariable extends SourceBasedVariable {
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
}
|
|
882
|
-
async _loadSource() {
|
|
883
|
-
if (this.loaded) {
|
|
884
|
-
return this._source;
|
|
885
|
-
}
|
|
886
|
-
try {
|
|
887
|
-
this._source = await supportedSourceFromDefinition(this._definition);
|
|
888
|
-
if (!this._source) {
|
|
889
|
-
throw new Error("Invalid definition");
|
|
890
|
-
}
|
|
891
|
-
// The title group and snippet
|
|
892
|
-
this.variables.push(new GroupOfVariables(this._profile, this.title, this.featureSetSnippets));
|
|
893
|
-
// Add the fields
|
|
894
|
-
const fieldsGroup = new GroupOfVariables(this._profile, { code: "fields" });
|
|
895
|
-
this.variables.push(fieldsGroup);
|
|
896
|
-
fieldsGroup.variables = this._source.fields
|
|
897
|
-
.sort(sortFields(this._source))
|
|
898
|
-
.map((field) => this._getFieldProperty(field));
|
|
899
|
-
// Add the relationships if enabled
|
|
900
|
-
const relationshipsGroup = await this._getRelationshipsProperty();
|
|
901
|
-
if (relationshipsGroup) {
|
|
902
|
-
this.variables.push(relationshipsGroup);
|
|
903
|
-
}
|
|
868
|
+
constructor(props, featureSetSnippets = [],
|
|
869
|
+
// Relationships for feature set if only supported if the feature set is actually
|
|
870
|
+
// representing a relationsip feature layer for a feature source.
|
|
871
|
+
relationshipProps) {
|
|
872
|
+
super(props, relationshipProps);
|
|
873
|
+
this.featureSetSnippets = featureSetSnippets;
|
|
874
|
+
this.type = "featureSet";
|
|
875
|
+
}
|
|
876
|
+
get title() {
|
|
877
|
+
if (isSupportedLayerInstance(this._source)) {
|
|
878
|
+
return this._source.title;
|
|
879
|
+
}
|
|
880
|
+
return { code: "featureset" };
|
|
904
881
|
}
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
882
|
+
async _loadSource() {
|
|
883
|
+
if (this.loaded) {
|
|
884
|
+
return this._source;
|
|
885
|
+
}
|
|
886
|
+
try {
|
|
887
|
+
this._source = await supportedSourceFromDefinition(this._definition);
|
|
888
|
+
if (!this._source) {
|
|
889
|
+
throw new Error("Invalid definition");
|
|
890
|
+
}
|
|
891
|
+
// The title group and snippet
|
|
892
|
+
this.variables.push(new GroupOfVariables(this._profile, this.title, this.featureSetSnippets));
|
|
893
|
+
// Add the fields
|
|
894
|
+
const fieldsGroup = new GroupOfVariables(this._profile, { code: "fields" });
|
|
895
|
+
this.variables.push(fieldsGroup);
|
|
896
|
+
fieldsGroup.variables = this._source.fields
|
|
897
|
+
.sort(sortFields(this._source))
|
|
898
|
+
.map((field) => this._getFieldProperty(field));
|
|
899
|
+
// Add the relationships if enabled
|
|
900
|
+
const relationshipsGroup = await this._getRelationshipsProperty();
|
|
901
|
+
if (relationshipsGroup) {
|
|
902
|
+
this.variables.push(relationshipsGroup);
|
|
903
|
+
}
|
|
904
|
+
}
|
|
905
|
+
catch (e) {
|
|
906
|
+
console.error("Loading issue", e, this);
|
|
907
|
+
this._source = null;
|
|
908
|
+
}
|
|
909
|
+
finally {
|
|
910
|
+
this._loaded = true;
|
|
911
|
+
}
|
|
912
|
+
return this._source;
|
|
908
913
|
}
|
|
909
|
-
|
|
910
|
-
|
|
914
|
+
toProfileVariableDefinition() {
|
|
915
|
+
return { type: this.type, name: "", ...this.declaration, definition: this._definition };
|
|
911
916
|
}
|
|
912
|
-
return this._source;
|
|
913
|
-
}
|
|
914
|
-
toProfileVariableDefinition() {
|
|
915
|
-
return { type: this.type, name: "", ...this.declaration, definition: this._definition };
|
|
916
|
-
}
|
|
917
917
|
}
|
|
918
918
|
class FeatureSetCollectionVariable extends CollectionBasedVariable {
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
}
|
|
939
|
-
get informationType() {
|
|
940
|
-
if (!this.loaded || !this._featureSetCollections) {
|
|
941
|
-
return "";
|
|
942
|
-
}
|
|
943
|
-
if (typeof this._featureSetCollections.source !== "string") {
|
|
944
|
-
return this._profile?.intlStrings?.webmap ?? "webmap";
|
|
945
|
-
}
|
|
946
|
-
return this._profile?.intlStrings?.featureservice ?? "featureservice";
|
|
947
|
-
}
|
|
948
|
-
async loadSource() {
|
|
949
|
-
if (D(this._loadPromise) && G(this._loadPromise)) {
|
|
950
|
-
return this._loadPromise;
|
|
951
|
-
}
|
|
952
|
-
this._loadPromise = this._loadSource();
|
|
953
|
-
return this._loadPromise;
|
|
954
|
-
}
|
|
955
|
-
async _loadSource() {
|
|
956
|
-
if (this.loaded) {
|
|
957
|
-
return this._featureSetCollections;
|
|
919
|
+
constructor(props) {
|
|
920
|
+
super(props);
|
|
921
|
+
this.type = "featureSetCollection";
|
|
922
|
+
this._featureSetCollections = null;
|
|
923
|
+
this._loaded = false;
|
|
924
|
+
this._definition = props?.declaration?.definition;
|
|
925
|
+
}
|
|
926
|
+
get informationUrl() {
|
|
927
|
+
if (!this.loaded || !this._featureSetCollections) {
|
|
928
|
+
return null;
|
|
929
|
+
}
|
|
930
|
+
if (typeof this._featureSetCollections.source !== "string") {
|
|
931
|
+
return portalItemPageUrl(this._featureSetCollections.source.portalItem);
|
|
932
|
+
}
|
|
933
|
+
// const firstLayer = this._featureSetCollection.layers[0] ?? this._featureSetCollection.tables[0];
|
|
934
|
+
// if (!firstLayer) {
|
|
935
|
+
return null;
|
|
936
|
+
// }
|
|
937
|
+
// return `${firstLayer.url}`;
|
|
958
938
|
}
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
: {
|
|
968
|
-
code: "webmapformat",
|
|
969
|
-
formatValues: {
|
|
970
|
-
webMapTitle: this._featureSetCollections.source.portalItem?.title ?? "Untitled map"
|
|
971
|
-
}
|
|
972
|
-
};
|
|
973
|
-
const headerGroup = new GroupOfVariables(this._profile, groupLabel, [
|
|
974
|
-
new ValueVariable({
|
|
975
|
-
profile: this._profile,
|
|
976
|
-
label: this.snippet,
|
|
977
|
-
description: "",
|
|
978
|
-
snippet: this.snippet
|
|
979
|
-
})
|
|
980
|
-
]);
|
|
981
|
-
// Creates the groups for the layer and tables
|
|
982
|
-
const layersGroup = new GroupOfVariables(this._profile, { code: "layers" }, this._featureSetCollections.layers);
|
|
983
|
-
const tablesGroup = new GroupOfVariables(this._profile, { code: "tables" }, this._featureSetCollections.tables);
|
|
984
|
-
this.variables.push(headerGroup, layersGroup, tablesGroup);
|
|
939
|
+
get informationType() {
|
|
940
|
+
if (!this.loaded || !this._featureSetCollections) {
|
|
941
|
+
return "";
|
|
942
|
+
}
|
|
943
|
+
if (typeof this._featureSetCollections.source !== "string") {
|
|
944
|
+
return this._profile?.intlStrings?.webmap ?? "webmap";
|
|
945
|
+
}
|
|
946
|
+
return this._profile?.intlStrings?.featureservice ?? "featureservice";
|
|
985
947
|
}
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
}
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
948
|
+
async loadSource() {
|
|
949
|
+
if (D(this._loadPromise) && G(this._loadPromise)) {
|
|
950
|
+
return this._loadPromise;
|
|
951
|
+
}
|
|
952
|
+
this._loadPromise = this._loadSource();
|
|
953
|
+
return this._loadPromise;
|
|
954
|
+
}
|
|
955
|
+
async _loadSource() {
|
|
956
|
+
if (this.loaded) {
|
|
957
|
+
return this._featureSetCollections;
|
|
958
|
+
}
|
|
959
|
+
try {
|
|
960
|
+
this._featureSetCollections = await this._featureSetCollectionsFromDefinition();
|
|
961
|
+
if (!this._featureSetCollections) {
|
|
962
|
+
throw new Error("Invalid definition");
|
|
963
|
+
}
|
|
964
|
+
// Create the group for the header
|
|
965
|
+
const groupLabel = typeof this._featureSetCollections.source === "string"
|
|
966
|
+
? { code: this._featureSetCollections.source.endsWith("FeatureServer") ? "featureservice" : "mapservice" }
|
|
967
|
+
: {
|
|
968
|
+
code: "webmapformat",
|
|
969
|
+
formatValues: {
|
|
970
|
+
webMapTitle: this._featureSetCollections.source.portalItem?.title ?? "Untitled map"
|
|
971
|
+
}
|
|
972
|
+
};
|
|
973
|
+
const headerGroup = new GroupOfVariables(this._profile, groupLabel, [
|
|
974
|
+
new ValueVariable({
|
|
975
|
+
profile: this._profile,
|
|
976
|
+
label: this.snippet,
|
|
977
|
+
description: "",
|
|
978
|
+
snippet: this.snippet
|
|
979
|
+
})
|
|
980
|
+
]);
|
|
981
|
+
// Creates the groups for the layer and tables
|
|
982
|
+
const layersGroup = new GroupOfVariables(this._profile, { code: "layers" }, this._featureSetCollections.layers);
|
|
983
|
+
const tablesGroup = new GroupOfVariables(this._profile, { code: "tables" }, this._featureSetCollections.tables);
|
|
984
|
+
this.variables.push(headerGroup, layersGroup, tablesGroup);
|
|
985
|
+
}
|
|
986
|
+
catch (e) {
|
|
987
|
+
console.error("Loading issue", e, this);
|
|
988
|
+
this._featureSetCollections = null;
|
|
989
|
+
}
|
|
990
|
+
finally {
|
|
991
|
+
this._loaded = true;
|
|
992
|
+
}
|
|
993
|
+
return this._featureSetCollections;
|
|
994
|
+
}
|
|
995
|
+
async _featureSetCollectionsFromDefinition() {
|
|
996
|
+
if (!this._definition) {
|
|
997
|
+
return null;
|
|
998
|
+
}
|
|
999
|
+
if (isWebMapInstance(this._definition)) {
|
|
1000
|
+
return this._featureSetCollectionFromWebMap(this._definition);
|
|
1001
|
+
}
|
|
1002
|
+
if (isSupportedLayerInstance(this._definition)) {
|
|
1003
|
+
return this._featureSetCollectionFromUrl(this._definition.url);
|
|
1004
|
+
}
|
|
1005
|
+
if (isPortalItemDefinition(this._definition)) {
|
|
1006
|
+
// Preload the portal item so we can discover if are dealing with a Web Map
|
|
1007
|
+
// or Feature Service
|
|
1008
|
+
return this._featureSetCollectionFromPortalItem(this._definition.portalItem);
|
|
1009
|
+
}
|
|
1010
|
+
if (isUrlDefinition(this._definition)) {
|
|
1011
|
+
// Assume that the url is pointing to a feature server
|
|
1012
|
+
return this._featureSetCollectionFromUrl(this._definition.url);
|
|
1013
|
+
}
|
|
1037
1014
|
return null;
|
|
1038
1015
|
}
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
}));
|
|
1050
|
-
const tablesPromise = Promise.all(metadata.tables.map(async (layerInfo) => {
|
|
1051
|
-
const fl = await newFeatureLayer({ url: `${url}/${layerInfo.id}` });
|
|
1052
|
-
await fl.load();
|
|
1053
|
-
return this._createFeatureSetVariable(fl);
|
|
1054
|
-
}));
|
|
1055
|
-
const [layers, tables] = await Promise.all([layersPromise, tablesPromise]);
|
|
1056
|
-
return { layers, tables, source: url };
|
|
1057
|
-
}
|
|
1058
|
-
_convertWebMapLayersToVariables(layers, filteringTables = false) {
|
|
1059
|
-
const layerVariables = [];
|
|
1060
|
-
layers
|
|
1061
|
-
.toArray()
|
|
1062
|
-
.reverse()
|
|
1063
|
-
.forEach((layer) => {
|
|
1064
|
-
if (isFeatureLayerInstance(layer)) {
|
|
1065
|
-
layerVariables.push(this._createFeatureSetVariable(layer, true));
|
|
1066
|
-
return;
|
|
1067
|
-
}
|
|
1068
|
-
if (isGroupLayerInstance(layer)) {
|
|
1069
|
-
const groupLayerVariables = filteringTables
|
|
1070
|
-
? this._convertWebMapLayersToVariables(layer.allTables, true)
|
|
1071
|
-
: this._convertWebMapLayersToVariables(layer.allLayers);
|
|
1072
|
-
layerVariables.push(...groupLayerVariables);
|
|
1073
|
-
}
|
|
1074
|
-
});
|
|
1075
|
-
return layerVariables;
|
|
1076
|
-
}
|
|
1077
|
-
_createFeatureSetVariable(featureLayer, isFromWebMap = false) {
|
|
1078
|
-
return new FeatureSetVariable({
|
|
1079
|
-
profile: this._profile,
|
|
1080
|
-
declaration: { definition: featureLayer },
|
|
1081
|
-
label: featureLayer.title,
|
|
1082
|
-
description: "",
|
|
1083
|
-
nonInteractive: true
|
|
1084
|
-
}, this._makeFeatureSetSnippets(featureLayer, isFromWebMap));
|
|
1085
|
-
}
|
|
1086
|
-
_makeFeatureSetSnippets(featureLayer, isFromWebMap = false) {
|
|
1087
|
-
if (!this._profile?.supportFeatureSetFunctions) {
|
|
1088
|
-
return [];
|
|
1089
|
-
}
|
|
1090
|
-
if (isFromWebMap) {
|
|
1091
|
-
const snippetById = `FeatureSetById(${this.snippet}, "${featureLayer.id}")`;
|
|
1092
|
-
const snippetByName = `FeatureSetByName(${this.snippet}, "${featureLayer.title}")`;
|
|
1093
|
-
return [
|
|
1094
|
-
new ValueVariable({ profile: this._profile, label: snippetById, description: "", snippet: snippetById }),
|
|
1095
|
-
new ValueVariable({ profile: this._profile, label: snippetByName, description: "", snippet: snippetByName })
|
|
1096
|
-
];
|
|
1016
|
+
async _featureSetCollectionFromWebMap(definition) {
|
|
1017
|
+
const webMap = isWebMapInstance(definition) ? definition : await newWebMap({ portalItem: definition });
|
|
1018
|
+
await webMap.loadAll();
|
|
1019
|
+
// Until jsapi fix a bug we have to load the table separately
|
|
1020
|
+
await Promise.all(webMap.tables.map(async (t) => t.load()));
|
|
1021
|
+
return {
|
|
1022
|
+
layers: this._convertWebMapLayersToVariables(webMap.layers),
|
|
1023
|
+
tables: this._convertWebMapLayersToVariables(webMap.tables, true),
|
|
1024
|
+
source: webMap
|
|
1025
|
+
};
|
|
1097
1026
|
}
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
|
|
1027
|
+
async _featureSetCollectionFromPortalItem(definition) {
|
|
1028
|
+
const portalItem = await newPortalItem(definition);
|
|
1029
|
+
await portalItem.load();
|
|
1030
|
+
switch (portalItem.type) {
|
|
1031
|
+
case "Web Map":
|
|
1032
|
+
return this._featureSetCollectionFromWebMap(portalItem);
|
|
1033
|
+
case "Feature Service":
|
|
1034
|
+
return this._featureSetCollectionFromUrl(portalItem.url);
|
|
1035
|
+
default:
|
|
1036
|
+
console.error("Unsupported portal item", definition);
|
|
1037
|
+
return null;
|
|
1038
|
+
}
|
|
1039
|
+
}
|
|
1040
|
+
async _featureSetCollectionFromUrl(url) {
|
|
1041
|
+
url = url.replace(/\/featureserver\/[0-9]*/iu, "/FeatureServer");
|
|
1042
|
+
url = url.replace(/\/mapserver\/[0-9]*/iu, "/MapServer");
|
|
1043
|
+
url = url.split("?")[0];
|
|
1044
|
+
const metadata = await serviceMetaData(url);
|
|
1045
|
+
const layersPromise = Promise.all(metadata.layers.map(async (layerInfo) => {
|
|
1046
|
+
const fl = await newFeatureLayer({ url: `${url}/${layerInfo.id}` });
|
|
1047
|
+
await fl.load();
|
|
1048
|
+
return this._createFeatureSetVariable(fl);
|
|
1049
|
+
}));
|
|
1050
|
+
const tablesPromise = Promise.all(metadata.tables.map(async (layerInfo) => {
|
|
1051
|
+
const fl = await newFeatureLayer({ url: `${url}/${layerInfo.id}` });
|
|
1052
|
+
await fl.load();
|
|
1053
|
+
return this._createFeatureSetVariable(fl);
|
|
1054
|
+
}));
|
|
1055
|
+
const [layers, tables] = await Promise.all([layersPromise, tablesPromise]);
|
|
1056
|
+
return { layers, tables, source: url };
|
|
1057
|
+
}
|
|
1058
|
+
_convertWebMapLayersToVariables(layers, filteringTables = false) {
|
|
1059
|
+
const layerVariables = [];
|
|
1060
|
+
layers
|
|
1061
|
+
.toArray()
|
|
1062
|
+
.reverse()
|
|
1063
|
+
.forEach((layer) => {
|
|
1064
|
+
if (isFeatureLayerInstance(layer)) {
|
|
1065
|
+
layerVariables.push(this._createFeatureSetVariable(layer, true));
|
|
1066
|
+
return;
|
|
1067
|
+
}
|
|
1068
|
+
if (isGroupLayerInstance(layer)) {
|
|
1069
|
+
const groupLayerVariables = filteringTables
|
|
1070
|
+
? this._convertWebMapLayersToVariables(layer.allTables, true)
|
|
1071
|
+
: this._convertWebMapLayersToVariables(layer.allLayers);
|
|
1072
|
+
layerVariables.push(...groupLayerVariables);
|
|
1073
|
+
}
|
|
1074
|
+
});
|
|
1075
|
+
return layerVariables;
|
|
1076
|
+
}
|
|
1077
|
+
_createFeatureSetVariable(featureLayer, isFromWebMap = false) {
|
|
1078
|
+
return new FeatureSetVariable({
|
|
1079
|
+
profile: this._profile,
|
|
1080
|
+
declaration: { definition: featureLayer },
|
|
1081
|
+
label: featureLayer.title,
|
|
1082
|
+
description: "",
|
|
1083
|
+
nonInteractive: true
|
|
1084
|
+
}, this._makeFeatureSetSnippets(featureLayer, isFromWebMap));
|
|
1085
|
+
}
|
|
1086
|
+
_makeFeatureSetSnippets(featureLayer, isFromWebMap = false) {
|
|
1087
|
+
if (!this._profile?.supportFeatureSetFunctions) {
|
|
1088
|
+
return [];
|
|
1089
|
+
}
|
|
1090
|
+
if (isFromWebMap) {
|
|
1091
|
+
const snippetById = `FeatureSetById(${this.snippet}, "${featureLayer.id}")`;
|
|
1092
|
+
const snippetByName = `FeatureSetByName(${this.snippet}, "${featureLayer.title}")`;
|
|
1093
|
+
return [
|
|
1094
|
+
new ValueVariable({ profile: this._profile, label: snippetById, description: "", snippet: snippetById }),
|
|
1095
|
+
new ValueVariable({ profile: this._profile, label: snippetByName, description: "", snippet: snippetByName })
|
|
1096
|
+
];
|
|
1097
|
+
}
|
|
1098
|
+
else {
|
|
1099
|
+
const snippetById = `FeatureSetById(${this.snippet}, "${featureLayer.layerId}")`;
|
|
1100
|
+
return [new ValueVariable({ profile: this._profile, label: snippetById, description: "", snippet: snippetById })];
|
|
1101
|
+
}
|
|
1102
|
+
}
|
|
1103
|
+
toProfileVariableDefinition() {
|
|
1104
|
+
return { type: this.type, name: "", ...this.declaration, definition: this._definition };
|
|
1101
1105
|
}
|
|
1102
|
-
}
|
|
1103
|
-
toProfileVariableDefinition() {
|
|
1104
|
-
return { type: this.type, name: "", ...this.declaration, definition: this._definition };
|
|
1105
|
-
}
|
|
1106
1106
|
}
|
|
1107
1107
|
/**
|
|
1108
1108
|
* The EditorProfile is an object that represents an Arcade Profile.
|
|
@@ -1113,64 +1113,64 @@ class FeatureSetCollectionVariable extends CollectionBasedVariable {
|
|
|
1113
1113
|
* They need to be loaded asynchronously to get the metadata necessary for validation and completion.
|
|
1114
1114
|
*/
|
|
1115
1115
|
class EditorProfile extends DictionaryVariable {
|
|
1116
|
-
|
|
1117
|
-
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
|
|
1124
|
-
|
|
1125
|
-
|
|
1126
|
-
|
|
1127
|
-
|
|
1128
|
-
|
|
1129
|
-
|
|
1130
|
-
|
|
1131
|
-
|
|
1132
|
-
|
|
1133
|
-
|
|
1134
|
-
|
|
1135
|
-
|
|
1136
|
-
|
|
1137
|
-
|
|
1138
|
-
|
|
1139
|
-
|
|
1140
|
-
|
|
1141
|
-
|
|
1142
|
-
|
|
1143
|
-
|
|
1144
|
-
|
|
1145
|
-
|
|
1146
|
-
|
|
1147
|
-
|
|
1148
|
-
|
|
1149
|
-
|
|
1150
|
-
|
|
1151
|
-
|
|
1152
|
-
|
|
1153
|
-
|
|
1154
|
-
|
|
1116
|
+
constructor(definition, intlStrings, locale = "en") {
|
|
1117
|
+
// Delay the load of the variable declarations so we have a `this`
|
|
1118
|
+
super({
|
|
1119
|
+
profile: null,
|
|
1120
|
+
declaration: { properties: [] }
|
|
1121
|
+
});
|
|
1122
|
+
this.definition = definition;
|
|
1123
|
+
this.intlStrings = intlStrings;
|
|
1124
|
+
this.locale = locale;
|
|
1125
|
+
this.variables = [];
|
|
1126
|
+
// We are the root
|
|
1127
|
+
this._profile = this;
|
|
1128
|
+
// Now that `this` is defined, we can load the variables
|
|
1129
|
+
this.loadPropertyDeclarations(definition?.variables);
|
|
1130
|
+
}
|
|
1131
|
+
/**
|
|
1132
|
+
* Returns true if the profile supports feature set functions for snippets.
|
|
1133
|
+
*/
|
|
1134
|
+
get supportFeatureSetFunctions() {
|
|
1135
|
+
return this.definition?.bundles?.includes("data-access") ?? false;
|
|
1136
|
+
}
|
|
1137
|
+
/**
|
|
1138
|
+
* Returns the language service profile. It is different than the editor profile as it is optimized for Monaco.
|
|
1139
|
+
*/
|
|
1140
|
+
async toLSProfile() {
|
|
1141
|
+
const { apiVersion, bundles, hiddenApiItems } = this.definition ?? {};
|
|
1142
|
+
const variables = await variablesToLSVariable(this.dictionaryVariables);
|
|
1143
|
+
return { apiVersion, bundles, variables, hiddenApiItems: hiddenApiItems?.map((s) => s.toLowerCase()) };
|
|
1144
|
+
}
|
|
1145
|
+
/**
|
|
1146
|
+
* Returns the EditorProfile as a json. The EditorProfile may have been updated. This function allows to
|
|
1147
|
+
* get the new json representing mutations.
|
|
1148
|
+
*/
|
|
1149
|
+
toEditorProfileDefinition() {
|
|
1150
|
+
return {
|
|
1151
|
+
...this.definition,
|
|
1152
|
+
variables: this.dictionaryVariables.map((variable) => variable.toProfileVariableDefinition())
|
|
1153
|
+
};
|
|
1154
|
+
}
|
|
1155
1155
|
}
|
|
1156
1156
|
//#endregion
|
|
1157
1157
|
|
|
1158
1158
|
function isFeatureDefinition(item) {
|
|
1159
|
-
|
|
1160
|
-
|
|
1161
|
-
|
|
1162
|
-
|
|
1163
|
-
|
|
1159
|
+
return (isSupportedLayerInstance(item) ||
|
|
1160
|
+
isFeatureSetInstance(item) ||
|
|
1161
|
+
isUrlDefinition(item) ||
|
|
1162
|
+
isFieldsDefinition(item) ||
|
|
1163
|
+
isFeatureLayerItemDefinition(item));
|
|
1164
1164
|
}
|
|
1165
1165
|
function isFeatureSetDefinition(item) {
|
|
1166
|
-
|
|
1167
|
-
|
|
1168
|
-
|
|
1169
|
-
|
|
1170
|
-
|
|
1166
|
+
return (isFeatureLayerInstance(item) ||
|
|
1167
|
+
isFeatureSetInstance(item) ||
|
|
1168
|
+
isUrlDefinition(item) ||
|
|
1169
|
+
isFieldsDefinition(item) ||
|
|
1170
|
+
isFeatureLayerItemDefinition(item));
|
|
1171
1171
|
}
|
|
1172
1172
|
function isFeatureSetCollectionDefinition(item) {
|
|
1173
|
-
|
|
1173
|
+
return isPortalItemDefinition(item) || isWebMapInstance(item) || isFeatureSetDefinition(item);
|
|
1174
1174
|
}
|
|
1175
1175
|
/**
|
|
1176
1176
|
* Get a PredefinedProfile for a locale. If not already loaded then fetch it.
|
|
@@ -1178,26 +1178,26 @@ function isFeatureSetCollectionDefinition(item) {
|
|
|
1178
1178
|
* the english version of the profile.
|
|
1179
1179
|
*/
|
|
1180
1180
|
async function getSdkPredefinedProfiles(locale = "en") {
|
|
1181
|
-
|
|
1182
|
-
|
|
1183
|
-
|
|
1184
|
-
|
|
1185
|
-
|
|
1186
|
-
|
|
1187
|
-
|
|
1188
|
-
|
|
1189
|
-
|
|
1190
|
-
|
|
1191
|
-
|
|
1192
|
-
|
|
1193
|
-
|
|
1194
|
-
|
|
1195
|
-
|
|
1196
|
-
|
|
1197
|
-
|
|
1198
|
-
|
|
1199
|
-
|
|
1200
|
-
|
|
1181
|
+
const profiles = sdkPredefinedProfilesMap.get(locale);
|
|
1182
|
+
if (profiles) {
|
|
1183
|
+
return profiles;
|
|
1184
|
+
}
|
|
1185
|
+
if (!x.has(locale)) {
|
|
1186
|
+
return getSdkPredefinedProfiles("en");
|
|
1187
|
+
}
|
|
1188
|
+
try {
|
|
1189
|
+
const response = await fetch(getAssetPath(`./assets/arcade-language/profiles/arcade-profiles.t9n.${locale}.json`));
|
|
1190
|
+
if (response.ok) {
|
|
1191
|
+
return cacheSdkPredefinedProfiles(locale, await response.json());
|
|
1192
|
+
}
|
|
1193
|
+
if (locale === "en") {
|
|
1194
|
+
return null;
|
|
1195
|
+
}
|
|
1196
|
+
return getSdkPredefinedProfiles("en");
|
|
1197
|
+
}
|
|
1198
|
+
catch (e) {
|
|
1199
|
+
return null;
|
|
1200
|
+
}
|
|
1201
1201
|
}
|
|
1202
1202
|
const sdkPredefinedProfilesMap = new Map();
|
|
1203
1203
|
/**
|
|
@@ -1205,237 +1205,237 @@ const sdkPredefinedProfilesMap = new Map();
|
|
|
1205
1205
|
* Map of profiles per locale.
|
|
1206
1206
|
*/
|
|
1207
1207
|
function cacheSdkPredefinedProfiles(locale, profiles) {
|
|
1208
|
-
|
|
1209
|
-
|
|
1210
|
-
|
|
1211
|
-
|
|
1212
|
-
|
|
1213
|
-
|
|
1208
|
+
const map = new Map();
|
|
1209
|
+
profiles.forEach((profile) => {
|
|
1210
|
+
map.set(profile.id, profile);
|
|
1211
|
+
});
|
|
1212
|
+
sdkPredefinedProfilesMap.set(locale, map);
|
|
1213
|
+
return map;
|
|
1214
1214
|
}
|
|
1215
1215
|
async function getSdkPredefinedProfile(id, locale = "en") {
|
|
1216
|
-
|
|
1217
|
-
|
|
1216
|
+
const profiles = await getSdkPredefinedProfiles(locale);
|
|
1217
|
+
return profiles?.get(id) ?? null;
|
|
1218
1218
|
}
|
|
1219
1219
|
function isExtendedPredefinedProfileDefinition(predefinedProfileDefinition) {
|
|
1220
|
-
|
|
1220
|
+
return Array.isArray(predefinedProfileDefinition?.additionalVariables);
|
|
1221
1221
|
}
|
|
1222
1222
|
function convertApiVariables(variables) {
|
|
1223
|
-
|
|
1224
|
-
|
|
1225
|
-
|
|
1226
|
-
|
|
1223
|
+
if (!variables) {
|
|
1224
|
+
return [];
|
|
1225
|
+
}
|
|
1226
|
+
return variables.map(convertApiVariable);
|
|
1227
1227
|
}
|
|
1228
1228
|
function convertApiVariable(variable) {
|
|
1229
|
-
|
|
1230
|
-
|
|
1231
|
-
|
|
1232
|
-
|
|
1233
|
-
|
|
1234
|
-
|
|
1235
|
-
|
|
1236
|
-
|
|
1237
|
-
|
|
1238
|
-
|
|
1239
|
-
|
|
1240
|
-
|
|
1241
|
-
|
|
1242
|
-
|
|
1243
|
-
|
|
1244
|
-
|
|
1245
|
-
|
|
1229
|
+
switch (variable.type) {
|
|
1230
|
+
case "dictionary":
|
|
1231
|
+
return {
|
|
1232
|
+
...variable,
|
|
1233
|
+
type: variable.type,
|
|
1234
|
+
properties: convertApiVariables(variable.properties)
|
|
1235
|
+
};
|
|
1236
|
+
case "array": {
|
|
1237
|
+
return {
|
|
1238
|
+
...variable,
|
|
1239
|
+
type: variable.type,
|
|
1240
|
+
elementType: { type: "number", name: "number" }
|
|
1241
|
+
};
|
|
1242
|
+
}
|
|
1243
|
+
default:
|
|
1244
|
+
return { ...variable, type: variable.type };
|
|
1245
|
+
}
|
|
1246
1246
|
}
|
|
1247
1247
|
async function convertToEditorProfileDefinition(predefinedProfile, locale = "en") {
|
|
1248
|
-
|
|
1249
|
-
|
|
1250
|
-
|
|
1251
|
-
|
|
1252
|
-
|
|
1253
|
-
|
|
1254
|
-
|
|
1255
|
-
|
|
1256
|
-
|
|
1257
|
-
|
|
1258
|
-
|
|
1259
|
-
|
|
1260
|
-
|
|
1261
|
-
|
|
1262
|
-
|
|
1263
|
-
|
|
1264
|
-
|
|
1265
|
-
|
|
1266
|
-
|
|
1267
|
-
|
|
1268
|
-
|
|
1269
|
-
|
|
1270
|
-
|
|
1271
|
-
|
|
1272
|
-
|
|
1273
|
-
|
|
1274
|
-
|
|
1275
|
-
|
|
1276
|
-
|
|
1277
|
-
|
|
1278
|
-
|
|
1279
|
-
|
|
1280
|
-
|
|
1281
|
-
|
|
1282
|
-
|
|
1283
|
-
|
|
1284
|
-
|
|
1285
|
-
|
|
1286
|
-
|
|
1287
|
-
|
|
1288
|
-
|
|
1289
|
-
|
|
1290
|
-
|
|
1291
|
-
|
|
1292
|
-
|
|
1293
|
-
|
|
1294
|
-
|
|
1295
|
-
|
|
1296
|
-
|
|
1297
|
-
|
|
1298
|
-
|
|
1299
|
-
|
|
1300
|
-
|
|
1248
|
+
if (!isPredefinedProfile(predefinedProfile)) {
|
|
1249
|
+
return undefined;
|
|
1250
|
+
}
|
|
1251
|
+
const sdkPredefinedProfile = await getSdkPredefinedProfile(predefinedProfile.id, locale);
|
|
1252
|
+
if (!sdkPredefinedProfile) {
|
|
1253
|
+
return undefined;
|
|
1254
|
+
}
|
|
1255
|
+
const editorProfile = {
|
|
1256
|
+
bundles: [...sdkPredefinedProfile.bundles],
|
|
1257
|
+
variables: [],
|
|
1258
|
+
hiddenApiItems: predefinedProfile.hiddenApiItems?.map((s) => s.toLowerCase())
|
|
1259
|
+
};
|
|
1260
|
+
// Merge the SDK variables' definitions/properties with the predefined profile definitions.
|
|
1261
|
+
sdkPredefinedProfile.variables.forEach((sdkVariable) => {
|
|
1262
|
+
// Don't include disabled variables
|
|
1263
|
+
if (predefinedProfile.disabledVariables?.includes(sdkVariable.name)) {
|
|
1264
|
+
return;
|
|
1265
|
+
}
|
|
1266
|
+
// Try to get a definition from the predefined profile.
|
|
1267
|
+
const definition = predefinedProfile.definitions[sdkVariable.name];
|
|
1268
|
+
// Note: Something is weird with TS. The sdkVariables are being casted to the wrong type
|
|
1269
|
+
// despite the type checking from the switch statement.
|
|
1270
|
+
switch (sdkVariable.type) {
|
|
1271
|
+
case "dictionary":
|
|
1272
|
+
// For dictionary, we support properties overrride
|
|
1273
|
+
return editorProfile.variables.push(convertApiVariable({
|
|
1274
|
+
...sdkVariable,
|
|
1275
|
+
type: sdkVariable.type,
|
|
1276
|
+
properties: Array.isArray(definition) ? [...definition] : sdkVariable.properties
|
|
1277
|
+
}));
|
|
1278
|
+
case "feature":
|
|
1279
|
+
if (isFeatureDefinition(definition)) {
|
|
1280
|
+
return editorProfile.variables.push({ ...sdkVariable, type: sdkVariable.type, definition });
|
|
1281
|
+
}
|
|
1282
|
+
return editorProfile.variables.push({ ...sdkVariable, type: sdkVariable.type });
|
|
1283
|
+
case "featureSet":
|
|
1284
|
+
if (isFeatureSetDefinition(definition)) {
|
|
1285
|
+
return editorProfile.variables.push({ ...sdkVariable, type: sdkVariable.type, definition });
|
|
1286
|
+
}
|
|
1287
|
+
return editorProfile.variables.push({ ...sdkVariable, type: sdkVariable.type });
|
|
1288
|
+
case "featureSetCollection":
|
|
1289
|
+
if (isFeatureSetCollectionDefinition(definition)) {
|
|
1290
|
+
return editorProfile.variables.push({ ...sdkVariable, type: sdkVariable.type, definition });
|
|
1291
|
+
}
|
|
1292
|
+
return editorProfile.variables.push({ ...sdkVariable, type: sdkVariable.type });
|
|
1293
|
+
default:
|
|
1294
|
+
return editorProfile.variables.push(convertApiVariable(sdkVariable));
|
|
1295
|
+
}
|
|
1296
|
+
});
|
|
1297
|
+
if (isExtendedPredefinedProfileDefinition(predefinedProfile)) {
|
|
1298
|
+
editorProfile.variables.push(...(predefinedProfile.additionalVariables ?? []));
|
|
1299
|
+
}
|
|
1300
|
+
return editorProfile;
|
|
1301
1301
|
}
|
|
1302
1302
|
|
|
1303
1303
|
const arcadeLanguageId = "arcade";
|
|
1304
1304
|
const defaultContext = {
|
|
1305
|
-
|
|
1305
|
+
locale: "en"
|
|
1306
1306
|
};
|
|
1307
1307
|
class ArcadeLanguageServiceDefaults {
|
|
1308
|
-
|
|
1309
|
-
|
|
1310
|
-
|
|
1311
|
-
|
|
1312
|
-
|
|
1313
|
-
|
|
1314
|
-
|
|
1315
|
-
|
|
1316
|
-
|
|
1317
|
-
|
|
1318
|
-
|
|
1319
|
-
|
|
1320
|
-
|
|
1321
|
-
|
|
1322
|
-
|
|
1323
|
-
|
|
1324
|
-
|
|
1325
|
-
|
|
1326
|
-
|
|
1327
|
-
|
|
1328
|
-
|
|
1329
|
-
|
|
1330
|
-
|
|
1331
|
-
|
|
1332
|
-
|
|
1333
|
-
|
|
1334
|
-
|
|
1335
|
-
|
|
1336
|
-
|
|
1337
|
-
|
|
1338
|
-
|
|
1339
|
-
|
|
1340
|
-
|
|
1341
|
-
|
|
1342
|
-
|
|
1343
|
-
|
|
1344
|
-
|
|
1345
|
-
|
|
1346
|
-
|
|
1347
|
-
|
|
1348
|
-
|
|
1349
|
-
|
|
1350
|
-
|
|
1351
|
-
|
|
1352
|
-
|
|
1353
|
-
|
|
1354
|
-
|
|
1355
|
-
|
|
1356
|
-
|
|
1357
|
-
|
|
1358
|
-
|
|
1359
|
-
|
|
1360
|
-
|
|
1361
|
-
|
|
1362
|
-
|
|
1363
|
-
|
|
1364
|
-
|
|
1365
|
-
|
|
1366
|
-
|
|
1367
|
-
|
|
1368
|
-
|
|
1369
|
-
|
|
1370
|
-
|
|
1371
|
-
|
|
1372
|
-
|
|
1373
|
-
|
|
1374
|
-
|
|
1375
|
-
|
|
1376
|
-
|
|
1377
|
-
|
|
1378
|
-
|
|
1379
|
-
|
|
1380
|
-
|
|
1381
|
-
|
|
1382
|
-
|
|
1383
|
-
|
|
1384
|
-
|
|
1385
|
-
|
|
1386
|
-
|
|
1387
|
-
|
|
1388
|
-
|
|
1389
|
-
|
|
1390
|
-
|
|
1391
|
-
|
|
1392
|
-
|
|
1393
|
-
|
|
1394
|
-
|
|
1395
|
-
|
|
1396
|
-
|
|
1397
|
-
|
|
1398
|
-
|
|
1399
|
-
|
|
1400
|
-
|
|
1401
|
-
|
|
1402
|
-
|
|
1403
|
-
|
|
1404
|
-
|
|
1405
|
-
|
|
1406
|
-
|
|
1407
|
-
|
|
1408
|
-
|
|
1409
|
-
|
|
1410
|
-
|
|
1411
|
-
|
|
1412
|
-
|
|
1413
|
-
|
|
1414
|
-
|
|
1415
|
-
|
|
1416
|
-
|
|
1417
|
-
|
|
1418
|
-
|
|
1419
|
-
|
|
1420
|
-
|
|
1421
|
-
|
|
1422
|
-
|
|
1423
|
-
|
|
1424
|
-
|
|
1425
|
-
|
|
1426
|
-
|
|
1427
|
-
|
|
1428
|
-
|
|
1429
|
-
|
|
1430
|
-
|
|
1431
|
-
|
|
1432
|
-
|
|
1433
|
-
|
|
1434
|
-
|
|
1308
|
+
constructor() {
|
|
1309
|
+
this._languageId = arcadeLanguageId;
|
|
1310
|
+
this._languageOptions = {};
|
|
1311
|
+
this._onDidChange = new Emitter();
|
|
1312
|
+
this._profileMap = new Map();
|
|
1313
|
+
this._apiContextMap = new Map();
|
|
1314
|
+
this._onModelContextDidChange = new Emitter();
|
|
1315
|
+
this._onDidModelContextChangeTimeout = -1;
|
|
1316
|
+
}
|
|
1317
|
+
get onDidChange() {
|
|
1318
|
+
return this._onDidChange.event;
|
|
1319
|
+
}
|
|
1320
|
+
get onModelContextDidChange() {
|
|
1321
|
+
return this._onModelContextDidChange.event;
|
|
1322
|
+
}
|
|
1323
|
+
get languageId() {
|
|
1324
|
+
return this._languageId;
|
|
1325
|
+
}
|
|
1326
|
+
get languageOptions() {
|
|
1327
|
+
return this._languageOptions;
|
|
1328
|
+
}
|
|
1329
|
+
_fireModelContextDidChange(key) {
|
|
1330
|
+
if (this._onDidModelContextChangeTimeout !== -1) {
|
|
1331
|
+
return;
|
|
1332
|
+
}
|
|
1333
|
+
this._onDidModelContextChangeTimeout = window.setTimeout(() => {
|
|
1334
|
+
this._onDidModelContextChangeTimeout = -1;
|
|
1335
|
+
this._onModelContextDidChange.fire(key);
|
|
1336
|
+
}, 0);
|
|
1337
|
+
}
|
|
1338
|
+
_getApiKey(modelId) {
|
|
1339
|
+
if (!Uri.isUri(modelId)) {
|
|
1340
|
+
modelId = Uri.parse(modelId);
|
|
1341
|
+
}
|
|
1342
|
+
return modelId.toString();
|
|
1343
|
+
}
|
|
1344
|
+
/**
|
|
1345
|
+
* Create an EditorProfile for the given model id using the given definition and locale.
|
|
1346
|
+
* The EditorProfile is used by the the Arcade Language service as well by the cosing components.
|
|
1347
|
+
* The definition can be a pre-defined profile or an editor profile definition.
|
|
1348
|
+
* If the locale is not provided then the 'en' locale is used.
|
|
1349
|
+
* @param modelId The model id for which to create the context.
|
|
1350
|
+
* @param definition The definition to use for the model context.
|
|
1351
|
+
* @param locale The locale to use for the model context.
|
|
1352
|
+
* @returns The EditorProfile for the model.
|
|
1353
|
+
*/
|
|
1354
|
+
async setProfileForModel(modelId, definition, apiContext = { locale: "en" }) {
|
|
1355
|
+
// Convert pre-defined profile to a runtime profile
|
|
1356
|
+
if (isPredefinedProfile(definition)) {
|
|
1357
|
+
definition = await convertToEditorProfileDefinition(definition, apiContext.locale);
|
|
1358
|
+
}
|
|
1359
|
+
const intlStrings = await N(apiContext.locale, getAssetPath("./assets/arcade-language/t9n"), "profile.t9n.");
|
|
1360
|
+
if (!intlStrings) {
|
|
1361
|
+
throw new Error(`Failed to load the language bundle for ${apiContext.locale}`);
|
|
1362
|
+
}
|
|
1363
|
+
this.disposeEditorProfileForModel(modelId);
|
|
1364
|
+
const key = this._getApiKey(modelId);
|
|
1365
|
+
const editorProfile = new EditorProfile(definition, intlStrings);
|
|
1366
|
+
this._profileMap.set(key, editorProfile);
|
|
1367
|
+
const apiProfile = await editorProfile.toLSProfile();
|
|
1368
|
+
this.updateApiContextForModel(modelId, {
|
|
1369
|
+
locale: apiContext.locale,
|
|
1370
|
+
profile: apiProfile,
|
|
1371
|
+
snippets: apiContext.snippets
|
|
1372
|
+
});
|
|
1373
|
+
}
|
|
1374
|
+
/**
|
|
1375
|
+
* Dispose the editor profile for the given model id.
|
|
1376
|
+
* It is the responsibility of the caller that created the editor profile to dispose it.
|
|
1377
|
+
* @param modelId The model id for which to dispose the editor profile.
|
|
1378
|
+
*/
|
|
1379
|
+
disposeEditorProfileForModel(modelId) {
|
|
1380
|
+
const key = this._getApiKey(modelId);
|
|
1381
|
+
this._profileMap.delete(key);
|
|
1382
|
+
}
|
|
1383
|
+
/**
|
|
1384
|
+
* Dispose the api context for the given model id.
|
|
1385
|
+
* @param modelId The model id for which to dispose the api context.
|
|
1386
|
+
*/
|
|
1387
|
+
disposeApiContextForModel(modelId) {
|
|
1388
|
+
const key = this._getApiKey(modelId);
|
|
1389
|
+
if (this._apiContextMap.delete(key)) {
|
|
1390
|
+
this._fireModelContextDidChange(key);
|
|
1391
|
+
}
|
|
1392
|
+
}
|
|
1393
|
+
/**
|
|
1394
|
+
* Returns the editor profile for the given model id.
|
|
1395
|
+
* @param modelId The model id for which to get the editor profile.
|
|
1396
|
+
* @returns The editor profile for the model.
|
|
1397
|
+
*/
|
|
1398
|
+
getEditorProfileForModel(modelId) {
|
|
1399
|
+
return this._profileMap.get(this._getApiKey(modelId));
|
|
1400
|
+
}
|
|
1401
|
+
/**
|
|
1402
|
+
* Returns the API context for the given model id.
|
|
1403
|
+
* Returns the default context if the model has no context.
|
|
1404
|
+
* @param modelId The model id for which to get the API context.
|
|
1405
|
+
* @returns The API context for the model.
|
|
1406
|
+
*/
|
|
1407
|
+
getApiContextForModel(contextId) {
|
|
1408
|
+
return this._apiContextMap.get(this._getApiKey(contextId)) ?? defaultContext;
|
|
1409
|
+
}
|
|
1410
|
+
/**
|
|
1411
|
+
* Set or update api context for the given model id.
|
|
1412
|
+
* @param modelId The model id for which to set the context.
|
|
1413
|
+
* @param apiContext The api context to set.
|
|
1414
|
+
*/
|
|
1415
|
+
updateApiContextForModel(modelId, apiContext) {
|
|
1416
|
+
const key = this._getApiKey(modelId);
|
|
1417
|
+
const currentApiContext = this._apiContextMap.get(key) ?? {};
|
|
1418
|
+
this._apiContextMap.set(key, { ...currentApiContext, ...apiContext });
|
|
1419
|
+
this._fireModelContextDidChange(key);
|
|
1420
|
+
}
|
|
1421
|
+
/**
|
|
1422
|
+
* Set or update the Arcade language service options.
|
|
1423
|
+
* @param languageOptions The language options to set.
|
|
1424
|
+
*/
|
|
1425
|
+
setLanguageOptions(languageOptions = {}) {
|
|
1426
|
+
// Check if options have actually changed.
|
|
1427
|
+
// Avoid restarting the worker when no updates.
|
|
1428
|
+
// Today we only have the 'assetsPath' as a property
|
|
1429
|
+
if (this._languageOptions.assetsPath === languageOptions.assetsPath) {
|
|
1430
|
+
return;
|
|
1431
|
+
}
|
|
1432
|
+
this._languageOptions = { ...this._languageOptions, ...languageOptions };
|
|
1433
|
+
this._onDidChange.fire(this);
|
|
1434
|
+
}
|
|
1435
1435
|
}
|
|
1436
1436
|
const arcadeDefaults = new ArcadeLanguageServiceDefaults();
|
|
1437
1437
|
const arcade = {
|
|
1438
|
-
|
|
1438
|
+
setProfileForModel: arcadeDefaults.setProfileForModel.bind(arcadeDefaults)
|
|
1439
1439
|
};
|
|
1440
1440
|
|
|
1441
1441
|
export { arcade as a, arcadeDefaults as b };
|