@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.
Files changed (78) hide show
  1. package/README.md +84 -0
  2. package/lib/cjs/grouping-mapping-widget.d.ts +1 -0
  3. package/lib/cjs/grouping-mapping-widget.js +3 -1
  4. package/lib/cjs/grouping-mapping-widget.js.map +1 -1
  5. package/lib/cjs/test/GroupingMappingCustomUI.test.d.ts +2 -0
  6. package/lib/cjs/test/GroupingMappingCustomUI.test.js +162 -0
  7. package/lib/cjs/test/GroupingMappingCustomUI.test.js.map +1 -0
  8. package/lib/cjs/test/WidgetHeader.test.d.ts +2 -0
  9. package/lib/cjs/test/WidgetHeader.test.js +36 -0
  10. package/lib/cjs/test/WidgetHeader.test.js.map +1 -0
  11. package/lib/cjs/test/test-utils.d.ts +72 -0
  12. package/lib/cjs/test/test-utils.js +71 -0
  13. package/lib/cjs/test/test-utils.js.map +1 -0
  14. package/lib/cjs/widget/components/GroupAction.d.ts +2 -1
  15. package/lib/cjs/widget/components/GroupAction.js +82 -75
  16. package/lib/cjs/widget/components/GroupAction.js.map +1 -1
  17. package/lib/cjs/widget/components/GroupAction.scss +1 -13
  18. package/lib/cjs/widget/components/Grouping.d.ts +5 -0
  19. package/lib/cjs/widget/components/Grouping.js +107 -44
  20. package/lib/cjs/widget/components/Grouping.js.map +1 -1
  21. package/lib/cjs/widget/components/Grouping.scss +18 -3
  22. package/lib/cjs/widget/components/GroupingMapping.d.ts +6 -1
  23. package/lib/cjs/widget/components/GroupingMapping.js +22 -9
  24. package/lib/cjs/widget/components/GroupingMapping.js.map +1 -1
  25. package/lib/cjs/widget/components/Mapping.scss +4 -5
  26. package/lib/cjs/widget/components/context/GroupingMappingCustomUIContext.d.ts +6 -0
  27. package/lib/cjs/widget/components/context/GroupingMappingCustomUIContext.js +25 -0
  28. package/lib/cjs/widget/components/context/GroupingMappingCustomUIContext.js.map +1 -0
  29. package/lib/cjs/widget/components/customUI/GroupingMappingCustomUI.d.ts +91 -0
  30. package/lib/cjs/widget/components/customUI/GroupingMappingCustomUI.js +9 -0
  31. package/lib/cjs/widget/components/customUI/GroupingMappingCustomUI.js.map +1 -0
  32. package/lib/cjs/widget/components/customUI/ManualGroupingCustomUI.d.ts +6 -0
  33. package/lib/cjs/widget/components/customUI/ManualGroupingCustomUI.js +31 -0
  34. package/lib/cjs/widget/components/customUI/ManualGroupingCustomUI.js.map +1 -0
  35. package/lib/cjs/widget/components/customUI/ManualGroupingCustomUI.scss +17 -0
  36. package/lib/cjs/widget/components/customUI/SearchGroupingCustomUI.d.ts +6 -0
  37. package/lib/cjs/widget/components/customUI/SearchGroupingCustomUI.js +97 -0
  38. package/lib/cjs/widget/components/customUI/SearchGroupingCustomUI.js.map +1 -0
  39. package/lib/cjs/widget/components/customUI/SearchGroupingCustomUI.scss +17 -0
  40. package/lib/esm/grouping-mapping-widget.d.ts +1 -0
  41. package/lib/esm/grouping-mapping-widget.js +1 -0
  42. package/lib/esm/grouping-mapping-widget.js.map +1 -1
  43. package/lib/esm/test/GroupingMappingCustomUI.test.d.ts +2 -0
  44. package/lib/esm/test/GroupingMappingCustomUI.test.js +138 -0
  45. package/lib/esm/test/GroupingMappingCustomUI.test.js.map +1 -0
  46. package/lib/esm/test/WidgetHeader.test.d.ts +2 -0
  47. package/lib/esm/test/WidgetHeader.test.js +31 -0
  48. package/lib/esm/test/WidgetHeader.test.js.map +1 -0
  49. package/lib/esm/test/test-utils.d.ts +72 -0
  50. package/lib/esm/test/test-utils.js +42 -0
  51. package/lib/esm/test/test-utils.js.map +1 -0
  52. package/lib/esm/widget/components/GroupAction.d.ts +2 -1
  53. package/lib/esm/widget/components/GroupAction.js +85 -78
  54. package/lib/esm/widget/components/GroupAction.js.map +1 -1
  55. package/lib/esm/widget/components/GroupAction.scss +1 -13
  56. package/lib/esm/widget/components/Grouping.d.ts +5 -0
  57. package/lib/esm/widget/components/Grouping.js +107 -44
  58. package/lib/esm/widget/components/Grouping.js.map +1 -1
  59. package/lib/esm/widget/components/Grouping.scss +18 -3
  60. package/lib/esm/widget/components/GroupingMapping.d.ts +6 -1
  61. package/lib/esm/widget/components/GroupingMapping.js +23 -10
  62. package/lib/esm/widget/components/GroupingMapping.js.map +1 -1
  63. package/lib/esm/widget/components/Mapping.scss +4 -5
  64. package/lib/esm/widget/components/context/GroupingMappingCustomUIContext.d.ts +6 -0
  65. package/lib/esm/widget/components/context/GroupingMappingCustomUIContext.js +20 -0
  66. package/lib/esm/widget/components/context/GroupingMappingCustomUIContext.js.map +1 -0
  67. package/lib/esm/widget/components/customUI/GroupingMappingCustomUI.d.ts +91 -0
  68. package/lib/esm/widget/components/customUI/GroupingMappingCustomUI.js +6 -0
  69. package/lib/esm/widget/components/customUI/GroupingMappingCustomUI.js.map +1 -0
  70. package/lib/esm/widget/components/customUI/ManualGroupingCustomUI.d.ts +6 -0
  71. package/lib/esm/widget/components/customUI/ManualGroupingCustomUI.js +26 -0
  72. package/lib/esm/widget/components/customUI/ManualGroupingCustomUI.js.map +1 -0
  73. package/lib/esm/widget/components/customUI/ManualGroupingCustomUI.scss +17 -0
  74. package/lib/esm/widget/components/customUI/SearchGroupingCustomUI.d.ts +6 -0
  75. package/lib/esm/widget/components/customUI/SearchGroupingCustomUI.js +92 -0
  76. package/lib/esm/widget/components/customUI/SearchGroupingCustomUI.js.map +1 -0
  77. package/lib/esm/widget/components/customUI/SearchGroupingCustomUI.scss +17 -0
  78. package/package.json +17 -3
