@itwin/grouping-mapping-widget 0.6.0 → 0.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +84 -0
- package/lib/cjs/grouping-mapping-widget.d.ts +1 -0
- package/lib/cjs/grouping-mapping-widget.js +3 -1
- package/lib/cjs/grouping-mapping-widget.js.map +1 -1
- package/lib/cjs/test/GroupingMappingCustomUI.test.d.ts +2 -0
- package/lib/cjs/test/GroupingMappingCustomUI.test.js +162 -0
- package/lib/cjs/test/GroupingMappingCustomUI.test.js.map +1 -0
- package/lib/cjs/test/WidgetHeader.test.d.ts +2 -0
- package/lib/cjs/test/WidgetHeader.test.js +36 -0
- package/lib/cjs/test/WidgetHeader.test.js.map +1 -0
- package/lib/cjs/test/test-utils.d.ts +72 -0
- package/lib/cjs/test/test-utils.js +71 -0
- package/lib/cjs/test/test-utils.js.map +1 -0
- package/lib/cjs/widget/components/GroupAction.d.ts +2 -1
- package/lib/cjs/widget/components/GroupAction.js +82 -75
- package/lib/cjs/widget/components/GroupAction.js.map +1 -1
- package/lib/cjs/widget/components/GroupAction.scss +1 -13
- package/lib/cjs/widget/components/Grouping.d.ts +5 -0
- package/lib/cjs/widget/components/Grouping.js +107 -44
- package/lib/cjs/widget/components/Grouping.js.map +1 -1
- package/lib/cjs/widget/components/Grouping.scss +18 -3
- package/lib/cjs/widget/components/GroupingMapping.d.ts +6 -1
- package/lib/cjs/widget/components/GroupingMapping.js +22 -9
- package/lib/cjs/widget/components/GroupingMapping.js.map +1 -1
- package/lib/cjs/widget/components/Mapping.scss +4 -5
- package/lib/cjs/widget/components/context/GroupingMappingCustomUIContext.d.ts +6 -0
- package/lib/cjs/widget/components/context/GroupingMappingCustomUIContext.js +25 -0
- package/lib/cjs/widget/components/context/GroupingMappingCustomUIContext.js.map +1 -0
- package/lib/cjs/widget/components/customUI/GroupingMappingCustomUI.d.ts +91 -0
- package/lib/cjs/widget/components/customUI/GroupingMappingCustomUI.js +9 -0
- package/lib/cjs/widget/components/customUI/GroupingMappingCustomUI.js.map +1 -0
- package/lib/cjs/widget/components/customUI/ManualGroupingCustomUI.d.ts +6 -0
- package/lib/cjs/widget/components/customUI/ManualGroupingCustomUI.js +31 -0
- package/lib/cjs/widget/components/customUI/ManualGroupingCustomUI.js.map +1 -0
- package/lib/cjs/widget/components/customUI/ManualGroupingCustomUI.scss +17 -0
- package/lib/cjs/widget/components/customUI/SearchGroupingCustomUI.d.ts +6 -0
- package/lib/cjs/widget/components/customUI/SearchGroupingCustomUI.js +97 -0
- package/lib/cjs/widget/components/customUI/SearchGroupingCustomUI.js.map +1 -0
- package/lib/cjs/widget/components/customUI/SearchGroupingCustomUI.scss +17 -0
- package/lib/esm/grouping-mapping-widget.d.ts +1 -0
- package/lib/esm/grouping-mapping-widget.js +1 -0
- package/lib/esm/grouping-mapping-widget.js.map +1 -1
- package/lib/esm/test/GroupingMappingCustomUI.test.d.ts +2 -0
- package/lib/esm/test/GroupingMappingCustomUI.test.js +138 -0
- package/lib/esm/test/GroupingMappingCustomUI.test.js.map +1 -0
- package/lib/esm/test/WidgetHeader.test.d.ts +2 -0
- package/lib/esm/test/WidgetHeader.test.js +31 -0
- package/lib/esm/test/WidgetHeader.test.js.map +1 -0
- package/lib/esm/test/test-utils.d.ts +72 -0
- package/lib/esm/test/test-utils.js +42 -0
- package/lib/esm/test/test-utils.js.map +1 -0
- package/lib/esm/widget/components/GroupAction.d.ts +2 -1
- package/lib/esm/widget/components/GroupAction.js +85 -78
- package/lib/esm/widget/components/GroupAction.js.map +1 -1
- package/lib/esm/widget/components/GroupAction.scss +1 -13
- package/lib/esm/widget/components/Grouping.d.ts +5 -0
- package/lib/esm/widget/components/Grouping.js +107 -44
- package/lib/esm/widget/components/Grouping.js.map +1 -1
- package/lib/esm/widget/components/Grouping.scss +18 -3
- package/lib/esm/widget/components/GroupingMapping.d.ts +6 -1
- package/lib/esm/widget/components/GroupingMapping.js +23 -10
- package/lib/esm/widget/components/GroupingMapping.js.map +1 -1
- package/lib/esm/widget/components/Mapping.scss +4 -5
- package/lib/esm/widget/components/context/GroupingMappingCustomUIContext.d.ts +6 -0
- package/lib/esm/widget/components/context/GroupingMappingCustomUIContext.js +20 -0
- package/lib/esm/widget/components/context/GroupingMappingCustomUIContext.js.map +1 -0
- package/lib/esm/widget/components/customUI/GroupingMappingCustomUI.d.ts +91 -0
- package/lib/esm/widget/components/customUI/GroupingMappingCustomUI.js +6 -0
- package/lib/esm/widget/components/customUI/GroupingMappingCustomUI.js.map +1 -0
- package/lib/esm/widget/components/customUI/ManualGroupingCustomUI.d.ts +6 -0
- package/lib/esm/widget/components/customUI/ManualGroupingCustomUI.js +26 -0
- package/lib/esm/widget/components/customUI/ManualGroupingCustomUI.js.map +1 -0
- package/lib/esm/widget/components/customUI/ManualGroupingCustomUI.scss +17 -0
- package/lib/esm/widget/components/customUI/SearchGroupingCustomUI.d.ts +6 -0
- package/lib/esm/widget/components/customUI/SearchGroupingCustomUI.js +92 -0
- package/lib/esm/widget/components/customUI/SearchGroupingCustomUI.js.map +1 -0
- package/lib/esm/widget/components/customUI/SearchGroupingCustomUI.scss +17 -0
- package/package.json +17 -3
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.useGroupingMappingCustomUI = exports.GroupingMappingCustomUIContext = exports.createGroupingMappingCustomUI = void 0;
|
|
4
|
+
/*---------------------------------------------------------------------------------------------
|
|
5
|
+
* Copyright (c) Bentley Systems, Incorporated. All rights reserved.
|
|
6
|
+
* See LICENSE.md in the project root for license terms and full copyright notice.
|
|
7
|
+
*--------------------------------------------------------------------------------------------*/
|
|
8
|
+
const react_1 = require("react");
|
|
9
|
+
const createGroupingMappingCustomUI = (customUIs) => {
|
|
10
|
+
if (undefined === customUIs) {
|
|
11
|
+
return [];
|
|
12
|
+
}
|
|
13
|
+
return customUIs;
|
|
14
|
+
};
|
|
15
|
+
exports.createGroupingMappingCustomUI = createGroupingMappingCustomUI;
|
|
16
|
+
exports.GroupingMappingCustomUIContext = react_1.createContext([]);
|
|
17
|
+
const useGroupingMappingCustomUI = () => {
|
|
18
|
+
const context = react_1.useContext(exports.GroupingMappingCustomUIContext);
|
|
19
|
+
if (!context) {
|
|
20
|
+
throw new Error("useGroupingMappingCustomUI should be used within a GroupingMappingCustomUIContext provider");
|
|
21
|
+
}
|
|
22
|
+
return context;
|
|
23
|
+
};
|
|
24
|
+
exports.useGroupingMappingCustomUI = useGroupingMappingCustomUI;
|
|
25
|
+
//# sourceMappingURL=GroupingMappingCustomUIContext.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"GroupingMappingCustomUIContext.js","sourceRoot":"","sources":["../../../../../src/widget/components/context/GroupingMappingCustomUIContext.ts"],"names":[],"mappings":";;;AAAA;;;+FAG+F;AAC/F,iCAAkD;AAG3C,MAAM,6BAA6B,GAAG,CAC3C,SAAgD,EACrB,EAAE;IAC7B,IAAI,SAAS,KAAK,SAAS,EAAE;QAC3B,OAAO,EAAE,CAAC;KACX;IACD,OAAO,SAAS,CAAC;AACnB,CAAC,CAAC;AAPW,QAAA,6BAA6B,iCAOxC;AAEW,QAAA,8BAA8B,GAAG,qBAAa,CAA4B,EAAE,CAAC,CAAC;AAEpF,MAAM,0BAA0B,GAAG,GAAG,EAAE;IAC7C,MAAM,OAAO,GAAG,kBAAU,CAAC,sCAA8B,CAAC,CAAC;IAC3D,IAAI,CAAC,OAAO,EAAE;QACZ,MAAM,IAAI,KAAK,CACb,4FAA4F,CAC7F,CAAC;KACH;IACD,OAAO,OAAO,CAAC;AACjB,CAAC,CAAC;AARW,QAAA,0BAA0B,8BAQrC","sourcesContent":["/*---------------------------------------------------------------------------------------------\n* Copyright (c) Bentley Systems, Incorporated. All rights reserved.\n* See LICENSE.md in the project root for license terms and full copyright notice.\n*--------------------------------------------------------------------------------------------*/\nimport { createContext, useContext } from \"react\";\nimport type { GroupingMappingCustomUI } from \"../customUI/GroupingMappingCustomUI\";\n\nexport const createGroupingMappingCustomUI = (\n customUIs: GroupingMappingCustomUI[] | undefined,\n): GroupingMappingCustomUI[] => {\n if (undefined === customUIs) {\n return [];\n }\n return customUIs;\n};\n\nexport const GroupingMappingCustomUIContext = createContext<GroupingMappingCustomUI[]>([]);\n\nexport const useGroupingMappingCustomUI = () => {\n const context = useContext(GroupingMappingCustomUIContext);\n if (!context) {\n throw new Error(\n \"useGroupingMappingCustomUI should be used within a GroupingMappingCustomUIContext provider\",\n );\n }\n return context;\n};\n"]}
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import type { ReactElement } from "react";
|
|
2
|
+
export declare enum GroupingMappingCustomUIType {
|
|
3
|
+
Grouping = 0,
|
|
4
|
+
Context = 1
|
|
5
|
+
}
|
|
6
|
+
export declare type GroupingMappingCustomUI = GroupingCustomUI | ContextCustomUI;
|
|
7
|
+
/** Custom UI Definitions. */
|
|
8
|
+
export interface IGroupingMappingCustomUI {
|
|
9
|
+
/**
|
|
10
|
+
* See GroupingMappingCustomUIType.
|
|
11
|
+
*/
|
|
12
|
+
type: GroupingMappingCustomUIType;
|
|
13
|
+
/**
|
|
14
|
+
* Unique identifier of the custom UI.
|
|
15
|
+
*/
|
|
16
|
+
name: string;
|
|
17
|
+
/**
|
|
18
|
+
* Display label in the widget.
|
|
19
|
+
*/
|
|
20
|
+
displayLabel: string;
|
|
21
|
+
/**
|
|
22
|
+
* Optional icon, will be shown before display label in widget.
|
|
23
|
+
*/
|
|
24
|
+
icon?: ReactElement;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Context custom UI type definition.
|
|
28
|
+
*/
|
|
29
|
+
export interface ContextCustomUI extends IGroupingMappingCustomUI {
|
|
30
|
+
/**
|
|
31
|
+
* See GroupingMappingCustomUIType.
|
|
32
|
+
*/
|
|
33
|
+
type: GroupingMappingCustomUIType.Context;
|
|
34
|
+
/**
|
|
35
|
+
* User defined component for UI interaction with grouping mapping widget.
|
|
36
|
+
*/
|
|
37
|
+
uiComponent?: (props: ContextCustomUIProps) => JSX.Element;
|
|
38
|
+
/**
|
|
39
|
+
* Callback function for context custom UI menu item click event.
|
|
40
|
+
*/
|
|
41
|
+
onClick?: (groupId: string, mappingId: string, iModelId: string) => void;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Group custom UI type definition.
|
|
45
|
+
*/
|
|
46
|
+
export interface GroupingCustomUI extends IGroupingMappingCustomUI {
|
|
47
|
+
/**
|
|
48
|
+
* See GroupingMappingCustomUIType.
|
|
49
|
+
*/
|
|
50
|
+
type: GroupingMappingCustomUIType.Grouping;
|
|
51
|
+
/**
|
|
52
|
+
* Custom UI Component to build query interactively. Refer to SearchGroupingCustomUI/ManualGroupingCustomUI.
|
|
53
|
+
*/
|
|
54
|
+
uiComponent: (props: GroupingCustomUIProps) => JSX.Element;
|
|
55
|
+
}
|
|
56
|
+
/** Custom UI Component props definitions. */
|
|
57
|
+
/**
|
|
58
|
+
* Context custom UI component arguments definition.
|
|
59
|
+
*/
|
|
60
|
+
export interface ContextCustomUIProps {
|
|
61
|
+
/**
|
|
62
|
+
* IModel Id.
|
|
63
|
+
*/
|
|
64
|
+
iModelId: string;
|
|
65
|
+
/**
|
|
66
|
+
* Mapping Id.
|
|
67
|
+
*/
|
|
68
|
+
mappingId: string;
|
|
69
|
+
/**
|
|
70
|
+
* Group Id.
|
|
71
|
+
*/
|
|
72
|
+
groupId: string;
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Group custom UI component arguments definition.
|
|
76
|
+
*/
|
|
77
|
+
export interface GroupingCustomUIProps {
|
|
78
|
+
/**
|
|
79
|
+
* To validate and update current query.
|
|
80
|
+
*/
|
|
81
|
+
updateQuery: (query: string) => void;
|
|
82
|
+
/**
|
|
83
|
+
* To get the query loading status.
|
|
84
|
+
*/
|
|
85
|
+
isUpdating?: boolean;
|
|
86
|
+
/**
|
|
87
|
+
* To reset the viewer.
|
|
88
|
+
*/
|
|
89
|
+
resetView?: () => Promise<void>;
|
|
90
|
+
}
|
|
91
|
+
//# sourceMappingURL=GroupingMappingCustomUI.d.ts.map
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.GroupingMappingCustomUIType = void 0;
|
|
4
|
+
var GroupingMappingCustomUIType;
|
|
5
|
+
(function (GroupingMappingCustomUIType) {
|
|
6
|
+
GroupingMappingCustomUIType[GroupingMappingCustomUIType["Grouping"] = 0] = "Grouping";
|
|
7
|
+
GroupingMappingCustomUIType[GroupingMappingCustomUIType["Context"] = 1] = "Context";
|
|
8
|
+
})(GroupingMappingCustomUIType = exports.GroupingMappingCustomUIType || (exports.GroupingMappingCustomUIType = {}));
|
|
9
|
+
//# sourceMappingURL=GroupingMappingCustomUI.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"GroupingMappingCustomUI.js","sourceRoot":"","sources":["../../../../../src/widget/components/customUI/GroupingMappingCustomUI.ts"],"names":[],"mappings":";;;AAMA,IAAY,2BAGX;AAHD,WAAY,2BAA2B;IACrC,qFAAQ,CAAA;IACR,mFAAO,CAAA;AACT,CAAC,EAHW,2BAA2B,GAA3B,mCAA2B,KAA3B,mCAA2B,QAGtC","sourcesContent":["/*---------------------------------------------------------------------------------------------\n* Copyright (c) Bentley Systems, Incorporated. All rights reserved.\n* See LICENSE.md in the project root for license terms and full copyright notice.\n*--------------------------------------------------------------------------------------------*/\nimport type { ReactElement } from \"react\";\n\nexport enum GroupingMappingCustomUIType {\n Grouping,\n Context,\n}\n\nexport type GroupingMappingCustomUI = GroupingCustomUI | ContextCustomUI;\n\n/** Custom UI Definitions. */\n\nexport interface IGroupingMappingCustomUI {\n /**\n * See GroupingMappingCustomUIType.\n */\n type: GroupingMappingCustomUIType;\n /**\n * Unique identifier of the custom UI.\n */\n name: string;\n /**\n * Display label in the widget.\n */\n displayLabel: string;\n /**\n * Optional icon, will be shown before display label in widget.\n */\n icon?: ReactElement;\n}\n\n/**\n * Context custom UI type definition.\n */\nexport interface ContextCustomUI extends IGroupingMappingCustomUI {\n /**\n * See GroupingMappingCustomUIType.\n */\n type: GroupingMappingCustomUIType.Context;\n /**\n * User defined component for UI interaction with grouping mapping widget.\n */\n uiComponent?: (props: ContextCustomUIProps) => JSX.Element;\n /**\n * Callback function for context custom UI menu item click event.\n */\n onClick?: (groupId: string, mappingId: string, iModelId: string) => void;\n}\n\n/**\n * Group custom UI type definition.\n */\nexport interface GroupingCustomUI extends IGroupingMappingCustomUI {\n /**\n * See GroupingMappingCustomUIType.\n */\n type: GroupingMappingCustomUIType.Grouping;\n /**\n * Custom UI Component to build query interactively. Refer to SearchGroupingCustomUI/ManualGroupingCustomUI.\n */\n uiComponent: (props: GroupingCustomUIProps) => JSX.Element;\n}\n\n/** Custom UI Component props definitions. */\n\n/**\n * Context custom UI component arguments definition.\n */\nexport interface ContextCustomUIProps {\n /**\n * IModel Id.\n */\n iModelId: string;\n /**\n * Mapping Id.\n */\n mappingId: string;\n /**\n * Group Id.\n */\n groupId: string;\n}\n\n/**\n * Group custom UI component arguments definition.\n */\nexport interface GroupingCustomUIProps {\n /**\n * To validate and update current query.\n */\n updateQuery: (query: string) => void;\n /**\n * To get the query loading status.\n */\n isUpdating?: boolean;\n /**\n * To reset the viewer.\n */\n resetView?: () => Promise<void>;\n}\n"]}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/// <reference types="react" />
|
|
2
|
+
import "./ManualGroupingCustomUI.scss";
|
|
3
|
+
import type { GroupingCustomUIProps } from "./GroupingMappingCustomUI";
|
|
4
|
+
declare const ManualGroupingCustomUI: ({ updateQuery, isUpdating, resetView, }: GroupingCustomUIProps) => JSX.Element;
|
|
5
|
+
export default ManualGroupingCustomUI;
|
|
6
|
+
//# sourceMappingURL=ManualGroupingCustomUI.d.ts.map
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
/*---------------------------------------------------------------------------------------------
|
|
7
|
+
* Copyright (c) Bentley Systems, Incorporated. All rights reserved.
|
|
8
|
+
* See LICENSE.md in the project root for license terms and full copyright notice.
|
|
9
|
+
*--------------------------------------------------------------------------------------------*/
|
|
10
|
+
const react_1 = __importDefault(require("react"));
|
|
11
|
+
const itwinui_react_1 = require("@itwin/itwinui-react");
|
|
12
|
+
const utils_1 = require("../utils");
|
|
13
|
+
require("./ManualGroupingCustomUI.scss");
|
|
14
|
+
const ManualGroupingCustomUI = ({ updateQuery, isUpdating, resetView, }) => {
|
|
15
|
+
const [manualInput, setManualInput] = react_1.default.useState("");
|
|
16
|
+
return (react_1.default.createElement("div", { className: 'gmw-manual-form' },
|
|
17
|
+
react_1.default.createElement(itwinui_react_1.Text, null, "Generate group using an ECSQL query. Please select ECInstanceId and ECClassId columns in the query."),
|
|
18
|
+
react_1.default.createElement(itwinui_react_1.LabeledTextarea, { label: 'Query', required: true, value: manualInput, onChange: (event) => setManualInput(event.target.value), disabled: isUpdating, placeholder: `E.g. "SELECT ECInstanceId, ECClassId FROM BisCore:PhysicalElement"` }),
|
|
19
|
+
react_1.default.createElement("div", { className: 'gmw-manual-actions' },
|
|
20
|
+
isUpdating && react_1.default.createElement(utils_1.LoadingSpinner, null),
|
|
21
|
+
react_1.default.createElement(itwinui_react_1.Button, { disabled: isUpdating, onClick: () => updateQuery(manualInput) }, "Apply"),
|
|
22
|
+
react_1.default.createElement(itwinui_react_1.Button, { disabled: isUpdating, onClick: async () => {
|
|
23
|
+
updateQuery("");
|
|
24
|
+
setManualInput("");
|
|
25
|
+
if (resetView) {
|
|
26
|
+
await resetView();
|
|
27
|
+
}
|
|
28
|
+
} }, "Clear"))));
|
|
29
|
+
};
|
|
30
|
+
exports.default = ManualGroupingCustomUI;
|
|
31
|
+
//# sourceMappingURL=ManualGroupingCustomUI.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ManualGroupingCustomUI.js","sourceRoot":"","sources":["../../../../../src/widget/components/customUI/ManualGroupingCustomUI.tsx"],"names":[],"mappings":";;;;;AAAA;;;+FAG+F;AAC/F,kDAA0B;AAC1B,wDAAqE;AACrE,oCAA0C;AAC1C,yCAAuC;AAGvC,MAAM,sBAAsB,GAAG,CAAC,EAC9B,WAAW,EACX,UAAU,EACV,SAAS,GACa,EAAE,EAAE;IAC1B,MAAM,CAAC,WAAW,EAAE,cAAc,CAAC,GAAG,eAAK,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;IAEzD,OAAO,CACL,uCAAK,SAAS,EAAC,iBAAiB;QAC9B,8BAAC,oBAAI,8GAEE;QACP,8BAAC,+BAAe,IACd,KAAK,EAAC,OAAO,EACb,QAAQ,QACR,KAAK,EAAE,WAAW,EAClB,QAAQ,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,cAAc,CAAC,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,EACvD,QAAQ,EAAE,UAAU,EACpB,WAAW,EAAE,oEAAoE,GACjF;QACF,uCAAK,SAAS,EAAC,oBAAoB;YAChC,UAAU,IAAI,8BAAC,sBAAc,OAAG;YACjC,8BAAC,sBAAM,IAAC,QAAQ,EAAE,UAAU,EAAE,OAAO,EAAE,GAAG,EAAE,CAAC,WAAW,CAAC,WAAW,CAAC,YAE5D;YACT,8BAAC,sBAAM,IACL,QAAQ,EAAE,UAAU,EACpB,OAAO,EAAE,KAAK,IAAI,EAAE;oBAClB,WAAW,CAAC,EAAE,CAAC,CAAC;oBAChB,cAAc,CAAC,EAAE,CAAC,CAAC;oBACnB,IAAI,SAAS,EAAE;wBACb,MAAM,SAAS,EAAE,CAAC;qBACnB;gBACH,CAAC,YAGM,CACL,CACF,CACP,CAAC;AACJ,CAAC,CAAC;AAEF,kBAAe,sBAAsB,CAAC","sourcesContent":["/*---------------------------------------------------------------------------------------------\n* Copyright (c) Bentley Systems, Incorporated. All rights reserved.\n* See LICENSE.md in the project root for license terms and full copyright notice.\n*--------------------------------------------------------------------------------------------*/\nimport React from \"react\";\nimport { Button, LabeledTextarea, Text } from \"@itwin/itwinui-react\";\nimport { LoadingSpinner } from \"../utils\";\nimport \"./ManualGroupingCustomUI.scss\";\nimport type { GroupingCustomUIProps } from \"./GroupingMappingCustomUI\";\n\nconst ManualGroupingCustomUI = ({\n updateQuery,\n isUpdating,\n resetView,\n}: GroupingCustomUIProps) => {\n const [manualInput, setManualInput] = React.useState(\"\");\n\n return (\n <div className='gmw-manual-form'>\n <Text>\n Generate group using an ECSQL query. Please select ECInstanceId and ECClassId columns in the query.\n </Text>\n <LabeledTextarea\n label='Query'\n required\n value={manualInput}\n onChange={(event) => setManualInput(event.target.value)}\n disabled={isUpdating}\n placeholder={`E.g. \"SELECT ECInstanceId, ECClassId FROM BisCore:PhysicalElement\"`}\n />\n <div className='gmw-manual-actions'>\n {isUpdating && <LoadingSpinner />}\n <Button disabled={isUpdating} onClick={() => updateQuery(manualInput)}>\n Apply\n </Button>\n <Button\n disabled={isUpdating}\n onClick={async () => {\n updateQuery(\"\");\n setManualInput(\"\");\n if (resetView) {\n await resetView();\n }\n }}\n >\n Clear\n </Button>\n </div>\n </div>\n );\n};\n\nexport default ManualGroupingCustomUI;\n"]}
|
|
@@ -0,0 +1,17 @@
|
|
|
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 "~@itwin/itwinui-css/scss/variables";
|
|
6
|
+
|
|
7
|
+
.gmw-manual-form {
|
|
8
|
+
display: flex;
|
|
9
|
+
flex-direction: column;
|
|
10
|
+
gap: $iui-baseline;
|
|
11
|
+
margin-top: $iui-baseline;
|
|
12
|
+
> .gmw-manual-actions {
|
|
13
|
+
display: flex;
|
|
14
|
+
justify-content: flex-end;
|
|
15
|
+
gap: $iui-s;
|
|
16
|
+
}
|
|
17
|
+
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/// <reference types="react" />
|
|
2
|
+
import type { GroupingCustomUIProps } from "./GroupingMappingCustomUI";
|
|
3
|
+
import "./SearchGroupingCustomUI.scss";
|
|
4
|
+
declare const SearchGroupingCustomUI: ({ updateQuery, isUpdating, resetView, }: GroupingCustomUIProps) => JSX.Element;
|
|
5
|
+
export default SearchGroupingCustomUI;
|
|
6
|
+
//# sourceMappingURL=SearchGroupingCustomUI.d.ts.map
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
/*---------------------------------------------------------------------------------------------
|
|
7
|
+
* Copyright (c) Bentley Systems, Incorporated. All rights reserved.
|
|
8
|
+
* See LICENSE.md in the project root for license terms and full copyright notice.
|
|
9
|
+
*--------------------------------------------------------------------------------------------*/
|
|
10
|
+
const react_1 = __importDefault(require("react"));
|
|
11
|
+
const itwinui_react_1 = require("@itwin/itwinui-react");
|
|
12
|
+
const utils_1 = require("../utils");
|
|
13
|
+
require("./SearchGroupingCustomUI.scss");
|
|
14
|
+
const SearchGroupingCustomUI = ({ updateQuery, isUpdating, resetView, }) => {
|
|
15
|
+
const [searchInput, setSearchInput] = react_1.default.useState("");
|
|
16
|
+
const isWrappedInQuotes = (text) => {
|
|
17
|
+
return text.startsWith(`"`) && text.endsWith(`"`);
|
|
18
|
+
};
|
|
19
|
+
const needsAndOperator = (token, index, searchQuery) => isWrappedInQuotes(token) ||
|
|
20
|
+
(index === 1 && isWrappedInQuotes(searchQuery[0]));
|
|
21
|
+
const generateSearchQuery = (searchQuery) => {
|
|
22
|
+
if (searchQuery.length === 0) {
|
|
23
|
+
updateQuery("");
|
|
24
|
+
return;
|
|
25
|
+
}
|
|
26
|
+
let generatedSearchQuery = `SELECT be.ECInstanceId, be.ECClassId FROM bis.geometricelement3d be `;
|
|
27
|
+
generatedSearchQuery += `LEFT JOIN bis.SpatialCategory cat ON be.Category.Id = cat.ECInstanceID LEFT JOIN ecdbmeta.ECClassDef ecc ON be.ECClassId = ecc.ECInstanceId `;
|
|
28
|
+
generatedSearchQuery += `LEFT JOIN bis.PhysicalType pt ON be.TypeDefinition.Id = pt.ECInstanceID`;
|
|
29
|
+
generatedSearchQuery += ` WHERE `;
|
|
30
|
+
generatedSearchQuery += `((${searchQuery
|
|
31
|
+
.map((token, index) => `${index === 0
|
|
32
|
+
? ""
|
|
33
|
+
: needsAndOperator(token, index, searchQuery)
|
|
34
|
+
? "AND"
|
|
35
|
+
: "OR"} be.codevalue LIKE '%${isWrappedInQuotes(token) ? token.slice(1, -1) : token}%'`)
|
|
36
|
+
.join(" ")}) OR (${searchQuery
|
|
37
|
+
.map((token, index) => `${index === 0
|
|
38
|
+
? ""
|
|
39
|
+
: needsAndOperator(token, index, searchQuery)
|
|
40
|
+
? "AND"
|
|
41
|
+
: "OR"} be.userlabel LIKE '%${isWrappedInQuotes(token) ? token.slice(1, -1) : token}%'`)
|
|
42
|
+
.join(" ")})) OR ((${searchQuery
|
|
43
|
+
.map((token, index) => `${index === 0
|
|
44
|
+
? ""
|
|
45
|
+
: needsAndOperator(token, index, searchQuery)
|
|
46
|
+
? "AND"
|
|
47
|
+
: "OR"} cat.codevalue LIKE '%${isWrappedInQuotes(token) ? token.slice(1, -1) : token}%'`)
|
|
48
|
+
.join(" ")}) OR (${searchQuery
|
|
49
|
+
.map((token, index) => `${index === 0
|
|
50
|
+
? ""
|
|
51
|
+
: needsAndOperator(token, index, searchQuery)
|
|
52
|
+
? "AND"
|
|
53
|
+
: "OR"} cat.userlabel LIKE '%${isWrappedInQuotes(token) ? token.slice(1, -1) : token}%'`)
|
|
54
|
+
.join(" ")})) OR (${searchQuery
|
|
55
|
+
.map((token, index) => `${index === 0
|
|
56
|
+
? ""
|
|
57
|
+
: needsAndOperator(token, index, searchQuery)
|
|
58
|
+
? "AND"
|
|
59
|
+
: "OR"} ecc.name LIKE '%${isWrappedInQuotes(token) ? token.slice(1, -1) : token}%'`)
|
|
60
|
+
.join(" ")})`;
|
|
61
|
+
// Physical Types
|
|
62
|
+
generatedSearchQuery += ` OR ((${searchQuery
|
|
63
|
+
.map((token, index) => `${index === 0
|
|
64
|
+
? ""
|
|
65
|
+
: needsAndOperator(token, index, searchQuery)
|
|
66
|
+
? "AND"
|
|
67
|
+
: "OR"} pt.codevalue LIKE '%${isWrappedInQuotes(token) ? token.slice(1, -1) : token}%'`)
|
|
68
|
+
.join(" ")}) OR (${searchQuery
|
|
69
|
+
.map((token, index) => `${index === 0
|
|
70
|
+
? ""
|
|
71
|
+
: needsAndOperator(token, index, searchQuery)
|
|
72
|
+
? "AND"
|
|
73
|
+
: "OR"} pt.userlabel LIKE '%${isWrappedInQuotes(token) ? token.slice(1, -1) : token}%'`)
|
|
74
|
+
.join(" ")})) `;
|
|
75
|
+
updateQuery(generatedSearchQuery);
|
|
76
|
+
};
|
|
77
|
+
return (react_1.default.createElement("div", { className: 'gmw-search-form' },
|
|
78
|
+
react_1.default.createElement(itwinui_react_1.Text, null, "Generate a query by keywords. Keywords wrapped in double quotes will be considered a required criteria."),
|
|
79
|
+
react_1.default.createElement(itwinui_react_1.LabeledTextarea, { label: 'Query Keywords', required: true, value: searchInput, onChange: (event) => setSearchInput(event.target.value), disabled: isUpdating, placeholder: `E.g. "red" chair` }),
|
|
80
|
+
react_1.default.createElement("div", { className: 'gmw-search-actions' },
|
|
81
|
+
isUpdating && react_1.default.createElement(utils_1.LoadingSpinner, null),
|
|
82
|
+
react_1.default.createElement(itwinui_react_1.Button, { disabled: isUpdating, onClick: () => generateSearchQuery(searchInput
|
|
83
|
+
? searchInput
|
|
84
|
+
.replace(/(\r\n|\n|\r)/gm, "")
|
|
85
|
+
.trim()
|
|
86
|
+
.split(" ")
|
|
87
|
+
: []) }, "Apply"),
|
|
88
|
+
react_1.default.createElement(itwinui_react_1.Button, { disabled: isUpdating, onClick: async () => {
|
|
89
|
+
updateQuery("");
|
|
90
|
+
setSearchInput("");
|
|
91
|
+
if (resetView) {
|
|
92
|
+
await resetView();
|
|
93
|
+
}
|
|
94
|
+
} }, "Clear"))));
|
|
95
|
+
};
|
|
96
|
+
exports.default = SearchGroupingCustomUI;
|
|
97
|
+
//# sourceMappingURL=SearchGroupingCustomUI.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SearchGroupingCustomUI.js","sourceRoot":"","sources":["../../../../../src/widget/components/customUI/SearchGroupingCustomUI.tsx"],"names":[],"mappings":"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","sourcesContent":["/*---------------------------------------------------------------------------------------------\n* Copyright (c) Bentley Systems, Incorporated. All rights reserved.\n* See LICENSE.md in the project root for license terms and full copyright notice.\n*--------------------------------------------------------------------------------------------*/\nimport React from \"react\";\nimport { Button, LabeledTextarea, Text } from \"@itwin/itwinui-react\";\nimport type { GroupingCustomUIProps } from \"./GroupingMappingCustomUI\";\nimport { LoadingSpinner } from \"../utils\";\nimport \"./SearchGroupingCustomUI.scss\";\n\nconst SearchGroupingCustomUI = ({\n updateQuery,\n isUpdating,\n resetView,\n}: GroupingCustomUIProps) => {\n const [searchInput, setSearchInput] = React.useState(\"\");\n const isWrappedInQuotes = (text: string) => {\n return text.startsWith(`\"`) && text.endsWith(`\"`);\n };\n\n const needsAndOperator = (\n token: string,\n index: number,\n searchQuery: string[],\n ) =>\n isWrappedInQuotes(token) ||\n (index === 1 && isWrappedInQuotes(searchQuery[0]));\n\n const generateSearchQuery = (searchQuery: string[]) => {\n if (searchQuery.length === 0) {\n updateQuery(\"\");\n return;\n }\n\n let generatedSearchQuery = `SELECT be.ECInstanceId, be.ECClassId FROM bis.geometricelement3d be `;\n generatedSearchQuery += `LEFT JOIN bis.SpatialCategory cat ON be.Category.Id = cat.ECInstanceID LEFT JOIN ecdbmeta.ECClassDef ecc ON be.ECClassId = ecc.ECInstanceId `;\n generatedSearchQuery += `LEFT JOIN bis.PhysicalType pt ON be.TypeDefinition.Id = pt.ECInstanceID`;\n generatedSearchQuery += ` WHERE `;\n generatedSearchQuery += `((${searchQuery\n .map(\n (token, index) =>\n `${index === 0\n ? \"\"\n : needsAndOperator(token, index, searchQuery)\n ? \"AND\"\n : \"OR\"\n } be.codevalue LIKE '%${isWrappedInQuotes(token) ? token.slice(1, -1) : token\n }%'`,\n )\n .join(\" \")}) OR (${searchQuery\n .map(\n (token, index) =>\n `${index === 0\n ? \"\"\n : needsAndOperator(token, index, searchQuery)\n ? \"AND\"\n : \"OR\"\n } be.userlabel LIKE '%${isWrappedInQuotes(token) ? token.slice(1, -1) : token\n }%'`,\n )\n .join(\" \")})) OR ((${searchQuery\n .map(\n (token, index) =>\n `${index === 0\n ? \"\"\n : needsAndOperator(token, index, searchQuery)\n ? \"AND\"\n : \"OR\"\n } cat.codevalue LIKE '%${isWrappedInQuotes(token) ? token.slice(1, -1) : token\n }%'`,\n )\n .join(\" \")}) OR (${searchQuery\n .map(\n (token, index) =>\n `${index === 0\n ? \"\"\n : needsAndOperator(token, index, searchQuery)\n ? \"AND\"\n : \"OR\"\n } cat.userlabel LIKE '%${isWrappedInQuotes(token) ? token.slice(1, -1) : token\n }%'`,\n )\n .join(\" \")})) OR (${searchQuery\n .map(\n (token, index) =>\n `${index === 0\n ? \"\"\n : needsAndOperator(token, index, searchQuery)\n ? \"AND\"\n : \"OR\"\n } ecc.name LIKE '%${isWrappedInQuotes(token) ? token.slice(1, -1) : token\n }%'`,\n )\n .join(\" \")})`;\n // Physical Types\n generatedSearchQuery += ` OR ((${searchQuery\n .map(\n (token, index) =>\n `${index === 0\n ? \"\"\n : needsAndOperator(token, index, searchQuery)\n ? \"AND\"\n : \"OR\"\n } pt.codevalue LIKE '%${isWrappedInQuotes(token) ? token.slice(1, -1) : token\n }%'`,\n )\n .join(\" \")}) OR (${searchQuery\n .map(\n (token, index) =>\n `${index === 0\n ? \"\"\n : needsAndOperator(token, index, searchQuery)\n ? \"AND\"\n : \"OR\"\n } pt.userlabel LIKE '%${isWrappedInQuotes(token) ? token.slice(1, -1) : token\n }%'`,\n )\n .join(\" \")})) `;\n\n updateQuery(generatedSearchQuery);\n };\n\n return (\n <div className='gmw-search-form'>\n <Text>\n Generate a query by keywords. Keywords wrapped in double quotes will be\n considered a required criteria.\n </Text>\n <LabeledTextarea\n label='Query Keywords'\n required\n value={searchInput}\n onChange={(event) => setSearchInput(event.target.value)}\n disabled={isUpdating}\n placeholder={`E.g. \"red\" chair`}\n />\n <div className='gmw-search-actions'>\n {isUpdating && <LoadingSpinner />}\n <Button\n disabled={isUpdating}\n onClick={() =>\n generateSearchQuery(\n searchInput\n ? searchInput\n .replace(/(\\r\\n|\\n|\\r)/gm, \"\")\n .trim()\n .split(\" \")\n : [],\n )\n }\n >\n Apply\n </Button>\n <Button\n disabled={isUpdating}\n onClick={async () => {\n updateQuery(\"\");\n setSearchInput(\"\");\n if (resetView) {\n await resetView();\n }\n }}\n >\n Clear\n </Button>\n </div>\n </div>\n );\n};\n\nexport default SearchGroupingCustomUI;\n"]}
|
|
@@ -0,0 +1,17 @@
|
|
|
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 "~@itwin/itwinui-css/scss/variables";
|
|
6
|
+
|
|
7
|
+
.gmw-search-form {
|
|
8
|
+
display: flex;
|
|
9
|
+
flex-direction: column;
|
|
10
|
+
gap: $iui-baseline;
|
|
11
|
+
margin-top: $iui-baseline;
|
|
12
|
+
> .gmw-search-actions {
|
|
13
|
+
display: flex;
|
|
14
|
+
justify-content: flex-end;
|
|
15
|
+
gap: $iui-s;
|
|
16
|
+
}
|
|
17
|
+
}
|
|
@@ -12,4 +12,5 @@ export { PropertyMenu } from "./widget/components/PropertyMenu";
|
|
|
12
12
|
export { resolveFormulaDataType } from "./formula/FormulaDataTypeResolver";
|
|
13
13
|
export { DataType, PropertyMap } from "./formula/Types";
|
|
14
14
|
export { IResult } from "./formula/IResult";
|
|
15
|
+
export { GroupingMappingCustomUI, GroupingMappingCustomUIType, ContextCustomUI, GroupingCustomUI, GroupingCustomUIProps, ContextCustomUIProps } from "./widget/components/customUI/GroupingMappingCustomUI";
|
|
15
16
|
//# sourceMappingURL=grouping-mapping-widget.d.ts.map
|
|
@@ -13,4 +13,5 @@ export { Groupings } from "./widget/components/Grouping";
|
|
|
13
13
|
export { PropertyMenu } from "./widget/components/PropertyMenu";
|
|
14
14
|
/** Formula DataType resolver */
|
|
15
15
|
export { resolveFormulaDataType } from "./formula/FormulaDataTypeResolver";
|
|
16
|
+
export { GroupingMappingCustomUIType } from "./widget/components/customUI/GroupingMappingCustomUI";
|
|
16
17
|
//# sourceMappingURL=grouping-mapping-widget.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"grouping-mapping-widget.js","sourceRoot":"","sources":["../../src/grouping-mapping-widget.ts"],"names":[],"mappings":"AAAA;;;+FAG+F;AAC/F,gDAAgD;AAChD,cAAc,gCAAgC,CAAC;AAE/C,0EAA0E;AAC1E,OAAO,EAAE,0BAA0B,EAAE,MAAM,kDAAkD,CAAC;AAE9F,cAAc,wBAAwB,CAAC;AAEvC,yCAAyC;AACzC,OAAO,EAAE,QAAQ,EAAE,MAAM,6BAA6B,CAAC;AACvD,OAAO,EAAE,SAAS,EAAE,MAAM,8BAA8B,CAAC;AACzD,OAAO,EAAE,YAAY,EAAE,MAAM,kCAAkC,CAAC;AAEhE,gCAAgC;AAChC,OAAO,EAAE,sBAAsB,EAAE,MAAM,mCAAmC,CAAC","sourcesContent":["/*---------------------------------------------------------------------------------------------\n* Copyright (c) Bentley Systems, Incorporated. All rights reserved.\n* See LICENSE.md in the project root for license terms and full copyright notice.\n*--------------------------------------------------------------------------------------------*/\n/** UI Provider for iTwin Viewer Applications */\nexport * from \"./widget/GroupingMappingWidget\";\n\n/** Interfaces for providing custom MappingClient and API configuration */\nexport { createDefaultMappingClient } from \"./widget/components/context/MappingClientContext\";\nexport { ClientPrefix, GetAccessTokenFn } from \"./widget/components/context/GroupingApiConfigContext\";\nexport * from \"@itwin/insights-client\";\n\n/** Internal components for custom UIs */\nexport { Mappings } from \"./widget/components/Mapping\";\nexport { Groupings } from \"./widget/components/Grouping\";\nexport { PropertyMenu } from \"./widget/components/PropertyMenu\";\n\n/** Formula DataType resolver */\nexport { resolveFormulaDataType } from \"./formula/FormulaDataTypeResolver\";\nexport { DataType, PropertyMap } from \"./formula/Types\";\nexport { IResult } from \"./formula/IResult\";\n"]}
|
|
1
|
+
{"version":3,"file":"grouping-mapping-widget.js","sourceRoot":"","sources":["../../src/grouping-mapping-widget.ts"],"names":[],"mappings":"AAAA;;;+FAG+F;AAC/F,gDAAgD;AAChD,cAAc,gCAAgC,CAAC;AAE/C,0EAA0E;AAC1E,OAAO,EAAE,0BAA0B,EAAE,MAAM,kDAAkD,CAAC;AAE9F,cAAc,wBAAwB,CAAC;AAEvC,yCAAyC;AACzC,OAAO,EAAE,QAAQ,EAAE,MAAM,6BAA6B,CAAC;AACvD,OAAO,EAAE,SAAS,EAAE,MAAM,8BAA8B,CAAC;AACzD,OAAO,EAAE,YAAY,EAAE,MAAM,kCAAkC,CAAC;AAEhE,gCAAgC;AAChC,OAAO,EAAE,sBAAsB,EAAE,MAAM,mCAAmC,CAAC;AAG3E,OAAO,EAA2B,2BAA2B,EAAkF,MAAM,sDAAsD,CAAC","sourcesContent":["/*---------------------------------------------------------------------------------------------\n* Copyright (c) Bentley Systems, Incorporated. All rights reserved.\n* See LICENSE.md in the project root for license terms and full copyright notice.\n*--------------------------------------------------------------------------------------------*/\n/** UI Provider for iTwin Viewer Applications */\nexport * from \"./widget/GroupingMappingWidget\";\n\n/** Interfaces for providing custom MappingClient and API configuration */\nexport { createDefaultMappingClient } from \"./widget/components/context/MappingClientContext\";\nexport { ClientPrefix, GetAccessTokenFn } from \"./widget/components/context/GroupingApiConfigContext\";\nexport * from \"@itwin/insights-client\";\n\n/** Internal components for custom UIs */\nexport { Mappings } from \"./widget/components/Mapping\";\nexport { Groupings } from \"./widget/components/Grouping\";\nexport { PropertyMenu } from \"./widget/components/PropertyMenu\";\n\n/** Formula DataType resolver */\nexport { resolveFormulaDataType } from \"./formula/FormulaDataTypeResolver\";\nexport { DataType, PropertyMap } from \"./formula/Types\";\nexport { IResult } from \"./formula/IResult\";\nexport { GroupingMappingCustomUI, GroupingMappingCustomUIType, ContextCustomUI, GroupingCustomUI, GroupingCustomUIProps, ContextCustomUIProps } from \"./widget/components/customUI/GroupingMappingCustomUI\";\n"]}
|
|
@@ -0,0 +1,138 @@
|
|
|
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 React from "react";
|
|
6
|
+
import "@testing-library/jest-dom";
|
|
7
|
+
import { mockAccessToken, mockMappingClient, render, screen, TestUtils, waitForElementToBeRemoved, within } from "./test-utils";
|
|
8
|
+
import { faker } from "@faker-js/faker";
|
|
9
|
+
import { Groupings } from "../grouping-mapping-widget";
|
|
10
|
+
import * as moq from "typemoq";
|
|
11
|
+
import { NoRenderApp } from "@itwin/core-frontend";
|
|
12
|
+
import { Presentation, SelectionChangeEvent } from "@itwin/presentation-frontend";
|
|
13
|
+
import { EmptyLocalization } from "@itwin/core-common";
|
|
14
|
+
const mockITwinId = faker.datatype.uuid();
|
|
15
|
+
const mockIModelId = faker.datatype.uuid();
|
|
16
|
+
const mockMappingId = faker.datatype.uuid();
|
|
17
|
+
const mockMapping = {
|
|
18
|
+
id: mockMappingId,
|
|
19
|
+
mappingName: "mOcKmApPiNg1",
|
|
20
|
+
description: "mOcKmApPiNgDeScRiPtIoN1",
|
|
21
|
+
createdBy: faker.random.alpha(),
|
|
22
|
+
createdOn: faker.date.past().toDateString(),
|
|
23
|
+
modifiedBy: faker.random.alpha(),
|
|
24
|
+
modifiedOn: faker.date.past().toDateString(),
|
|
25
|
+
extractionEnabled: false,
|
|
26
|
+
_links: {
|
|
27
|
+
imodel: {
|
|
28
|
+
href: "",
|
|
29
|
+
},
|
|
30
|
+
},
|
|
31
|
+
};
|
|
32
|
+
const groupsFactory = () => ({
|
|
33
|
+
groups: Array.from({ length: faker.datatype.number({ min: 3, max: 5 }) }, (_, index) => ({
|
|
34
|
+
id: `${faker.datatype.uuid()}`,
|
|
35
|
+
groupName: `mOcKgRoUp${index}`,
|
|
36
|
+
description: `mOcKgRoUpDeScRiPtIoN${index}`,
|
|
37
|
+
query: `mOcKgRoUpQuErY${index}`,
|
|
38
|
+
_links: {
|
|
39
|
+
imodel: {
|
|
40
|
+
href: "",
|
|
41
|
+
},
|
|
42
|
+
mapping: {
|
|
43
|
+
href: "",
|
|
44
|
+
},
|
|
45
|
+
},
|
|
46
|
+
})),
|
|
47
|
+
_links: {
|
|
48
|
+
next: undefined,
|
|
49
|
+
self: {
|
|
50
|
+
href: "",
|
|
51
|
+
},
|
|
52
|
+
},
|
|
53
|
+
});
|
|
54
|
+
const connectionMock = moq.Mock.ofType();
|
|
55
|
+
const selectionManagerMock = moq.Mock.ofType();
|
|
56
|
+
const selectionScopesManagerMock = moq.Mock.ofType();
|
|
57
|
+
jest.mock("@itwin/appui-react", () => ({
|
|
58
|
+
...jest.requireActual("@itwin/appui-react"),
|
|
59
|
+
useActiveIModelConnection: () => connectionMock.object,
|
|
60
|
+
}));
|
|
61
|
+
beforeAll(async () => {
|
|
62
|
+
await NoRenderApp.startup({ localization: new EmptyLocalization() });
|
|
63
|
+
await Presentation.initialize();
|
|
64
|
+
const selectionSet = moq.Mock.ofType();
|
|
65
|
+
const onChanged = moq.Mock.ofType();
|
|
66
|
+
selectionSet.setup((x) => x.elements).returns(() => new Set([]));
|
|
67
|
+
selectionSet.setup((x) => x.onChanged).returns(() => onChanged.object);
|
|
68
|
+
connectionMock
|
|
69
|
+
.setup((x) => x.selectionSet)
|
|
70
|
+
.returns(() => selectionSet.object);
|
|
71
|
+
connectionMock.setup((x) => x.iModelId).returns(() => mockIModelId);
|
|
72
|
+
connectionMock.setup((x) => x.iTwinId).returns(() => mockITwinId);
|
|
73
|
+
selectionManagerMock
|
|
74
|
+
.setup((x) => x.selectionChange)
|
|
75
|
+
.returns(() => new SelectionChangeEvent());
|
|
76
|
+
selectionScopesManagerMock
|
|
77
|
+
.setup(async (x) => x.getSelectionScopes(connectionMock.object))
|
|
78
|
+
.returns(async () => []);
|
|
79
|
+
selectionManagerMock
|
|
80
|
+
.setup((x) => x.scopes)
|
|
81
|
+
.returns(() => selectionScopesManagerMock.object);
|
|
82
|
+
Presentation.setSelectionManager(selectionManagerMock.object);
|
|
83
|
+
await TestUtils.initializeUiFramework(connectionMock.object);
|
|
84
|
+
});
|
|
85
|
+
describe("Groupings View with default UIs", () => {
|
|
86
|
+
it("List all groups and click on add group and edit group buttons", async () => {
|
|
87
|
+
// Arange
|
|
88
|
+
const mockGroups = groupsFactory();
|
|
89
|
+
const mockedAccessToken = await mockAccessToken();
|
|
90
|
+
mockMappingClient
|
|
91
|
+
.setup(async (x) => x.getGroups(mockedAccessToken, mockIModelId, mockMappingId))
|
|
92
|
+
.returns(async () => mockGroups.groups);
|
|
93
|
+
// Act
|
|
94
|
+
const { user } = render(React.createElement(Groupings, { mapping: mockMapping, goBack: jest.fn() }));
|
|
95
|
+
await waitForElementToBeRemoved(() => screen.getByText(/loading/i));
|
|
96
|
+
// Assert
|
|
97
|
+
const addButton = screen.getAllByTestId("gmw-add-group-button");
|
|
98
|
+
expect(addButton).toHaveLength(1);
|
|
99
|
+
// Click on 'Add Group' button
|
|
100
|
+
await user.click(addButton[0]);
|
|
101
|
+
// Should have three menu items
|
|
102
|
+
const addSelection = screen.getAllByTestId("gmw-add-0");
|
|
103
|
+
expect(addSelection).toHaveLength(1);
|
|
104
|
+
const addSearch = screen.getAllByTestId("gmw-add-1");
|
|
105
|
+
expect(addSearch).toHaveLength(1);
|
|
106
|
+
const addManual = screen.getAllByTestId("gmw-add-2");
|
|
107
|
+
expect(addManual).toHaveLength(1);
|
|
108
|
+
// Should have the right group number
|
|
109
|
+
const horizontalTiles = screen.getAllByTestId("gmw-horizontal-tile");
|
|
110
|
+
expect(horizontalTiles).toHaveLength(mockGroups.groups.length);
|
|
111
|
+
horizontalTiles.forEach((horizontalTile, index) => {
|
|
112
|
+
var _a;
|
|
113
|
+
const groupTile = within(horizontalTile);
|
|
114
|
+
expect(groupTile.getByText(mockGroups.groups[index].groupName)).toBeInTheDocument();
|
|
115
|
+
expect(groupTile.getByText((_a = mockGroups.groups[index].description) !== null && _a !== void 0 ? _a : "")).toBeInTheDocument();
|
|
116
|
+
});
|
|
117
|
+
// Click on first group more icon
|
|
118
|
+
const moreButton = screen.getAllByTestId("gmw-more-button");
|
|
119
|
+
expect(moreButton).toHaveLength(mockGroups.groups.length);
|
|
120
|
+
await user.click(moreButton[0]);
|
|
121
|
+
// Should have 3 context menu items
|
|
122
|
+
const contextMenuItems = screen.getAllByTestId("gmw-context-menu-item");
|
|
123
|
+
expect(contextMenuItems).toHaveLength(3);
|
|
124
|
+
expect(contextMenuItems[0]).toHaveTextContent("Edit");
|
|
125
|
+
expect(contextMenuItems[1]).toHaveTextContent("Properties");
|
|
126
|
+
expect(contextMenuItems[2]).toHaveTextContent("Remove");
|
|
127
|
+
// Hover on 'Edit'
|
|
128
|
+
await user.hover(contextMenuItems[0]);
|
|
129
|
+
// Should have 3 sub menu items
|
|
130
|
+
const editSelection = screen.getAllByTestId(`gmw-edit-0`);
|
|
131
|
+
expect(editSelection).toHaveLength(1);
|
|
132
|
+
const editSearch = screen.getAllByTestId(`gmw-edit-1`);
|
|
133
|
+
expect(editSearch).toHaveLength(1);
|
|
134
|
+
const editManual = screen.getAllByTestId(`gmw-edit-2`);
|
|
135
|
+
expect(editManual).toHaveLength(1);
|
|
136
|
+
});
|
|
137
|
+
});
|
|
138
|
+
//# sourceMappingURL=GroupingMappingCustomUI.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"GroupingMappingCustomUI.test.js","sourceRoot":"","sources":["../../../src/test/GroupingMappingCustomUI.test.tsx"],"names":[],"mappings":"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","sourcesContent":["/*---------------------------------------------------------------------------------------------\n* Copyright (c) Bentley Systems, Incorporated. All rights reserved.\n* See LICENSE.md in the project root for license terms and full copyright notice.\n*--------------------------------------------------------------------------------------------*/\nimport React from \"react\";\nimport \"@testing-library/jest-dom\";\nimport { mockAccessToken, mockMappingClient, render, screen, TestUtils, waitForElementToBeRemoved, within } from \"./test-utils\";\nimport { faker } from \"@faker-js/faker\";\nimport { Groupings } from \"../grouping-mapping-widget\";\nimport type { GroupCollection, Mapping} from \"@itwin/insights-client\";\nimport * as moq from \"typemoq\";\nimport type { IModelConnection, SelectionSet, SelectionSetEvent} from \"@itwin/core-frontend\";\nimport { NoRenderApp } from \"@itwin/core-frontend\";\nimport type { SelectionManager, SelectionScopesManager } from \"@itwin/presentation-frontend\";\nimport { Presentation, SelectionChangeEvent } from \"@itwin/presentation-frontend\";\nimport type { BeEvent } from \"@itwin/core-bentley\";\nimport { EmptyLocalization } from \"@itwin/core-common\";\n\nconst mockITwinId = faker.datatype.uuid();\nconst mockIModelId = faker.datatype.uuid();\nconst mockMappingId = faker.datatype.uuid();\nconst mockMapping: Mapping = {\n id: mockMappingId,\n mappingName: \"mOcKmApPiNg1\",\n description: \"mOcKmApPiNgDeScRiPtIoN1\",\n createdBy: faker.random.alpha(),\n createdOn: faker.date.past().toDateString(),\n modifiedBy: faker.random.alpha(),\n modifiedOn: faker.date.past().toDateString(),\n extractionEnabled:false,\n _links: {\n imodel: {\n href: \"\",\n },\n },\n};\n\nconst groupsFactory = (): GroupCollection => ({\n groups: Array.from(\n { length: faker.datatype.number({ min: 3, max: 5 }) },\n (_, index) => ({\n id: `${faker.datatype.uuid()}`,\n groupName: `mOcKgRoUp${index}`,\n description: `mOcKgRoUpDeScRiPtIoN${index}`,\n query: `mOcKgRoUpQuErY${index}`,\n _links: {\n imodel: {\n href: \"\",\n },\n mapping: {\n href: \"\",\n },\n },\n })\n ),\n _links: {\n next: undefined,\n self: {\n href: \"\",\n },\n },\n});\n\nconst connectionMock = moq.Mock.ofType<IModelConnection>();\nconst selectionManagerMock = moq.Mock.ofType<SelectionManager>();\nconst selectionScopesManagerMock = moq.Mock.ofType<SelectionScopesManager>();\n\njest.mock(\"@itwin/appui-react\", () => ({\n ...jest.requireActual(\"@itwin/appui-react\"),\n useActiveIModelConnection: () => connectionMock.object,\n}));\n\nbeforeAll(async () => {\n await NoRenderApp.startup({localization: new EmptyLocalization()});\n await Presentation.initialize();\n const selectionSet = moq.Mock.ofType<SelectionSet>();\n const onChanged = moq.Mock.ofType<BeEvent<(ev: SelectionSetEvent) => void>>();\n selectionSet.setup((x) => x.elements).returns(() => new Set([]));\n selectionSet.setup((x) => x.onChanged).returns(() => onChanged.object);\n connectionMock\n .setup((x) => x.selectionSet)\n .returns(() => selectionSet.object);\n connectionMock.setup((x) => x.iModelId).returns(() => mockIModelId);\n connectionMock.setup((x) => x.iTwinId).returns(() => mockITwinId);\n\n selectionManagerMock\n .setup((x) => x.selectionChange)\n .returns(() => new SelectionChangeEvent());\n\n selectionScopesManagerMock\n .setup(async (x) => x.getSelectionScopes(connectionMock.object))\n .returns(async () => []);\n selectionManagerMock\n .setup((x) => x.scopes)\n .returns(() => selectionScopesManagerMock.object);\n\n Presentation.setSelectionManager(selectionManagerMock.object);\n await TestUtils.initializeUiFramework(connectionMock.object);\n});\n\ndescribe(\"Groupings View with default UIs\", () => {\n it(\"List all groups and click on add group and edit group buttons\", async () => {\n // Arange\n const mockGroups = groupsFactory();\n const mockedAccessToken = await mockAccessToken();\n mockMappingClient\n .setup(async (x) => x.getGroups(mockedAccessToken, mockIModelId, mockMappingId))\n .returns(async () => mockGroups.groups);\n\n // Act\n const { user } = render(<Groupings mapping={mockMapping} goBack={jest.fn()} />);\n await waitForElementToBeRemoved(() => screen.getByText(/loading/i));\n\n // Assert\n const addButton = screen.getAllByTestId(\"gmw-add-group-button\");\n expect(addButton).toHaveLength(1);\n\n // Click on 'Add Group' button\n await user.click(addButton[0]);\n\n // Should have three menu items\n const addSelection = screen.getAllByTestId(\"gmw-add-0\");\n expect(addSelection).toHaveLength(1);\n const addSearch = screen.getAllByTestId(\"gmw-add-1\");\n expect(addSearch).toHaveLength(1);\n const addManual = screen.getAllByTestId(\"gmw-add-2\");\n expect(addManual).toHaveLength(1);\n\n // Should have the right group number\n const horizontalTiles = screen.getAllByTestId(\"gmw-horizontal-tile\");\n expect(horizontalTiles).toHaveLength(mockGroups.groups.length);\n\n horizontalTiles.forEach((horizontalTile, index) => {\n const groupTile = within(horizontalTile);\n expect(\n groupTile.getByText(\n mockGroups.groups[index].groupName\n )\n ).toBeInTheDocument();\n expect(\n groupTile.getByText(\n mockGroups.groups[index].description ?? \"\"\n )\n ).toBeInTheDocument();\n });\n\n // Click on first group more icon\n const moreButton = screen.getAllByTestId(\"gmw-more-button\");\n expect(moreButton).toHaveLength(mockGroups.groups.length);\n\n await user.click(moreButton[0]);\n\n // Should have 3 context menu items\n const contextMenuItems = screen.getAllByTestId(\"gmw-context-menu-item\");\n expect(contextMenuItems).toHaveLength(3);\n expect(contextMenuItems[0]).toHaveTextContent(\"Edit\");\n expect(contextMenuItems[1]).toHaveTextContent(\"Properties\");\n expect(contextMenuItems[2]).toHaveTextContent(\"Remove\");\n\n // Hover on 'Edit'\n await user.hover(contextMenuItems[0]);\n\n // Should have 3 sub menu items\n const editSelection = screen.getAllByTestId(`gmw-edit-0`);\n expect(editSelection).toHaveLength(1);\n const editSearch = screen.getAllByTestId(`gmw-edit-1`);\n expect(editSearch).toHaveLength(1);\n const editManual = screen.getAllByTestId(`gmw-edit-2`);\n expect(editManual).toHaveLength(1);\n });\n});\n"]}
|
|
@@ -0,0 +1,31 @@
|
|
|
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 React from "react";
|
|
6
|
+
import "@testing-library/jest-dom";
|
|
7
|
+
import { render, screen } from "../test/test-utils";
|
|
8
|
+
import { WidgetHeader } from "../widget/components/utils";
|
|
9
|
+
import { faker } from "@faker-js/faker";
|
|
10
|
+
describe("Widget Header Component", () => {
|
|
11
|
+
it("title renders", async () => {
|
|
12
|
+
// Arrange
|
|
13
|
+
const fakeTitle = faker.word.interjection();
|
|
14
|
+
// Act
|
|
15
|
+
render(React.createElement(WidgetHeader, { title: fakeTitle }));
|
|
16
|
+
// Assert
|
|
17
|
+
const title = screen.getByText(fakeTitle);
|
|
18
|
+
expect(title).toHaveTextContent(fakeTitle);
|
|
19
|
+
});
|
|
20
|
+
it("header allows return callback", async () => {
|
|
21
|
+
// Arrange
|
|
22
|
+
const mockReturnFn = jest.fn();
|
|
23
|
+
// Act
|
|
24
|
+
const { user, container } = render(React.createElement(WidgetHeader, { title: "", returnFn: mockReturnFn }));
|
|
25
|
+
// Assert
|
|
26
|
+
const returnBtn = container.getElementsByClassName("gmw-chevron")[0];
|
|
27
|
+
await user.click(returnBtn);
|
|
28
|
+
expect(mockReturnFn).toHaveBeenCalledTimes(1);
|
|
29
|
+
});
|
|
30
|
+
});
|
|
31
|
+
//# sourceMappingURL=WidgetHeader.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"WidgetHeader.test.js","sourceRoot":"","sources":["../../../src/test/WidgetHeader.test.tsx"],"names":[],"mappings":"AAAA;;;+FAG+F;AAC/F,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,2BAA2B,CAAC;AACnC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAC;AACpD,OAAO,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAC;AAC1D,OAAO,EAAE,KAAK,EAAE,MAAM,iBAAiB,CAAC;AAExC,QAAQ,CAAC,yBAAyB,EAAE,GAAG,EAAE;IACvC,EAAE,CAAC,eAAe,EAAE,KAAK,IAAI,EAAE;QAC7B,UAAU;QACV,MAAM,SAAS,GAAG,KAAK,CAAC,IAAI,CAAC,YAAY,EAAE,CAAC;QAE5C,MAAM;QACN,MAAM,CAAC,oBAAC,YAAY,IAAC,KAAK,EAAE,SAAS,GAAI,CAAC,CAAC;QAE3C,SAAS;QACT,MAAM,KAAK,GAAG,MAAM,CAAC,SAAS,CAAC,SAAS,CAAC,CAAC;QAC1C,MAAM,CAAC,KAAK,CAAC,CAAC,iBAAiB,CAAC,SAAS,CAAC,CAAC;IAC7C,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,+BAA+B,EAAE,KAAK,IAAI,EAAE;QAC7C,UAAU;QACV,MAAM,YAAY,GAAG,IAAI,CAAC,EAAE,EAAE,CAAC;QAE/B,MAAM;QACN,MAAM,EAAE,IAAI,EAAE,SAAS,EAAE,GAAG,MAAM,CAAC,oBAAC,YAAY,IAAC,KAAK,EAAC,EAAE,EAAC,QAAQ,EAAE,YAAY,GAAI,CAAC,CAAC;QAEtF,SAAS;QACT,MAAM,SAAS,GAAG,SAAS,CAAC,sBAAsB,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,CAAC;QACrE,MAAM,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC;QAC5B,MAAM,CAAC,YAAY,CAAC,CAAC,qBAAqB,CAAC,CAAC,CAAC,CAAC;IAChD,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC","sourcesContent":["/*---------------------------------------------------------------------------------------------\n* Copyright (c) Bentley Systems, Incorporated. All rights reserved.\n* See LICENSE.md in the project root for license terms and full copyright notice.\n*--------------------------------------------------------------------------------------------*/\nimport React from \"react\";\nimport \"@testing-library/jest-dom\";\nimport { render, screen } from \"../test/test-utils\";\nimport { WidgetHeader } from \"../widget/components/utils\";\nimport { faker } from \"@faker-js/faker\";\n\ndescribe(\"Widget Header Component\", () => {\n it(\"title renders\", async () => {\n // Arrange\n const fakeTitle = faker.word.interjection();\n\n // Act\n render(<WidgetHeader title={fakeTitle} />);\n\n // Assert\n const title = screen.getByText(fakeTitle);\n expect(title).toHaveTextContent(fakeTitle);\n });\n\n it(\"header allows return callback\", async () => {\n // Arrange\n const mockReturnFn = jest.fn();\n\n // Act\n const { user, container } = render(<WidgetHeader title=\"\" returnFn={mockReturnFn} />);\n\n // Assert\n const returnBtn = container.getElementsByClassName(\"gmw-chevron\")[0];\n await user.click(returnBtn);\n expect(mockReturnFn).toHaveBeenCalledTimes(1);\n });\n});\n"]}
|