@itwin/grouping-mapping-widget 0.7.0 → 0.8.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/cjs/widget/components/BlockingOverlay.js +1 -2
- package/lib/cjs/widget/components/BlockingOverlay.js.map +1 -1
- package/lib/cjs/widget/components/BlockingOverlay.scss +8 -10
- package/lib/cjs/widget/components/GroupPropertyAction.d.ts +1 -1
- package/lib/cjs/widget/components/GroupPropertyAction.js +149 -302
- package/lib/cjs/widget/components/GroupPropertyAction.js.map +1 -1
- package/lib/cjs/widget/components/GroupPropertyAction.scss +82 -8
- package/lib/cjs/widget/components/GroupPropertyUtils.d.ts +21 -0
- package/lib/cjs/widget/components/GroupPropertyUtils.js +287 -0
- package/lib/cjs/widget/components/GroupPropertyUtils.js.map +1 -0
- package/lib/cjs/widget/components/GroupingMapping.scss +4 -1
- package/lib/cjs/widget/components/HorizontalTile.d.ts +5 -3
- package/lib/cjs/widget/components/HorizontalTile.js +9 -6
- package/lib/cjs/widget/components/HorizontalTile.js.map +1 -1
- package/lib/cjs/widget/components/HorizontalTile.scss +46 -22
- package/lib/cjs/widget/components/SelectProject.js +2 -0
- package/lib/cjs/widget/components/SelectProject.js.map +1 -1
- package/lib/cjs/widget/components/SortableHorizontalTile.d.ts +8 -0
- package/lib/cjs/widget/components/SortableHorizontalTile.js +51 -0
- package/lib/cjs/widget/components/SortableHorizontalTile.js.map +1 -0
- package/lib/esm/widget/components/BlockingOverlay.js +1 -2
- package/lib/esm/widget/components/BlockingOverlay.js.map +1 -1
- package/lib/esm/widget/components/BlockingOverlay.scss +8 -10
- package/lib/esm/widget/components/GroupPropertyAction.d.ts +1 -1
- package/lib/esm/widget/components/GroupPropertyAction.js +151 -304
- package/lib/esm/widget/components/GroupPropertyAction.js.map +1 -1
- package/lib/esm/widget/components/GroupPropertyAction.scss +82 -8
- package/lib/esm/widget/components/GroupPropertyUtils.d.ts +21 -0
- package/lib/esm/widget/components/GroupPropertyUtils.js +280 -0
- package/lib/esm/widget/components/GroupPropertyUtils.js.map +1 -0
- package/lib/esm/widget/components/GroupingMapping.scss +4 -1
- package/lib/esm/widget/components/HorizontalTile.d.ts +5 -3
- package/lib/esm/widget/components/HorizontalTile.js +9 -6
- package/lib/esm/widget/components/HorizontalTile.js.map +1 -1
- package/lib/esm/widget/components/HorizontalTile.scss +46 -22
- package/lib/esm/widget/components/SelectProject.js +2 -0
- package/lib/esm/widget/components/SelectProject.js.map +1 -1
- package/lib/esm/widget/components/SortableHorizontalTile.d.ts +8 -0
- package/lib/esm/widget/components/SortableHorizontalTile.js +30 -0
- package/lib/esm/widget/components/SortableHorizontalTile.js.map +1 -0
- package/package.json +8 -3
|
@@ -1,16 +1,26 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
/*---------------------------------------------------------------------------------------------
|
|
2
|
+
* Copyright (c) Bentley Systems, Incorporated. All rights reserved.
|
|
3
|
+
* See LICENSE.md in the project root for license terms and full copyright notice.
|
|
4
|
+
*--------------------------------------------------------------------------------------------*/
|
|
5
|
+
import { renderToStaticMarkup } from "react-dom/server";
|
|
6
|
+
import { PropertyValueFormat } from "@itwin/presentation-common";
|
|
3
7
|
import { useActiveIModelConnection } from "@itwin/appui-react";
|
|
4
|
-
import {
|
|
5
|
-
import { Alert, Fieldset, IconButton, LabeledInput, LabeledSelect, Select, Small, Text, } from "@itwin/itwinui-react";
|
|
8
|
+
import { Alert, Button, Fieldset, IconButton, Label, LabeledInput, LabeledSelect, Modal, ModalButtonBar, Small, Surface, Text, } from "@itwin/itwinui-react";
|
|
6
9
|
import React, { useCallback, useEffect, useMemo, useState } from "react";
|
|
7
10
|
import ActionPanel from "./ActionPanel";
|
|
8
11
|
import useValidator, { NAME_REQUIREMENTS } from "../hooks/useValidator";
|
|
9
12
|
import { handleError, WidgetHeader } from "./utils";
|
|
10
|
-
import "./GroupPropertyAction.scss";
|
|
11
|
-
import { DataType, QuantityType } from "@itwin/insights-client";
|
|
12
13
|
import { useMappingClient } from "./context/MappingClientContext";
|
|
13
14
|
import { useGroupingMappingApiConfig } from "./context/GroupingApiConfigContext";
|
|
15
|
+
import { HorizontalTile } from "./HorizontalTile";
|
|
16
|
+
import { DataType, QuantityType } from "@itwin/insights-client";
|
|
17
|
+
import { SvgClose, SvgDragHandleVertical, SvgMoreVerticalSmall, SvgRemove, SvgSearch, } from "@itwin/itwinui-icons-react";
|
|
18
|
+
import { closestCenter, DndContext, DragOverlay, KeyboardSensor, PointerSensor, useSensor, useSensors, } from "@dnd-kit/core";
|
|
19
|
+
import { arrayMove, SortableContext, sortableKeyboardCoordinates, verticalListSortingStrategy, } from "@dnd-kit/sortable";
|
|
20
|
+
import SortableHorizontalTile from "./SortableHorizontalTile";
|
|
21
|
+
import Split from "react-split";
|
|
22
|
+
import "./GroupPropertyAction.scss";
|
|
23
|
+
import { convertPresentationFields, convertToECProperties, fetchPresentationDescriptor, findProperties, } from "./GroupPropertyUtils";
|
|
14
24
|
export const quantityTypesSelectionOptions = [
|
|
15
25
|
{ value: QuantityType.Area, label: "Area" },
|
|
16
26
|
{ value: QuantityType.Distance, label: "Distance" },
|
|
@@ -21,130 +31,6 @@ export const quantityTypesSelectionOptions = [
|
|
|
21
31
|
{ value: QuantityType.Volume, label: "Volume" },
|
|
22
32
|
{ value: QuantityType.Undefined, label: "No Quantity Type" },
|
|
23
33
|
];
|
|
24
|
-
const extractPrimitive = (propertiesField, classToPropertiesMapping, navigation) => {
|
|
25
|
-
var _a, _b;
|
|
26
|
-
// There are rare cases which only happens in multiple selections where it returns more than one.
|
|
27
|
-
// This also checks if this property comes from a navigation property
|
|
28
|
-
const className = (_a = navigation === null || navigation === void 0 ? void 0 : navigation.rootClassName) !== null && _a !== void 0 ? _a : propertiesField.properties[0].property.classInfo.name;
|
|
29
|
-
// Sometimes class names are not defined. Type error. Not guaranteed.
|
|
30
|
-
if (!className) {
|
|
31
|
-
return;
|
|
32
|
-
}
|
|
33
|
-
if (!classToPropertiesMapping.has(className)) {
|
|
34
|
-
classToPropertiesMapping.set(className, []);
|
|
35
|
-
}
|
|
36
|
-
// Gets property name. Appends path if from navigation.
|
|
37
|
-
const propertyName = navigation
|
|
38
|
-
? `${navigation.navigationName}.${propertiesField.properties[0].property.name}`
|
|
39
|
-
: propertiesField.properties[0].property.name;
|
|
40
|
-
const label = navigation
|
|
41
|
-
? `${propertiesField.label} (${navigation === null || navigation === void 0 ? void 0 : navigation.navigationName})`
|
|
42
|
-
: propertiesField.label;
|
|
43
|
-
// Ignore hardcoded BisCore navigation properties
|
|
44
|
-
if (propertiesField.type.typeName === "navigation") {
|
|
45
|
-
return;
|
|
46
|
-
}
|
|
47
|
-
else {
|
|
48
|
-
(_b = classToPropertiesMapping.get(className)) === null || _b === void 0 ? void 0 : _b.push({
|
|
49
|
-
name: propertyName,
|
|
50
|
-
label,
|
|
51
|
-
type: propertiesField.properties[0].property.type,
|
|
52
|
-
});
|
|
53
|
-
}
|
|
54
|
-
};
|
|
55
|
-
const extractStructProperties = (name, className, classToPropertiesMapping, members) => {
|
|
56
|
-
var _a;
|
|
57
|
-
for (const member of members) {
|
|
58
|
-
if (member.type.valueFormat === PropertyValueFormat.Primitive) {
|
|
59
|
-
if (!classToPropertiesMapping.has(className)) {
|
|
60
|
-
classToPropertiesMapping.set(className, []);
|
|
61
|
-
}
|
|
62
|
-
(_a = classToPropertiesMapping.get(className)) === null || _a === void 0 ? void 0 : _a.push({
|
|
63
|
-
name: `${name}.${member.name}`,
|
|
64
|
-
label: member.label,
|
|
65
|
-
type: member.type.typeName,
|
|
66
|
-
});
|
|
67
|
-
}
|
|
68
|
-
else if (member.type.valueFormat === PropertyValueFormat.Struct) {
|
|
69
|
-
extractStructProperties(`${name}.${member.name}`, className, classToPropertiesMapping, member.type.members);
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
|
-
};
|
|
73
|
-
const extractProperties = (properties, classToPropertiesMapping, navigation) => {
|
|
74
|
-
var _a, _b;
|
|
75
|
-
for (const property of properties) {
|
|
76
|
-
switch (property.type.valueFormat) {
|
|
77
|
-
case PropertyValueFormat.Primitive: {
|
|
78
|
-
extractPrimitive(property, classToPropertiesMapping, navigation);
|
|
79
|
-
break;
|
|
80
|
-
}
|
|
81
|
-
// Get structs
|
|
82
|
-
case PropertyValueFormat.Struct: {
|
|
83
|
-
const nestedContentField = property;
|
|
84
|
-
// Only handling single path and not handling nested content fields within navigations
|
|
85
|
-
if (nestedContentField.pathToPrimaryClass &&
|
|
86
|
-
nestedContentField.pathToPrimaryClass.length > 1) {
|
|
87
|
-
break;
|
|
88
|
-
}
|
|
89
|
-
switch (nestedContentField.relationshipMeaning) {
|
|
90
|
-
case RelationshipMeaning.SameInstance: {
|
|
91
|
-
// Check for aspects. Ignore them if coming from navigation.
|
|
92
|
-
if (!navigation &&
|
|
93
|
-
(nestedContentField.pathToPrimaryClass[0].relationshipInfo
|
|
94
|
-
.name === "BisCore:ElementOwnsUniqueAspect" ||
|
|
95
|
-
nestedContentField.pathToPrimaryClass[0].relationshipInfo
|
|
96
|
-
.name === "BisCore:ElementOwnsMultiAspects")) {
|
|
97
|
-
const className = nestedContentField.contentClassInfo.name;
|
|
98
|
-
if (!classToPropertiesMapping.has(className)) {
|
|
99
|
-
classToPropertiesMapping.set(className, []);
|
|
100
|
-
}
|
|
101
|
-
extractProperties(nestedContentField.nestedFields, classToPropertiesMapping, navigation);
|
|
102
|
-
}
|
|
103
|
-
break;
|
|
104
|
-
}
|
|
105
|
-
// Navigation properties
|
|
106
|
-
case RelationshipMeaning.RelatedInstance: {
|
|
107
|
-
if (
|
|
108
|
-
// Deal with a TypeDefinition
|
|
109
|
-
nestedContentField.pathToPrimaryClass[0].relationshipInfo.name ===
|
|
110
|
-
"BisCore:GeometricElement3dHasTypeDefinition") {
|
|
111
|
-
const className = nestedContentField.pathToPrimaryClass[0].targetClassInfo.name;
|
|
112
|
-
extractProperties(nestedContentField.nestedFields, classToPropertiesMapping, {
|
|
113
|
-
navigationName: "TypeDefinition",
|
|
114
|
-
rootClassName: className,
|
|
115
|
-
});
|
|
116
|
-
// Hardcoded BisCore navigation properties for the type definition.
|
|
117
|
-
(_a = classToPropertiesMapping.get(className)) === null || _a === void 0 ? void 0 : _a.push({
|
|
118
|
-
name: "TypeDefinition.Model.ModeledElement.UserLabel",
|
|
119
|
-
label: "Model UserLabel (TypeDefinition)",
|
|
120
|
-
type: "string",
|
|
121
|
-
});
|
|
122
|
-
(_b = classToPropertiesMapping.get(className)) === null || _b === void 0 ? void 0 : _b.push({
|
|
123
|
-
name: "TypeDefinition.Model.ModeledElement.CodeValue",
|
|
124
|
-
label: "Model CodeValue (TypeDefinition)",
|
|
125
|
-
type: "string",
|
|
126
|
-
});
|
|
127
|
-
}
|
|
128
|
-
break;
|
|
129
|
-
}
|
|
130
|
-
default: {
|
|
131
|
-
// Some elements don't have a path to primary class or relationship meaning..
|
|
132
|
-
// Most likely a simple struct property
|
|
133
|
-
if (!nestedContentField.pathToPrimaryClass) {
|
|
134
|
-
const columnName = property.properties[0]
|
|
135
|
-
.property.name;
|
|
136
|
-
const className = property.properties[0]
|
|
137
|
-
.property.classInfo.name;
|
|
138
|
-
extractStructProperties(navigation
|
|
139
|
-
? `${navigation.navigationName}.${columnName}`
|
|
140
|
-
: columnName, navigation ? navigation.rootClassName : className, classToPropertiesMapping, property.type.members);
|
|
141
|
-
}
|
|
142
|
-
}
|
|
143
|
-
}
|
|
144
|
-
}
|
|
145
|
-
}
|
|
146
|
-
}
|
|
147
|
-
};
|
|
148
34
|
const GroupPropertyAction = ({ iModelId, mappingId, groupId, groupPropertyId, groupPropertyName, keySet, returnFn, }) => {
|
|
149
35
|
const iModelConnection = useActiveIModelConnection();
|
|
150
36
|
const { getAccessToken } = useGroupingMappingApiConfig();
|
|
@@ -152,117 +38,75 @@ const GroupPropertyAction = ({ iModelId, mappingId, groupId, groupPropertyId, gr
|
|
|
152
38
|
const [propertyName, setPropertyName] = useState("");
|
|
153
39
|
const [dataType, setDataType] = useState(DataType.Undefined);
|
|
154
40
|
const [quantityType, setQuantityType] = useState(QuantityType.Undefined);
|
|
155
|
-
const [
|
|
156
|
-
const [
|
|
41
|
+
const [selectedProperties, setSelectedProperties] = useState([]);
|
|
42
|
+
const [propertiesMetaData, setPropertiesMetaData] = useState([]);
|
|
43
|
+
const [propertiesNotFoundAlert, setPropertiesNotFoundAlert] = useState(false);
|
|
157
44
|
const [validator, showValidationMessage] = useValidator();
|
|
158
|
-
const [propertyAlert, setPropertyAlert] = useState(false);
|
|
159
45
|
const [isLoading, setIsLoading] = useState(false);
|
|
46
|
+
const [searchInput, setSearchInput] = useState("");
|
|
47
|
+
const [activeSearchInput, setActiveSearchInput] = useState("");
|
|
48
|
+
const [searched, setSearched] = useState(false);
|
|
49
|
+
const [activeDragProperty, setActiveDragProperty] = useState();
|
|
50
|
+
const sensors = useSensors(useSensor(PointerSensor), useSensor(KeyboardSensor, {
|
|
51
|
+
coordinateGetter: sortableKeyboardCoordinates,
|
|
52
|
+
}));
|
|
53
|
+
const [showModal, setShowModal] = useState(false);
|
|
54
|
+
const handleDragStart = useCallback((event) => {
|
|
55
|
+
const { active } = event;
|
|
56
|
+
const activeProperty = selectedProperties.find((p) => active.id === p.key);
|
|
57
|
+
setActiveDragProperty(activeProperty);
|
|
58
|
+
}, [selectedProperties]);
|
|
59
|
+
const handleDragEnd = useCallback((event) => {
|
|
60
|
+
const { active, over } = event;
|
|
61
|
+
if (over && (active.id !== over.id)) {
|
|
62
|
+
setSelectedProperties((items) => {
|
|
63
|
+
const oldIndex = selectedProperties.findIndex((p) => active.id === p.key);
|
|
64
|
+
const newIndex = selectedProperties.findIndex((p) => over.id === p.key);
|
|
65
|
+
return arrayMove(items, oldIndex, newIndex);
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
setActiveDragProperty(undefined);
|
|
69
|
+
}, [selectedProperties]);
|
|
70
|
+
const filteredProperties = useMemo(() => propertiesMetaData.filter((p) => [p.displayLabel, p.categoryLabel, p.actualECClassName]
|
|
71
|
+
.map((l) => l.toLowerCase())
|
|
72
|
+
.some((l) => l.includes(activeSearchInput.toLowerCase()))), [activeSearchInput, propertiesMetaData]);
|
|
160
73
|
useEffect(() => {
|
|
161
|
-
const
|
|
162
|
-
var _a
|
|
74
|
+
const generateProperties = async () => {
|
|
75
|
+
var _a;
|
|
163
76
|
setIsLoading(true);
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
specifications: [
|
|
170
|
-
{
|
|
171
|
-
specType: ContentSpecificationTypes.SelectedNodeInstances,
|
|
172
|
-
},
|
|
173
|
-
],
|
|
174
|
-
}
|
|
175
|
-
],
|
|
176
|
-
};
|
|
177
|
-
const requestOptions = {
|
|
178
|
-
imodel: iModelConnection,
|
|
179
|
-
keys: keySet,
|
|
180
|
-
rulesetOrId: ruleSet,
|
|
181
|
-
displayType: DefaultContentDisplayTypes.PropertyPane,
|
|
182
|
-
};
|
|
183
|
-
const content = await Presentation.presentation.getContentDescriptor(requestOptions);
|
|
184
|
-
// Only primitives and structs for now
|
|
185
|
-
const properties = (_a = content === null || content === void 0 ? void 0 : content.fields.filter((field) => field.type.valueFormat === PropertyValueFormat.Primitive ||
|
|
77
|
+
if (!iModelConnection)
|
|
78
|
+
return;
|
|
79
|
+
const descriptor = await fetchPresentationDescriptor(iModelConnection, keySet);
|
|
80
|
+
// Only allow primitives and structs
|
|
81
|
+
const propertyFields = (_a = descriptor === null || descriptor === void 0 ? void 0 : descriptor.fields.filter((field) => field.type.valueFormat === PropertyValueFormat.Primitive ||
|
|
186
82
|
field.type.valueFormat === PropertyValueFormat.Struct)) !== null && _a !== void 0 ? _a : [];
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
extractProperties(properties, classToPropertiesMapping);
|
|
190
|
-
const rootClassName = keySet.instanceKeys.keys().next().value;
|
|
191
|
-
// Hardcoded BisCore navigation properties.
|
|
192
|
-
(_b = classToPropertiesMapping.get(rootClassName)) === null || _b === void 0 ? void 0 : _b.push({
|
|
193
|
-
name: "Model.ModeledElement.UserLabel",
|
|
194
|
-
label: "Model UserLabel",
|
|
195
|
-
type: "string",
|
|
196
|
-
});
|
|
197
|
-
(_c = classToPropertiesMapping.get(rootClassName)) === null || _c === void 0 ? void 0 : _c.push({
|
|
198
|
-
name: "Model.ModeledElement.CodeValue",
|
|
199
|
-
label: "Model CodeValue",
|
|
200
|
-
type: "string",
|
|
201
|
-
});
|
|
202
|
-
(_d = classToPropertiesMapping.get(rootClassName)) === null || _d === void 0 ? void 0 : _d.push({
|
|
203
|
-
name: "Category.CodeValue",
|
|
204
|
-
label: "Category CodeValue",
|
|
205
|
-
type: "string",
|
|
206
|
-
});
|
|
207
|
-
(_e = classToPropertiesMapping.get(rootClassName)) === null || _e === void 0 ? void 0 : _e.push({
|
|
208
|
-
name: "Category.UserLabel",
|
|
209
|
-
label: "Category UserLabel",
|
|
210
|
-
type: "string",
|
|
211
|
-
});
|
|
212
|
-
setClassToPropertiesMapping(classToPropertiesMapping);
|
|
213
|
-
let newEcProperties;
|
|
214
|
-
// Fetch already existing ec properties then add all classes from presentation
|
|
83
|
+
const propertiesMetaData = convertPresentationFields(propertyFields);
|
|
84
|
+
setPropertiesMetaData(propertiesMetaData);
|
|
215
85
|
if (groupPropertyId) {
|
|
216
86
|
const accessToken = await getAccessToken();
|
|
217
87
|
let response;
|
|
218
88
|
try {
|
|
219
89
|
response = await mappingClient.getGroupProperty(accessToken, iModelId, mappingId, groupId, groupPropertyId);
|
|
90
|
+
setPropertyName(response.propertyName);
|
|
91
|
+
setDataType(response.dataType);
|
|
92
|
+
setQuantityType(response.quantityType);
|
|
93
|
+
const properties = findProperties(response.ecProperties, propertiesMetaData);
|
|
94
|
+
if (properties.length === 0) {
|
|
95
|
+
setPropertiesNotFoundAlert(true);
|
|
96
|
+
}
|
|
97
|
+
setSelectedProperties(properties);
|
|
220
98
|
}
|
|
221
99
|
catch (error) {
|
|
222
100
|
handleError(error.status);
|
|
223
101
|
}
|
|
224
|
-
if (!response) {
|
|
225
|
-
return;
|
|
226
|
-
}
|
|
227
|
-
newEcProperties = response.ecProperties;
|
|
228
|
-
let keys = Array.from(classToPropertiesMapping.keys()).reverse();
|
|
229
|
-
for (const ecProperty of newEcProperties) {
|
|
230
|
-
keys = keys.filter((key) => `${ecProperty.ecSchemaName}:${ecProperty.ecClassName}` !== key);
|
|
231
|
-
}
|
|
232
|
-
newEcProperties.push(...keys.map((key) => ({
|
|
233
|
-
ecSchemaName: key.split(":")[0],
|
|
234
|
-
ecClassName: key.split(":")[1],
|
|
235
|
-
// Placeholders for properties
|
|
236
|
-
ecPropertyName: "",
|
|
237
|
-
ecPropertyType: DataType.Undefined,
|
|
238
|
-
})));
|
|
239
|
-
setPropertyName(response.propertyName);
|
|
240
|
-
setDataType(response.dataType);
|
|
241
|
-
setQuantityType(response.quantityType);
|
|
242
102
|
}
|
|
243
|
-
else {
|
|
244
|
-
newEcProperties = Array.from(classToPropertiesMapping)
|
|
245
|
-
.map(([key]) => ({
|
|
246
|
-
ecSchemaName: key.split(":")[0],
|
|
247
|
-
ecClassName: key.split(":")[1],
|
|
248
|
-
// Placeholders for properties
|
|
249
|
-
ecPropertyName: "",
|
|
250
|
-
ecPropertyType: DataType.Undefined,
|
|
251
|
-
}))
|
|
252
|
-
.reverse();
|
|
253
|
-
}
|
|
254
|
-
setEcProperties(newEcProperties);
|
|
255
103
|
setIsLoading(false);
|
|
256
104
|
};
|
|
257
|
-
void
|
|
105
|
+
void generateProperties();
|
|
258
106
|
}, [getAccessToken, mappingClient, groupId, groupPropertyId, iModelConnection, iModelId, keySet, mappingId]);
|
|
259
107
|
const onSave = async () => {
|
|
260
|
-
|
|
261
|
-
if (!filteredEcProperties.length || !validator.allValid()) {
|
|
108
|
+
if (!validator.allValid()) {
|
|
262
109
|
showValidationMessage(true);
|
|
263
|
-
if (!filteredEcProperties.length) {
|
|
264
|
-
setPropertyAlert(true);
|
|
265
|
-
}
|
|
266
110
|
return;
|
|
267
111
|
}
|
|
268
112
|
try {
|
|
@@ -272,7 +116,7 @@ const GroupPropertyAction = ({ iModelId, mappingId, groupId, groupPropertyId, gr
|
|
|
272
116
|
propertyName,
|
|
273
117
|
dataType,
|
|
274
118
|
quantityType,
|
|
275
|
-
ecProperties:
|
|
119
|
+
ecProperties: selectedProperties.map((p) => convertToECProperties(p)).flat(),
|
|
276
120
|
};
|
|
277
121
|
groupPropertyId
|
|
278
122
|
? await mappingClient.updateGroupProperty(accessToken, iModelId, mappingId, groupId, groupPropertyId, groupProperty)
|
|
@@ -284,52 +128,29 @@ const GroupPropertyAction = ({ iModelId, mappingId, groupId, groupPropertyId, gr
|
|
|
284
128
|
setIsLoading(false);
|
|
285
129
|
}
|
|
286
130
|
};
|
|
287
|
-
const
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
type = DataType.Integer;
|
|
298
|
-
break;
|
|
299
|
-
default:
|
|
300
|
-
type = property.type;
|
|
301
|
-
}
|
|
302
|
-
updatedEcProperties[index].ecPropertyType = type;
|
|
303
|
-
return updatedEcProperties;
|
|
304
|
-
});
|
|
131
|
+
const startSearch = useCallback(() => {
|
|
132
|
+
if (!searchInput)
|
|
133
|
+
return;
|
|
134
|
+
setActiveSearchInput(searchInput);
|
|
135
|
+
setSearched(true);
|
|
136
|
+
}, [searchInput]);
|
|
137
|
+
const clearSearch = useCallback(() => {
|
|
138
|
+
setSearchInput("");
|
|
139
|
+
setActiveSearchInput("");
|
|
140
|
+
setSearched(false);
|
|
305
141
|
}, []);
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
}),
|
|
314
|
-
label: property.label,
|
|
315
|
-
}))) !== null && _b !== void 0 ? _b : [];
|
|
316
|
-
});
|
|
317
|
-
}, [classToPropertiesMapping, ecProperties]);
|
|
318
|
-
const getValue = useCallback((ecProperty, index) => {
|
|
319
|
-
var _a;
|
|
320
|
-
const property = (_a = classToPropertiesMapping === null || classToPropertiesMapping === void 0 ? void 0 : classToPropertiesMapping.get(`${ecProperty.ecSchemaName}:${ecProperty.ecClassName}`)) === null || _a === void 0 ? void 0 : _a.find((property) => property.name === ecProperties[index].ecPropertyName);
|
|
321
|
-
const result = JSON.stringify({
|
|
322
|
-
name: property === null || property === void 0 ? void 0 : property.name,
|
|
323
|
-
type: property === null || property === void 0 ? void 0 : property.type,
|
|
324
|
-
});
|
|
325
|
-
return result;
|
|
326
|
-
}, [classToPropertiesMapping, ecProperties]);
|
|
327
|
-
return (React.createElement(React.Fragment, null,
|
|
142
|
+
useEffect(() => {
|
|
143
|
+
if (searchInput.length === 0) {
|
|
144
|
+
setSearched(false);
|
|
145
|
+
clearSearch();
|
|
146
|
+
}
|
|
147
|
+
}, [searchInput, setSearched, clearSearch]);
|
|
148
|
+
return (React.createElement(DndContext, { sensors: sensors, collisionDetection: closestCenter, onDragStart: handleDragStart, onDragEnd: handleDragEnd },
|
|
328
149
|
React.createElement(WidgetHeader, { title: groupPropertyName !== null && groupPropertyName !== void 0 ? groupPropertyName : "Add Property", returnFn: async () => returnFn(false) }),
|
|
329
150
|
React.createElement("div", { className: 'gmw-group-property-action-container' },
|
|
330
|
-
React.createElement(Fieldset, { className: 'gmw-property-options', legend: 'Property Details' },
|
|
151
|
+
React.createElement(Fieldset, { disabled: isLoading, className: 'gmw-property-options', legend: 'Property Details' },
|
|
331
152
|
React.createElement(Small, { className: 'gmw-field-legend' }, "Asterisk * indicates mandatory fields."),
|
|
332
|
-
React.createElement(LabeledInput, { id: 'propertyName', label: 'Property Name', value: propertyName, required: true,
|
|
153
|
+
React.createElement(LabeledInput, { id: 'propertyName', label: 'Property Name', value: propertyName, required: true, onChange: (event) => {
|
|
333
154
|
setPropertyName(event.target.value);
|
|
334
155
|
validator.showMessageFor("propertyName");
|
|
335
156
|
}, message: validator.message("propertyName", propertyName, NAME_REQUIREMENTS), status: validator.message("propertyName", propertyName, NAME_REQUIREMENTS)
|
|
@@ -337,7 +158,7 @@ const GroupPropertyAction = ({ iModelId, mappingId, groupId, groupPropertyId, gr
|
|
|
337
158
|
: undefined, onBlur: () => {
|
|
338
159
|
validator.showMessageFor("propertyName");
|
|
339
160
|
} }),
|
|
340
|
-
React.createElement(LabeledSelect, { label: "Data Type", id: 'dataType',
|
|
161
|
+
React.createElement(LabeledSelect, { label: "Data Type", id: 'dataType', options: [
|
|
341
162
|
{ value: DataType.Boolean, label: "Boolean" },
|
|
342
163
|
{ value: DataType.Number, label: "Number" },
|
|
343
164
|
{ value: DataType.String, label: "String" },
|
|
@@ -349,45 +170,71 @@ const GroupPropertyAction = ({ iModelId, mappingId, groupId, groupPropertyId, gr
|
|
|
349
170
|
: undefined, onBlur: () => {
|
|
350
171
|
validator.showMessageFor("dataType");
|
|
351
172
|
}, onShow: () => { }, onHide: () => { } }),
|
|
352
|
-
React.createElement(LabeledSelect, { label: 'Quantity Type',
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
React.createElement(Text,
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
React.createElement(
|
|
389
|
-
|
|
390
|
-
|
|
173
|
+
React.createElement(LabeledSelect, { label: 'Quantity Type', options: quantityTypesSelectionOptions, value: quantityType, onChange: setQuantityType, onShow: () => { }, onHide: () => { } })),
|
|
174
|
+
propertiesNotFoundAlert &&
|
|
175
|
+
React.createElement(Alert, { type: "warning" }, "Warning: Could not match saved properties from the current generated list. It does not confirm or deny validity. Overwriting will occur if a new selection is made and saved."),
|
|
176
|
+
React.createElement(Fieldset, { className: 'gmw-property-view-container', legend: "Mapped Properties" },
|
|
177
|
+
React.createElement("div", { className: "gmw-property-view-button" },
|
|
178
|
+
React.createElement(Button, { onClick: async () => setShowModal(true), disabled: isLoading }, "Select Properties")),
|
|
179
|
+
React.createElement("div", { className: "gmw-properties-list" }, selectedProperties.length === 0 && !isLoading ?
|
|
180
|
+
React.createElement("div", { className: "gmw-empty-selection" },
|
|
181
|
+
React.createElement(Text, null, "No properties selected."),
|
|
182
|
+
React.createElement(Text, null, "Press the \"Select Properties\" button for options.")) :
|
|
183
|
+
selectedProperties.map((property) => (React.createElement(HorizontalTile, { key: property.key, title: `${property.displayLabel} (${property.propertyType})`, titleTooltip: `${property.actualECClassName}`, subText: property.categoryLabel, actionGroup: null })))))),
|
|
184
|
+
React.createElement(ActionPanel, { onSave: onSave, onCancel: async () => returnFn(false), isLoading: isLoading, isSavingDisabled: selectedProperties.length === 0 || !propertyName || !dataType }),
|
|
185
|
+
React.createElement(Modal, { title: "Properties Selection", isOpen: showModal, onClose: () => {
|
|
186
|
+
setShowModal(false);
|
|
187
|
+
clearSearch();
|
|
188
|
+
}, closeOnExternalClick: false },
|
|
189
|
+
React.createElement(Split, { expandToMin: false, className: "gmw-property-selection-container", gutterAlign: "center", gutterSize: 2, gutter: () => {
|
|
190
|
+
// Expects HTMLElement
|
|
191
|
+
const dragHangle = renderToStaticMarkup(React.createElement("div", { className: "gmw-gutter-drag-icon" },
|
|
192
|
+
React.createElement(SvgMoreVerticalSmall, null)));
|
|
193
|
+
const gutter = document.createElement("div");
|
|
194
|
+
gutter.className = `gmw-gutter`;
|
|
195
|
+
gutter.innerHTML = dragHangle;
|
|
196
|
+
return gutter;
|
|
197
|
+
}, direction: "horizontal" },
|
|
198
|
+
React.createElement(Surface, { className: "gmw-available-properties", elevation: 1 },
|
|
199
|
+
React.createElement("div", { className: "gmw-available-properties-header" },
|
|
200
|
+
React.createElement(Label, { as: "span" }, "Available Properties"),
|
|
201
|
+
React.createElement(LabeledInput, { displayStyle: "inline", iconDisplayStyle: "inline", className: "gmw-available-prop-search", value: searchInput, size: "small", placeholder: "Search....", onChange: (event) => {
|
|
202
|
+
const { target: { value }, } = event;
|
|
203
|
+
setSearchInput(value);
|
|
204
|
+
}, onKeyDown: (event) => {
|
|
205
|
+
if (event.key === "Enter") {
|
|
206
|
+
startSearch();
|
|
207
|
+
}
|
|
208
|
+
}, svgIcon: searched ? (React.createElement(IconButton, { onClick: clearSearch, styleType: "borderless" },
|
|
209
|
+
React.createElement(SvgClose, null))) : (React.createElement(IconButton, { onClick: startSearch, styleType: "borderless" },
|
|
210
|
+
React.createElement(SvgSearch, null))) })),
|
|
211
|
+
filteredProperties.length === 0 ?
|
|
212
|
+
React.createElement("div", { className: "gmw-empty-selection" },
|
|
213
|
+
React.createElement(Text, null, "No properties available. ")) :
|
|
214
|
+
React.createElement("div", { className: "gmw-properties-list" }, filteredProperties.map((property) => (React.createElement(HorizontalTile, { key: property.key, title: `${property.displayLabel} (${property.propertyType})`, titleTooltip: `${property.actualECClassName}`, subText: property.categoryLabel, actionGroup: null, selected: selectedProperties.some((p) => property.key === p.key), onClick: () => setSelectedProperties((sp) => sp.some((p) => property.key === p.key)
|
|
215
|
+
? sp.filter((p) => property.key !== p.key)
|
|
216
|
+
: [...sp, property]) }))))),
|
|
217
|
+
React.createElement(Surface, { className: "gmw-selected-properties", elevation: 1 },
|
|
218
|
+
React.createElement(Label, { as: "span" }, "Selected Properties"),
|
|
219
|
+
selectedProperties.length === 0 ?
|
|
220
|
+
React.createElement("div", { className: "gmw-empty-selection" },
|
|
221
|
+
React.createElement(Text, null, "No properties selected."),
|
|
222
|
+
React.createElement(Text, null, "Add some by clicking on the properties shown left.")) :
|
|
223
|
+
React.createElement("div", { className: "gmw-properties-list" },
|
|
224
|
+
React.createElement(SortableContext, { items: selectedProperties.map((p) => p.key), strategy: verticalListSortingStrategy }, selectedProperties.map((property) => React.createElement(SortableHorizontalTile, { key: property.key, id: property.key, title: `${property.displayLabel} (${property.propertyType})`, titleTooltip: `${property.actualECClassName}`, subText: property.categoryLabel, actionGroup: React.createElement("div", null,
|
|
225
|
+
React.createElement(IconButton, { styleType: "borderless", title: "Remove", onClick: () => {
|
|
226
|
+
setSelectedProperties((sp) => sp.filter((p) => property.key !== p.key));
|
|
227
|
+
} },
|
|
228
|
+
React.createElement(SvgRemove, null))) })))))),
|
|
229
|
+
React.createElement(ModalButtonBar, null,
|
|
230
|
+
React.createElement(Button, { onClick: () => {
|
|
231
|
+
setShowModal(false);
|
|
232
|
+
clearSearch();
|
|
233
|
+
}, styleType: "high-visibility" }, "Close"))),
|
|
234
|
+
React.createElement(DragOverlay, { zIndex: 9999 }, activeDragProperty ?
|
|
235
|
+
React.createElement(HorizontalTile, { title: `${activeDragProperty.displayLabel} (${activeDragProperty.propertyType})`, titleTooltip: `${activeDragProperty.actualECClassName}`, subText: activeDragProperty.categoryLabel, actionGroup: React.createElement(IconButton, { styleType: "borderless" },
|
|
236
|
+
React.createElement(SvgRemove, null)), dragHandle: React.createElement("div", { className: "gmw-drag-icon" },
|
|
237
|
+
React.createElement(SvgDragHandleVertical, null)) }) : null)));
|
|
391
238
|
};
|
|
392
239
|
export default GroupPropertyAction;
|
|
393
240
|
//# sourceMappingURL=GroupPropertyAction.js.map
|