@@ -0,0 +1,20 @@
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 { createContext, useContext } from "react";
6
+ export const createGroupingMappingCustomUI = (customUIs) => {
7
+ if (undefined === customUIs) {
8
+ return [];
9
+ }
10
+ return customUIs;
11
+ };
12
+ export const GroupingMappingCustomUIContext = createContext([]);
13
+ export const useGroupingMappingCustomUI = () => {
14
+ const context = useContext(GroupingMappingCustomUIContext);
15
+ if (!context) {
16
+ throw new Error("useGroupingMappingCustomUI should be used within a GroupingMappingCustomUIContext provider");
17
+ }
18
+ return context;
19
+ };
20
+ //# 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,OAAO,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,OAAO,CAAC;AAGlD,MAAM,CAAC,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;AAEF,MAAM,CAAC,MAAM,8BAA8B,GAAG,aAAa,CAA4B,EAAE,CAAC,CAAC;AAE3F,MAAM,CAAC,MAAM,0BAA0B,GAAG,GAAG,EAAE;IAC7C,MAAM,OAAO,GAAG,UAAU,CAAC,8BAA8B,CAAC,CAAC;IAC3D,IAAI,CAAC,OAAO,EAAE;QACZ,MAAM,IAAI,KAAK,CACb,4FAA4F,CAC7F,CAAC;KACH;IACD,OAAO,OAAO,CAAC;AACjB,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 { 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,6 @@
1
+ export var GroupingMappingCustomUIType;
2
+ (function (GroupingMappingCustomUIType) {
3
+ GroupingMappingCustomUIType[GroupingMappingCustomUIType["Grouping"] = 0] = "Grouping";
4
+ GroupingMappingCustomUIType[GroupingMappingCustomUIType["Context"] = 1] = "Context";
5
+ })(GroupingMappingCustomUIType || (GroupingMappingCustomUIType = {}));
6
+ //# sourceMappingURL=GroupingMappingCustomUI.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"GroupingMappingCustomUI.js","sourceRoot":"","sources":["../../../../../src/widget/components/customUI/GroupingMappingCustomUI.ts"],"names":[],"mappings":"AAMA,MAAM,CAAN,IAAY,2BAGX;AAHD,WAAY,2BAA2B;IACrC,qFAAQ,CAAA;IACR,mFAAO,CAAA;AACT,CAAC,EAHW,2BAA2B,KAA3B,2BAA2B,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,26 @@
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 { Button, LabeledTextarea, Text } from "@itwin/itwinui-react";
7
+ import { LoadingSpinner } from "../utils";
8
+ import "./ManualGroupingCustomUI.scss";
9
+ const ManualGroupingCustomUI = ({ updateQuery, isUpdating, resetView, }) => {
10
+ const [manualInput, setManualInput] = React.useState("");
11
+ return (React.createElement("div", { className: 'gmw-manual-form' },
12
+ React.createElement(Text, null, "Generate group using an ECSQL query. Please select ECInstanceId and ECClassId columns in the query."),
13
+ React.createElement(LabeledTextarea, { label: 'Query', required: true, value: manualInput, onChange: (event) => setManualInput(event.target.value), disabled: isUpdating, placeholder: `E.g. "SELECT ECInstanceId, ECClassId FROM BisCore:PhysicalElement"` }),
14
+ React.createElement("div", { className: 'gmw-manual-actions' },
15
+ isUpdating && React.createElement(LoadingSpinner, null),
16
+ React.createElement(Button, { disabled: isUpdating, onClick: () => updateQuery(manualInput) }, "Apply"),
17
+ React.createElement(Button, { disabled: isUpdating, onClick: async () => {
18
+ updateQuery("");
19
+ setManualInput("");
20
+ if (resetView) {
21
+ await resetView();
22
+ }
23
+ } }, "Clear"))));
24
+ };
25
+ export default ManualGroupingCustomUI;
26
+ //# 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,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,MAAM,EAAE,eAAe,EAAE,IAAI,EAAE,MAAM,sBAAsB,CAAC;AACrE,OAAO,EAAE,cAAc,EAAE,MAAM,UAAU,CAAC;AAC1C,OAAO,+BAA+B,CAAC;AAGvC,MAAM,sBAAsB,GAAG,CAAC,EAC9B,WAAW,EACX,UAAU,EACV,SAAS,GACa,EAAE,EAAE;IAC1B,MAAM,CAAC,WAAW,EAAE,cAAc,CAAC,GAAG,KAAK,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;IAEzD,OAAO,CACL,6BAAK,SAAS,EAAC,iBAAiB;QAC9B,oBAAC,IAAI,8GAEE;QACP,oBAAC,eAAe,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,6BAAK,SAAS,EAAC,oBAAoB;YAChC,UAAU,IAAI,oBAAC,cAAc,OAAG;YACjC,oBAAC,MAAM,IAAC,QAAQ,EAAE,UAAU,EAAE,OAAO,EAAE,GAAG,EAAE,CAAC,WAAW,CAAC,WAAW,CAAC,YAE5D;YACT,oBAAC,MAAM,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,eAAe,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,92 @@
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 { Button, LabeledTextarea, Text } from "@itwin/itwinui-react";
7
+ import { LoadingSpinner } from "../utils";
8
+ import "./SearchGroupingCustomUI.scss";
9
+ const SearchGroupingCustomUI = ({ updateQuery, isUpdating, resetView, }) => {
10
+ const [searchInput, setSearchInput] = React.useState("");
11
+ const isWrappedInQuotes = (text) => {
12
+ return text.startsWith(`"`) && text.endsWith(`"`);
13
+ };
14
+ const needsAndOperator = (token, index, searchQuery) => isWrappedInQuotes(token) ||
15
+ (index === 1 && isWrappedInQuotes(searchQuery[0]));
16
+ const generateSearchQuery = (searchQuery) => {
17
+ if (searchQuery.length === 0) {
18
+ updateQuery("");
19
+ return;
20
+ }
21
+ let generatedSearchQuery = `SELECT be.ECInstanceId, be.ECClassId FROM bis.geometricelement3d be `;
22
+ generatedSearchQuery += `LEFT JOIN bis.SpatialCategory cat ON be.Category.Id = cat.ECInstanceID LEFT JOIN ecdbmeta.ECClassDef ecc ON be.ECClassId = ecc.ECInstanceId `;
23
+ generatedSearchQuery += `LEFT JOIN bis.PhysicalType pt ON be.TypeDefinition.Id = pt.ECInstanceID`;
24
+ generatedSearchQuery += ` WHERE `;
25
+ generatedSearchQuery += `((${searchQuery
26
+ .map((token, index) => `${index === 0
27
+ ? ""
28
+ : needsAndOperator(token, index, searchQuery)
29
+ ? "AND"
30
+ : "OR"} be.codevalue LIKE '%${isWrappedInQuotes(token) ? token.slice(1, -1) : token}%'`)
31
+ .join(" ")}) OR (${searchQuery
32
+ .map((token, index) => `${index === 0
33
+ ? ""
34
+ : needsAndOperator(token, index, searchQuery)
35
+ ? "AND"
36
+ : "OR"} be.userlabel LIKE '%${isWrappedInQuotes(token) ? token.slice(1, -1) : token}%'`)
37
+ .join(" ")})) OR ((${searchQuery
38
+ .map((token, index) => `${index === 0
39
+ ? ""
40
+ : needsAndOperator(token, index, searchQuery)
41
+ ? "AND"
42
+ : "OR"} cat.codevalue LIKE '%${isWrappedInQuotes(token) ? token.slice(1, -1) : token}%'`)
43
+ .join(" ")}) OR (${searchQuery
44
+ .map((token, index) => `${index === 0
45
+ ? ""
46
+ : needsAndOperator(token, index, searchQuery)
47
+ ? "AND"
48
+ : "OR"} cat.userlabel LIKE '%${isWrappedInQuotes(token) ? token.slice(1, -1) : token}%'`)
49
+ .join(" ")})) OR (${searchQuery
50
+ .map((token, index) => `${index === 0
51
+ ? ""
52
+ : needsAndOperator(token, index, searchQuery)
53
+ ? "AND"
54
+ : "OR"} ecc.name LIKE '%${isWrappedInQuotes(token) ? token.slice(1, -1) : token}%'`)
55
+ .join(" ")})`;
56
+ // Physical Types
57
+ generatedSearchQuery += ` OR ((${searchQuery
58
+ .map((token, index) => `${index === 0
59
+ ? ""
60
+ : needsAndOperator(token, index, searchQuery)
61
+ ? "AND"
62
+ : "OR"} pt.codevalue LIKE '%${isWrappedInQuotes(token) ? token.slice(1, -1) : token}%'`)
63
+ .join(" ")}) OR (${searchQuery
64
+ .map((token, index) => `${index === 0
65
+ ? ""
66
+ : needsAndOperator(token, index, searchQuery)
67
+ ? "AND"
68
+ : "OR"} pt.userlabel LIKE '%${isWrappedInQuotes(token) ? token.slice(1, -1) : token}%'`)
69
+ .join(" ")})) `;
70
+ updateQuery(generatedSearchQuery);
71
+ };
72
+ return (React.createElement("div", { className: 'gmw-search-form' },
73
+ React.createElement(Text, null, "Generate a query by keywords. Keywords wrapped in double quotes will be considered a required criteria."),
74
+ React.createElement(LabeledTextarea, { label: 'Query Keywords', required: true, value: searchInput, onChange: (event) => setSearchInput(event.target.value), disabled: isUpdating, placeholder: `E.g. "red" chair` }),
75
+ React.createElement("div", { className: 'gmw-search-actions' },
76
+ isUpdating && React.createElement(LoadingSpinner, null),
77
+ React.createElement(Button, { disabled: isUpdating, onClick: () => generateSearchQuery(searchInput
78
+ ? searchInput
79
+ .replace(/(\r\n|\n|\r)/gm, "")
80
+ .trim()
81
+ .split(" ")
82
+ : []) }, "Apply"),
83
+ React.createElement(Button, { disabled: isUpdating, onClick: async () => {
84
+ updateQuery("");
85
+ setSearchInput("");
86
+ if (resetView) {
87
+ await resetView();
88
+ }
89
+ } }, "Clear"))));
90
+ };
91
+ export default SearchGroupingCustomUI;
92
+ //# 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
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@itwin/grouping-mapping-widget",
3
- "version": "0.6.0",
3
+ "version": "0.7.0",
4
4
  "description": "An iTwin.js 3D Viewer Widget that interfaces with the iTwin Reporting Platform.",
5
5
  "keywords": [
6
6
  "Bentley",
@@ -46,6 +46,7 @@
46
46
  "simple-react-validator": "^1.6.1"
47
47
  },
48
48
  "devDependencies": {
49
+ "@faker-js/faker": "^7.5.0",
49
50
  "@itwin/appui-abstract": "^3.2.0",
50
51
  "@itwin/appui-layout-react": "^3.2.0",
51
52
  "@itwin/appui-react": "^3.2.0",
@@ -66,12 +67,18 @@
66
67
  "@itwin/presentation-components": "^3.2.0",
67
68
  "@itwin/presentation-frontend": "^3.2.0",
68
69
  "@itwin/webgl-compatibility": "^3.2.0",
70
+ "@testing-library/dom": "^8.12.0",
71
+ "@testing-library/jest-dom": "^5.16.3",
72
+ "@testing-library/react": "^12.1.4",
73
+ "@testing-library/user-event": "^14.1.1",
69
74
  "@types/i18next": "^8.4.2",
75
+ "@types/jest": "^27.4.1",
70
76
  "@types/node": "^14.14.20",
71
77
  "@types/react": "^17.0.19",
72
78
  "@types/react-dom": "^17.0.9",
73
79
  "@types/react-redux": "^7.0.1",
74
80
  "@types/react-table": "^7.7.0",
81
+ "@types/testing-library__jest-dom": "^5.14.3",
75
82
  "@typescript-eslint/eslint-plugin": "^5.3.1",
76
83
  "@typescript-eslint/parser": "^5.10.1",
77
84
  "cpx2": "^3.0.0",
@@ -79,12 +86,18 @@
79
86
  "eslint-plugin-node": "^11.1.0",
80
87
  "eslint-plugin-react": "^7.25.1",
81
88
  "eslint-plugin-react-hooks": "^4.2.0",
89
+ "jest": "^27.5.1",
90
+ "jest-cli": "^27.5.1",
91
+ "jest-transform-stub": "^2.0.0",
92
+ "msw": "^0.39.2",
82
93
  "react": "^17.0.2",
83
94
  "react-dom": "^17.0.2",
84
95
  "react-redux": "^7.2.0",
85
96
  "react-table": "^7.7.0",
86
97
  "redux": "^4.1.0",
87
98
  "rimraf": "^3.0.2",
99
+ "ts-jest": "^27.1.3",
100
+ "typemoq": "^2.1.0",
88
101
  "typescript": "~4.3.0"
89
102
  },
90
103
  "peerDependencies": {
@@ -114,7 +127,8 @@
114
127
  "lint:fix": "npm run lint -- --fix",
115
128
  "pseudolocalize": "betools pseudolocalize --englishDir ./public/locales/en --out ./public/locales/en-PSEUDO",
116
129
  "rebuild": "npm run clean && npm run build",
117
- "test": ""
130
+ "test": "jest",
131
+ "test:watch": "jest --watch "
118
132
  },
119
- "readme": "# @itwin/grouping-mapping-widget\r\n\r\nCopyright © Bentley Systems, Incorporated. All rights reserved.\r\nThe Grouping Mapping widget is a UI component for iTwin Viewer applications that simplifies how users (and developers) interface with the [Reporting Platform APIs](https://developer.bentley.com/apis/insights/overview/).\r\nThe grouping-mapping-widget package provides a UiProvider class - `GroupingMappingProvider` - which can be passed into the `uiProviders` prop of the iTwin Viewer's `<Viewer />` component.\r\n\r\n## Getting Started\r\n\r\nThis is not a standalone UI and requires a parent iTwin Viewer application to work as intended.\r\nA guide on how to create a basic iTwin Viewer application can be found here: <https://www.itwinjs.org/learning/tutorials/develop-web-viewer/>.\r\nThis package provides a viewer 'widget'. Documentation on how to add a widget to your application can be found here: <https://developer.bentley.com/tutorials/itwin-viewer-hello-world/#2-your-first-ui-widget>.\r\n\r\n## Permissions and Scopes\r\n\r\nThe SPA client used by your iTwin viewer must have these additional scopes:\r\n\r\n- `insights:read`\r\n- `insights:modify`\r\n- `projects:read`\r\n\r\nIn addition, users must have the `imodels_read` and `imodels_write` [permissions](https://developer.bentley.com/apis/insights/operations/create-mapping/#authorization) assigned at either the Project or iModel level. Further instruction on how to create roles and assign permissions can be found in the [iTwin Platform Projects API documentation](https://developer.bentley.com/apis/projects/tutorials/).\r\n\r\n## Sample usage\r\n\r\n```tsx\r\nimport { GroupingMappingProvider } from \"@itwin/grouping-mapping-widget\";\r\n<Viewer\r\n ...\r\n uiProviders={[new GroupingMappingProvider()]}\r\n/>\r\n```\r\n"
133
+ "readme": "# @itwin/grouping-mapping-widget\r\n\r\nCopyright © Bentley Systems, Incorporated. All rights reserved.\r\nThe Grouping Mapping widget is a UI component for iTwin Viewer applications that simplifies how users (and developers) interface with the [Reporting Platform APIs](https://developer.bentley.com/apis/insights/overview/).\r\nThe grouping-mapping-widget package provides a UiProvider class - `GroupingMappingProvider` - which can be passed into the `uiProviders` prop of the iTwin Viewer's `<Viewer />` component.\r\n\r\n## Getting Started\r\n\r\nThis is not a standalone UI and requires a parent iTwin Viewer application to work as intended.\r\nA guide on how to create a basic iTwin Viewer application can be found here: <https://www.itwinjs.org/learning/tutorials/develop-web-viewer/>.\r\nThis package provides a viewer 'widget'. Documentation on how to add a widget to your application can be found here: <https://developer.bentley.com/tutorials/itwin-viewer-hello-world/#2-your-first-ui-widget>.\r\n\r\n## Permissions and Scopes\r\n\r\nThe SPA client used by your iTwin viewer must have these additional scopes:\r\n\r\n- `insights:read`\r\n- `insights:modify`\r\n- `projects:read`\r\n\r\nIn addition, users must have the `imodels_read` and `imodels_write` [permissions](https://developer.bentley.com/apis/insights/operations/create-mapping/#authorization) assigned at either the Project or iModel level. Further instruction on how to create roles and assign permissions can be found in the [iTwin Platform Projects API documentation](https://developer.bentley.com/apis/projects/tutorials/).\r\n\r\n## Sample usage\r\n\r\n```tsx\r\nimport { GroupingMappingProvider } from \"@itwin/grouping-mapping-widget\";\r\n<Viewer\r\n ...\r\n uiProviders={[new GroupingMappingProvider()]}\r\n/>\r\n```\r\n\r\n## Custom UI\r\n\r\nThis package provides an interface to define your own custom UI or callback functions in grouping mapping widget. There are different types of custom UIs provided.\r\n\r\n### Grouping Custom UI\r\n\r\nYou can use your own UI component to define group creation method.\r\n\r\nAn example of grouping custom UI, [ManualGroupingCustomUI](https://github.com/iTwin/viewer-components-react/blob/master/packages/itwin/grouping-mapping-widget/src/widget/components/customUI/ManualGroupingCustomUI.tsx) helps user to manually define ECSQL query for groups.\r\n\r\nIn `GroupingCustomUIProps`:\r\n\r\n- `updateQuery` is used to run the query and visualize results in the viewer.\r\n- `isUpdating` keeps track of the status of query execution.\r\n- `resetView` enables you to reset the viewer state.\r\n\r\nTo configure your own grouping custom UI, you need to give it:\r\n\r\n- a `type` as `GroupingMappingCustomUIType.Grouping`\r\n- a `name` as identifier\r\n- a `displayLabel` which will be shown in the 'Add Group' dropdown list\r\n- a `uiComponent` like above\r\n- an optional `icon`\r\n\r\nYou can define your UI provider as follows in the GroupingMappingProvider:\r\n\r\n```tsx\r\nnew GroupingMappingProvider({\r\n customUIs: [\r\n {\r\n type: GroupingMappingCustomUIType.Grouping,\r\n name: \"Manual\",\r\n displayLabel: \"Manual Query\",\r\n uiComponent: ManualGroupingCustomUI,\r\n icon: <SvgDraw />,\r\n },\r\n ],\r\n});\r\n```\r\n\r\nAfter adding the grouping custom UI, it will be presented in the 'Add Group' drop down list.\r\n\r\n![Process Functional Grouping Menu Item](./assets/ProcessGroupingMenuItem.jpg)\r\n\r\n### Context Custom UI\r\n\r\nYou can also add custom UI in context menu for each group. This could be UI driven interaction or simply a callback function to execute your own code.\r\n\r\nYou can use the `iModelId`, `mappingId` and `groupId` in `ContextCustomUIProps` provided by Grouping Mapping Widget in your UI component or callback.\r\n\r\nTo configure your own context custom UI, you need to give it:\r\n\r\n- a `type` as `GroupingMappingCustomUIType.Context`\r\n- a `name` as identifier\r\n- a `displayLabel` which will be shown in the context dropdown list in each group tile\r\n- an optional `uiComponent` which will be presented in the widget as a UI component\r\n- an optional `onClick` callback function where you could make your own API calls\r\n- an optional `icon`\r\n\r\nYou can define your context custom UI as following example in the GroupingMappingProvider with an example is to use [clash detection](https://www.itwinjs.org/sandboxes/iTwinPlatform/Clash%20Review) in the widget:\r\n\r\n```tsx\r\nconst customCB = (groupId: string, mappingId: string, iModelId: string) => {\r\n toaster.informational(`Called callback for group ${groupId}`)\r\n}\r\n\r\nnew GroupingMappingProvider({\r\n customUIs: [\r\n {\r\n type: GroupingMappingCustomUIType.Context,\r\n name: \"ClashDetection\",\r\n displayLabel: \"Clash Detection\",\r\n uiComponent: ClashDetectionCustomUI,\r\n onClick: customCB,\r\n icon: <SvgClash />,\r\n },\r\n ],\r\n});\r\n```\r\n\r\nAfter adding the context custom UI, the context menu item will look like this with additional `Clash Detection` menu item.\r\n\r\n![Clash Detection Context Menu Item](./assets/ClashDetectionContextMenuItem.jpg)\r\n"
120
134
  }