@itwin/one-click-lca-react 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE.md +9 -0
- package/README.md +28 -0
- package/lib/cjs/components/ExportModal.d.ts +10 -0
- package/lib/cjs/components/ExportModal.js +169 -0
- package/lib/cjs/components/ExportModal.js.map +1 -0
- package/lib/cjs/components/ExportModal.scss +85 -0
- package/lib/cjs/components/OneClickLCA.d.ts +5 -0
- package/lib/cjs/components/OneClickLCA.js +13 -0
- package/lib/cjs/components/OneClickLCA.js.map +1 -0
- package/lib/cjs/components/Reports.d.ts +5 -0
- package/lib/cjs/components/Reports.js +105 -0
- package/lib/cjs/components/Reports.js.map +1 -0
- package/lib/cjs/components/Reports.scss +44 -0
- package/lib/cjs/components/utils.d.ts +9 -0
- package/lib/cjs/components/utils.js +16 -0
- package/lib/cjs/components/utils.js.map +1 -0
- package/lib/cjs/components/utils.scss +35 -0
- package/lib/cjs/one-click-lca-widget.d.ts +3 -0
- package/lib/cjs/one-click-lca-widget.js +19 -0
- package/lib/cjs/one-click-lca-widget.js.map +1 -0
- package/lib/cjs/test/ExportModal.test.d.ts +2 -0
- package/lib/cjs/test/ExportModal.test.js +17 -0
- package/lib/cjs/test/ExportModal.test.js.map +1 -0
- package/lib/cjs/test/WidgetHeader.test.d.ts +2 -0
- package/lib/cjs/test/WidgetHeader.test.js +37 -0
- package/lib/cjs/test/WidgetHeader.test.js.map +1 -0
- package/lib/cjs/widgets/OneClickLCAWidget.d.ts +7 -0
- package/lib/cjs/widgets/OneClickLCAWidget.js +32 -0
- package/lib/cjs/widgets/OneClickLCAWidget.js.map +1 -0
- package/lib/esm/components/ExportModal.d.ts +10 -0
- package/lib/esm/components/ExportModal.js +164 -0
- package/lib/esm/components/ExportModal.js.map +1 -0
- package/lib/esm/components/ExportModal.scss +85 -0
- package/lib/esm/components/OneClickLCA.d.ts +5 -0
- package/lib/esm/components/OneClickLCA.js +8 -0
- package/lib/esm/components/OneClickLCA.js.map +1 -0
- package/lib/esm/components/Reports.d.ts +5 -0
- package/lib/esm/components/Reports.js +100 -0
- package/lib/esm/components/Reports.js.map +1 -0
- package/lib/esm/components/Reports.scss +44 -0
- package/lib/esm/components/utils.d.ts +9 -0
- package/lib/esm/components/utils.js +12 -0
- package/lib/esm/components/utils.js.map +1 -0
- package/lib/esm/components/utils.scss +35 -0
- package/lib/esm/one-click-lca-widget.d.ts +3 -0
- package/lib/esm/one-click-lca-widget.js +7 -0
- package/lib/esm/one-click-lca-widget.js.map +1 -0
- package/lib/esm/test/ExportModal.test.d.ts +2 -0
- package/lib/esm/test/ExportModal.test.js +12 -0
- package/lib/esm/test/ExportModal.test.js.map +1 -0
- package/lib/esm/test/WidgetHeader.test.d.ts +2 -0
- package/lib/esm/test/WidgetHeader.test.js +35 -0
- package/lib/esm/test/WidgetHeader.test.js.map +1 -0
- package/lib/esm/widgets/OneClickLCAWidget.d.ts +7 -0
- package/lib/esm/widgets/OneClickLCAWidget.js +25 -0
- package/lib/esm/widgets/OneClickLCAWidget.js.map +1 -0
- package/lib/public/logo/oneClickLCALogo.png +0 -0
- package/package.json +107 -0
package/LICENSE.md
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
# MIT License
|
|
2
|
+
|
|
3
|
+
Copyright © 2022 Bentley Systems, Inc. All rights reserved.
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
|
6
|
+
|
|
7
|
+
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
|
8
|
+
|
|
9
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# @itwin/one-click-lca-react
|
|
2
|
+
|
|
3
|
+
Copyright © Bentley Systems, Incorporated. All rights reserved.
|
|
4
|
+
|
|
5
|
+
The One Click CLA widget is a UI component for iTwin Viewer applications that simplifies how users (and developers) interface with the [Carbon Calculation One Click LCA APIs](https://developer.bentley.com/apis/carbon-calculation/overview/).
|
|
6
|
+
The one-click-lca-react package provides a UiProvider class, `OneClickLCAProvider`, which can be passed into the `uiProviders` prop of the iTwin Viewer's `<Viewer />` component.
|
|
7
|
+
|
|
8
|
+
## Getting Started
|
|
9
|
+
|
|
10
|
+
This is not a standalone UI and requires a parent iTwin Viewer application to work as intended.
|
|
11
|
+
A guide on how to create a basic iTwin Viewer application can be found [here](https://www.itwinjs.org/learning/tutorials/develop-web-viewer).
|
|
12
|
+
This 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).
|
|
13
|
+
|
|
14
|
+
## Permissions and Scopes
|
|
15
|
+
|
|
16
|
+
The SPA client used by your iTwin viewer application must have allowed scopes `insights:read` and `insights:write`, found under the Reporting & Insights category.
|
|
17
|
+
Users must have the `imodels_read` and `insights_view` [permissions](https://developer.bentley.com/apis/carbon-calculation/operations/create-oneclicklca-job/#authorization) assigned at either the Project or iModel level. Additional 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/).
|
|
18
|
+
|
|
19
|
+
## Sample usage
|
|
20
|
+
|
|
21
|
+
```tsx
|
|
22
|
+
import { OneClickLCAProvider } from "@itwin/one-click-lca-widget";
|
|
23
|
+
|
|
24
|
+
<Viewer
|
|
25
|
+
...
|
|
26
|
+
uiProviders={[new OneClickLCAProvider()]}
|
|
27
|
+
/>
|
|
28
|
+
```
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/// <reference types="react" />
|
|
2
|
+
import "./ExportModal.scss";
|
|
3
|
+
interface ExportProps {
|
|
4
|
+
isOpen: boolean;
|
|
5
|
+
close: () => void;
|
|
6
|
+
reportId: string | undefined;
|
|
7
|
+
}
|
|
8
|
+
declare const ExportModal: (props: ExportProps) => JSX.Element;
|
|
9
|
+
export default ExportModal;
|
|
10
|
+
//# sourceMappingURL=ExportModal.d.ts.map
|
|
@@ -0,0 +1,169 @@
|
|
|
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
|
+
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
7
|
+
/*---------------------------------------------------------------------------------------------
|
|
8
|
+
* Copyright (c) Bentley Systems, Incorporated. All rights reserved.
|
|
9
|
+
* See LICENSE.md in the project root for license terms and full copyright notice.
|
|
10
|
+
*--------------------------------------------------------------------------------------------*/
|
|
11
|
+
require("./ExportModal.scss");
|
|
12
|
+
const react_1 = require("react");
|
|
13
|
+
const core_frontend_1 = require("@itwin/core-frontend");
|
|
14
|
+
const itwinui_react_1 = require("@itwin/itwinui-react");
|
|
15
|
+
const itwinui_icons_react_1 = require("@itwin/itwinui-icons-react");
|
|
16
|
+
const insights_client_1 = require("@itwin/insights-client");
|
|
17
|
+
const oneClickLCALogo_png_1 = __importDefault(require("../../public/logo/oneClickLCALogo.png"));
|
|
18
|
+
const ExportModal = (props) => {
|
|
19
|
+
const MILI_SECONDS = 1000;
|
|
20
|
+
const PIN_INTERVAL = 1000;
|
|
21
|
+
const oneClickLCAClientApi = react_1.useMemo(() => new insights_client_1.OneClickLCAClient(), []);
|
|
22
|
+
const [email, setEmail] = react_1.useState("");
|
|
23
|
+
const [password, setPassword] = react_1.useState("");
|
|
24
|
+
const [passwordIsVisible, showPassword] = react_1.useState(false);
|
|
25
|
+
const [signinError, showSigninError] = react_1.useState(false);
|
|
26
|
+
const [emailError, setEmailError] = react_1.useState(false);
|
|
27
|
+
const [cache, cacheToken] = react_1.useState();
|
|
28
|
+
const [jobStatus, setJobStatus] = react_1.useState();
|
|
29
|
+
const [jobLink, setJobLink] = react_1.useState();
|
|
30
|
+
const isValidEmail = react_1.useCallback(() => {
|
|
31
|
+
return /\S+@\S+\.\S+/.test(email);
|
|
32
|
+
}, [email]);
|
|
33
|
+
const isValidPassword = react_1.useCallback(() => {
|
|
34
|
+
return password !== "";
|
|
35
|
+
}, [password]);
|
|
36
|
+
const validateSignin = react_1.useCallback(() => {
|
|
37
|
+
return (cache === null || cache === void 0 ? void 0 : cache.token) && (cache === null || cache === void 0 ? void 0 : cache.exp) > Date.now();
|
|
38
|
+
}, [cache]);
|
|
39
|
+
const [isSignedIn, setIsSignedIn] = react_1.useState(validateSignin());
|
|
40
|
+
const [isSigningIn, startSigningIn] = react_1.useState(false);
|
|
41
|
+
const intervalRef = react_1.useRef();
|
|
42
|
+
const isValidSignin = react_1.useCallback(() => {
|
|
43
|
+
return isValidEmail() && isValidPassword();
|
|
44
|
+
}, [isValidEmail, isValidPassword]);
|
|
45
|
+
const resetSignin = react_1.useCallback(() => {
|
|
46
|
+
setEmail("");
|
|
47
|
+
setPassword("");
|
|
48
|
+
showPassword(false);
|
|
49
|
+
showSigninError(false);
|
|
50
|
+
}, [setEmail, setPassword, showPassword, showSigninError]);
|
|
51
|
+
const pinStatus = react_1.useCallback((job) => {
|
|
52
|
+
const intervalId = window.setInterval(async () => {
|
|
53
|
+
var _a, _b, _c, _d, _e, _f;
|
|
54
|
+
const token = (_b = (await ((_a = core_frontend_1.IModelApp.authorizationClient) === null || _a === void 0 ? void 0 : _a.getAccessToken()))) !== null && _b !== void 0 ? _b : "";
|
|
55
|
+
if (job.id && token) {
|
|
56
|
+
const currentJobStatus = await oneClickLCAClientApi.getOneclicklcaJobStatus(token, job === null || job === void 0 ? void 0 : job.id);
|
|
57
|
+
if ((_c = currentJobStatus.job) === null || _c === void 0 ? void 0 : _c.status) {
|
|
58
|
+
if (((_d = currentJobStatus.job) === null || _d === void 0 ? void 0 : _d.status) === insights_client_1.JobStatus.StatusEnum.Succeeded) {
|
|
59
|
+
setJobLink((_e = currentJobStatus === null || currentJobStatus === void 0 ? void 0 : currentJobStatus.job._links) === null || _e === void 0 ? void 0 : _e.oneclicklca);
|
|
60
|
+
}
|
|
61
|
+
setJobStatus((_f = currentJobStatus.job) === null || _f === void 0 ? void 0 : _f.status);
|
|
62
|
+
}
|
|
63
|
+
else {
|
|
64
|
+
throw new Error("failed to get job status");
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
}, PIN_INTERVAL);
|
|
68
|
+
intervalRef.current = intervalId;
|
|
69
|
+
}, [setJobLink, setJobStatus, oneClickLCAClientApi]);
|
|
70
|
+
const runJob = react_1.useCallback(async (token) => {
|
|
71
|
+
var _a, _b, _c;
|
|
72
|
+
const accessToken = (_b = (await ((_a = core_frontend_1.IModelApp.authorizationClient) === null || _a === void 0 ? void 0 : _a.getAccessToken()))) !== null && _b !== void 0 ? _b : "";
|
|
73
|
+
if (props.reportId && token) {
|
|
74
|
+
try {
|
|
75
|
+
const jobCreated = await oneClickLCAClientApi.createOneclicklcaJob(accessToken, {
|
|
76
|
+
reportId: props.reportId,
|
|
77
|
+
token,
|
|
78
|
+
});
|
|
79
|
+
if ((_c = jobCreated === null || jobCreated === void 0 ? void 0 : jobCreated.job) === null || _c === void 0 ? void 0 : _c.id) {
|
|
80
|
+
pinStatus(jobCreated === null || jobCreated === void 0 ? void 0 : jobCreated.job);
|
|
81
|
+
}
|
|
82
|
+
else {
|
|
83
|
+
throw new Error("Failed to create job");
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
catch (e) {
|
|
87
|
+
throw new Error(`Failed to create one click lca job.${e}`);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
else {
|
|
91
|
+
throw new Error("No reportId or accessToken");
|
|
92
|
+
}
|
|
93
|
+
}, [props, pinStatus, oneClickLCAClientApi]);
|
|
94
|
+
const signin = react_1.useCallback(async (e) => {
|
|
95
|
+
e.preventDefault();
|
|
96
|
+
startSigningIn(true);
|
|
97
|
+
const result = await oneClickLCAClientApi.getOneclicklcaAccessToken(email, password);
|
|
98
|
+
if (result && result.access_token && result.expires_in) {
|
|
99
|
+
cacheToken({
|
|
100
|
+
token: result.access_token,
|
|
101
|
+
exp: Date.now() + result.expires_in * MILI_SECONDS,
|
|
102
|
+
});
|
|
103
|
+
resetSignin();
|
|
104
|
+
setIsSignedIn(true);
|
|
105
|
+
}
|
|
106
|
+
else {
|
|
107
|
+
showSigninError(true);
|
|
108
|
+
}
|
|
109
|
+
startSigningIn(false);
|
|
110
|
+
}, [
|
|
111
|
+
email,
|
|
112
|
+
password,
|
|
113
|
+
resetSignin,
|
|
114
|
+
cacheToken,
|
|
115
|
+
showSigninError,
|
|
116
|
+
oneClickLCAClientApi,
|
|
117
|
+
]);
|
|
118
|
+
const onClose = react_1.useCallback(() => {
|
|
119
|
+
resetSignin();
|
|
120
|
+
setJobStatus(undefined);
|
|
121
|
+
setJobLink(undefined);
|
|
122
|
+
if (intervalRef.current) {
|
|
123
|
+
window.clearInterval(intervalRef.current);
|
|
124
|
+
}
|
|
125
|
+
props.close();
|
|
126
|
+
}, [props, resetSignin]);
|
|
127
|
+
const getStatusComponent = react_1.useCallback((status, link) => {
|
|
128
|
+
switch (status) {
|
|
129
|
+
case insights_client_1.JobStatus.StatusEnum.Queued:
|
|
130
|
+
return (jsx_runtime_1.jsxs("div", Object.assign({ className: "oclca-progress-radial-container" }, { children: [jsx_runtime_1.jsx(itwinui_react_1.ProgressRadial, { indeterminate: true, size: "small", value: 50 }, void 0), jsx_runtime_1.jsx(itwinui_react_1.Text, Object.assign({ variant: "leading", className: "oclca-status-text" }, { children: "Export queued" }), void 0)] }), void 0));
|
|
131
|
+
case insights_client_1.JobStatus.StatusEnum.Running:
|
|
132
|
+
return (jsx_runtime_1.jsxs("div", Object.assign({ className: "oclca-progress-linear-container" }, { children: [jsx_runtime_1.jsx(itwinui_react_1.ProgressLinear, { indeterminate: true }, void 0), jsx_runtime_1.jsx(itwinui_react_1.Text, Object.assign({ variant: "leading", className: "oclca-status-text" }, { children: "Export running" }), void 0)] }), void 0));
|
|
133
|
+
case insights_client_1.JobStatus.StatusEnum.Succeeded:
|
|
134
|
+
return (link && (jsx_runtime_1.jsxs("div", Object.assign({ className: "oclca-progress-radial-container" }, { children: [jsx_runtime_1.jsx(itwinui_react_1.ProgressRadial, { status: "positive", size: "small", value: 50 }, void 0), jsx_runtime_1.jsx("a", Object.assign({ className: "oclca-report-button", href: link, target: "_blank", rel: "noopener noreferrer" }, { children: jsx_runtime_1.jsx(itwinui_react_1.Button, Object.assign({ styleType: "cta" }, { children: "Open in One Click LCA" }), void 0) }), void 0)] }), void 0)));
|
|
135
|
+
case insights_client_1.JobStatus.StatusEnum.Failed:
|
|
136
|
+
return (jsx_runtime_1.jsxs("div", Object.assign({ className: "oclca-progress-radial-container" }, { children: [jsx_runtime_1.jsx(itwinui_react_1.ProgressRadial, { status: "negative", size: "small", value: 100 }, void 0), jsx_runtime_1.jsx(itwinui_react_1.Text, Object.assign({ variant: "leading", className: "oclca-status-text" }, { children: "Export failed" }), void 0)] }), void 0));
|
|
137
|
+
default:
|
|
138
|
+
throw new Error(`Job status is invalid ${status}`);
|
|
139
|
+
}
|
|
140
|
+
}, []);
|
|
141
|
+
react_1.useEffect(() => {
|
|
142
|
+
if (props.isOpen && isSignedIn && (cache === null || cache === void 0 ? void 0 : cache.token)) {
|
|
143
|
+
runJob(cache.token).catch((err) => {
|
|
144
|
+
throw new Error(err);
|
|
145
|
+
});
|
|
146
|
+
}
|
|
147
|
+
}, [props.isOpen, isSignedIn, cache, runJob]);
|
|
148
|
+
react_1.useEffect(() => {
|
|
149
|
+
if (jobStatus === insights_client_1.JobStatus.StatusEnum.Succeeded ||
|
|
150
|
+
jobStatus === insights_client_1.JobStatus.StatusEnum.Failed) {
|
|
151
|
+
if (intervalRef.current) {
|
|
152
|
+
window.clearInterval(intervalRef.current);
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
}, [jobStatus]);
|
|
156
|
+
react_1.useEffect(() => {
|
|
157
|
+
if (email !== "") {
|
|
158
|
+
const timeoutId = setTimeout(() => setEmailError(!isValidEmail()), 1000);
|
|
159
|
+
return () => clearTimeout(timeoutId);
|
|
160
|
+
}
|
|
161
|
+
else {
|
|
162
|
+
setEmailError(false);
|
|
163
|
+
return;
|
|
164
|
+
}
|
|
165
|
+
}, [email, isValidEmail]);
|
|
166
|
+
return (jsx_runtime_1.jsxs(itwinui_react_1.Modal, Object.assign({ "data-testid": "export-modal", isOpen: props.isOpen, onClose: onClose, title: null, closeOnExternalClick: false }, { children: [!isSignedIn && (jsx_runtime_1.jsxs("div", Object.assign({ className: "oclca-signin" }, { children: [jsx_runtime_1.jsx("img", { className: "oclca-signin-icon", src: oneClickLCALogo_png_1.default, alt: "One Click LCA\u00AE software", "data-height-percentage": "80", "data-actual-width": "1200", "data-actual-height": "600" }, void 0), jsx_runtime_1.jsxs("form", Object.assign({ onSubmit: signin, className: "oclca-signin-form" }, { children: [jsx_runtime_1.jsx("div", Object.assign({ className: "oclca-signin-prompt" }, { children: "Sign in to One Click LCA." }), void 0), signinError && (jsx_runtime_1.jsx(itwinui_react_1.Alert, Object.assign({ type: "negative", className: "oclca-signin-error" }, { children: "Incorrect email or password." }), void 0)), jsx_runtime_1.jsx("div", Object.assign({ className: "oclca-signin-input" }, { children: jsx_runtime_1.jsx(itwinui_react_1.LabeledInput, { label: "Email", value: email, onChange: (v) => setEmail(v.target.value), type: "email", status: emailError ? "negative" : undefined, message: emailError ? "Invalid email address." : "", required: true }, void 0) }), void 0), jsx_runtime_1.jsx("div", Object.assign({ className: "oclca-signin-input" }, { children: jsx_runtime_1.jsx(itwinui_react_1.LabeledInput, { label: "Password", value: password, onChange: (e) => setPassword(e.target.value), type: passwordIsVisible ? "text" : "password", svgIcon: passwordIsVisible ? (jsx_runtime_1.jsx(itwinui_icons_react_1.SvgVisibilityHide, { onClick: () => showPassword(!passwordIsVisible) }, void 0)) : (jsx_runtime_1.jsx(itwinui_icons_react_1.SvgVisibilityShow, {}, void 0)), iconDisplayStyle: "inline", required: true }, void 0) }), void 0), jsx_runtime_1.jsx("div", Object.assign({ className: "oclca-signin-button-container" }, { children: jsx_runtime_1.jsx(itwinui_react_1.Button, Object.assign({ className: "oclca-signin-button", type: "submit", styleType: "cta", disabled: !isValidSignin() }, { children: isSigningIn ? (jsx_runtime_1.jsx(itwinui_react_1.ProgressRadial, { className: "oclca-signin-wait", indeterminate: true, size: "small", value: 50 }, void 0)) : ("Sign In") }), void 0) }), void 0)] }), void 0)] }), void 0)), isSignedIn && !jobStatus && (jsx_runtime_1.jsx("div", Object.assign({ className: "oclca-progress-radial-container" }, { children: jsx_runtime_1.jsx(itwinui_react_1.ProgressRadial, { indeterminate: true, size: "large", value: 50 }, void 0) }), void 0)), isSignedIn && jobStatus && getStatusComponent(jobStatus, jobLink === null || jobLink === void 0 ? void 0 : jobLink.href)] }), void 0));
|
|
167
|
+
};
|
|
168
|
+
exports.default = ExportModal;
|
|
169
|
+
//# sourceMappingURL=ExportModal.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ExportModal.js","sourceRoot":"","sources":["../../../src/components/ExportModal.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 \"./ExportModal.scss\";\nimport React, {\n useCallback,\n useEffect,\n useMemo,\n useRef,\n useState,\n} from \"react\";\nimport { IModelApp } from \"@itwin/core-frontend\";\nimport {\n Alert,\n Button,\n LabeledInput,\n Modal,\n ProgressLinear,\n ProgressRadial,\n Text,\n} from \"@itwin/itwinui-react\";\nimport {\n SvgVisibilityHide,\n SvgVisibilityShow,\n} from \"@itwin/itwinui-icons-react\";\nimport type { JobCreation, Link } from \"@itwin/insights-client\";\nimport { JobStatus, OneClickLCAClient } from \"@itwin/insights-client\";\nimport logo from \"../../public/logo/oneClickLCALogo.png\";\n\ninterface ExportProps {\n isOpen: boolean;\n close: () => void;\n reportId: string | undefined;\n}\n\ninterface OclcaTokenCache {\n token: string;\n exp: number;\n}\n\nconst ExportModal = (props: ExportProps) => {\n const MILI_SECONDS = 1000;\n const PIN_INTERVAL = 1000;\n const oneClickLCAClientApi = useMemo(() => new OneClickLCAClient(), []);\n\n const [email, setEmail] = useState(\"\");\n const [password, setPassword] = useState(\"\");\n const [passwordIsVisible, showPassword] = useState(false);\n const [signinError, showSigninError] = useState(false);\n const [emailError, setEmailError] = useState(false);\n const [cache, cacheToken] = useState<OclcaTokenCache>();\n\n const [jobStatus, setJobStatus] = useState<JobStatus.StatusEnum>();\n const [jobLink, setJobLink] = useState<Link>();\n\n const isValidEmail = useCallback(() => {\n return /\\S+@\\S+\\.\\S+/.test(email);\n }, [email]);\n\n const isValidPassword = useCallback(() => {\n return password !== \"\";\n }, [password]);\n\n const validateSignin = useCallback(() => {\n return cache?.token && cache?.exp > Date.now();\n }, [cache]);\n\n const [isSignedIn, setIsSignedIn] = useState(validateSignin());\n const [isSigningIn, startSigningIn] = useState(false);\n const intervalRef = useRef<number>();\n\n const isValidSignin = useCallback(() => {\n return isValidEmail() && isValidPassword();\n }, [isValidEmail, isValidPassword]);\n\n const resetSignin = useCallback(() => {\n setEmail(\"\");\n setPassword(\"\");\n showPassword(false);\n showSigninError(false);\n }, [setEmail, setPassword, showPassword, showSigninError]);\n\n const pinStatus = useCallback(\n (job: JobCreation) => {\n const intervalId = window.setInterval(async () => {\n const token =\n (await IModelApp.authorizationClient?.getAccessToken()) ?? \"\";\n if (job.id && token) {\n const currentJobStatus =\n await oneClickLCAClientApi.getOneclicklcaJobStatus(token, job?.id);\n if (currentJobStatus.job?.status) {\n if (\n currentJobStatus.job?.status === JobStatus.StatusEnum.Succeeded\n ) {\n setJobLink(currentJobStatus?.job._links?.oneclicklca);\n }\n setJobStatus(currentJobStatus.job?.status);\n } else {\n throw new Error(\"failed to get job status\");\n }\n }\n }, PIN_INTERVAL);\n intervalRef.current = intervalId;\n },\n [setJobLink, setJobStatus, oneClickLCAClientApi]\n );\n\n const runJob = useCallback(\n async (token: string) => {\n const accessToken =\n (await IModelApp.authorizationClient?.getAccessToken()) ?? \"\";\n if (props.reportId && token) {\n try {\n const jobCreated = await oneClickLCAClientApi.createOneclicklcaJob(\n accessToken,\n {\n reportId: props.reportId,\n token,\n }\n );\n if (jobCreated?.job?.id) {\n pinStatus(jobCreated?.job);\n } else {\n throw new Error(\"Failed to create job\");\n }\n } catch (e) {\n throw new Error(`Failed to create one click lca job.${e}`);\n }\n } else {\n throw new Error(\"No reportId or accessToken\");\n }\n },\n [props, pinStatus, oneClickLCAClientApi]\n );\n\n const signin = useCallback(\n async (e) => {\n e.preventDefault();\n startSigningIn(true);\n const result = await oneClickLCAClientApi.getOneclicklcaAccessToken(\n email,\n password\n );\n if (result && result.access_token && result.expires_in) {\n cacheToken({\n token: result.access_token,\n exp: Date.now() + result.expires_in * MILI_SECONDS,\n });\n resetSignin();\n setIsSignedIn(true);\n } else {\n showSigninError(true);\n }\n startSigningIn(false);\n },\n [\n email,\n password,\n resetSignin,\n cacheToken,\n showSigninError,\n oneClickLCAClientApi,\n ]\n );\n\n const onClose = useCallback(() => {\n resetSignin();\n setJobStatus(undefined);\n setJobLink(undefined);\n if (intervalRef.current) {\n window.clearInterval(intervalRef.current);\n }\n props.close();\n }, [props, resetSignin]);\n\n const getStatusComponent = useCallback(\n (status: JobStatus.StatusEnum, link: string | undefined) => {\n switch (status) {\n case JobStatus.StatusEnum.Queued:\n return (\n <div className=\"oclca-progress-radial-container\">\n <ProgressRadial indeterminate size=\"small\" value={50} />\n <Text variant=\"leading\" className=\"oclca-status-text\">\n Export queued\n </Text>\n </div>\n );\n case JobStatus.StatusEnum.Running:\n return (\n <div className=\"oclca-progress-linear-container\">\n <ProgressLinear indeterminate />\n <Text variant=\"leading\" className=\"oclca-status-text\">\n Export running\n </Text>\n </div>\n );\n case JobStatus.StatusEnum.Succeeded:\n return (\n link && (\n <div className=\"oclca-progress-radial-container\">\n <ProgressRadial status=\"positive\" size=\"small\" value={50} />\n <a\n className=\"oclca-report-button\"\n href={link}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n >\n <Button styleType=\"cta\">Open in One Click LCA</Button>\n </a>\n </div>\n )\n );\n case JobStatus.StatusEnum.Failed:\n return (\n <div className=\"oclca-progress-radial-container\">\n <ProgressRadial status=\"negative\" size=\"small\" value={100} />\n <Text variant=\"leading\" className=\"oclca-status-text\">\n Export failed\n </Text>\n </div>\n );\n default:\n throw new Error(`Job status is invalid ${status}`);\n }\n },\n []\n );\n\n useEffect(() => {\n if (props.isOpen && isSignedIn && cache?.token) {\n runJob(cache.token).catch((err) => {\n throw new Error(err);\n });\n }\n }, [props.isOpen, isSignedIn, cache, runJob]);\n\n useEffect(() => {\n if (\n jobStatus === JobStatus.StatusEnum.Succeeded ||\n jobStatus === JobStatus.StatusEnum.Failed\n ) {\n if (intervalRef.current) {\n window.clearInterval(intervalRef.current);\n }\n }\n }, [jobStatus]);\n\n useEffect(() => {\n if (email !== \"\") {\n const timeoutId = setTimeout(() => setEmailError(!isValidEmail()), 1000);\n return () => clearTimeout(timeoutId);\n } else {\n setEmailError(false);\n return;\n }\n }, [email, isValidEmail]);\n\n return (\n <Modal\n data-testid=\"export-modal\"\n isOpen={props.isOpen}\n onClose={onClose}\n title={null}\n closeOnExternalClick={false}\n >\n {!isSignedIn && (\n <div className=\"oclca-signin\">\n <img\n className=\"oclca-signin-icon\"\n src={logo}\n alt=\"One Click LCA® software\"\n data-height-percentage=\"80\"\n data-actual-width=\"1200\"\n data-actual-height=\"600\"\n />\n <form onSubmit={signin} className=\"oclca-signin-form\">\n <div className=\"oclca-signin-prompt\">Sign in to One Click LCA.</div>\n {signinError && (\n <Alert type=\"negative\" className=\"oclca-signin-error\">\n Incorrect email or password.\n </Alert>\n )}\n <div className=\"oclca-signin-input\">\n <LabeledInput\n label=\"Email\"\n value={email}\n onChange={(v) => setEmail(v.target.value)}\n type=\"email\"\n status={emailError ? \"negative\" : undefined}\n message={emailError ? \"Invalid email address.\" : \"\"}\n required\n />\n </div>\n <div className=\"oclca-signin-input\">\n <LabeledInput\n label=\"Password\"\n value={password}\n onChange={(e) => setPassword(e.target.value)}\n type={passwordIsVisible ? \"text\" : \"password\"}\n svgIcon={\n passwordIsVisible ? (\n <SvgVisibilityHide\n onClick={() => showPassword(!passwordIsVisible)}\n />\n ) : (\n <SvgVisibilityShow />\n )\n }\n iconDisplayStyle=\"inline\"\n required\n />\n </div>\n\n <div className=\"oclca-signin-button-container\">\n <Button\n className=\"oclca-signin-button\"\n type=\"submit\"\n styleType=\"cta\"\n disabled={!isValidSignin()}\n >\n {isSigningIn ? (\n <ProgressRadial\n className=\"oclca-signin-wait\"\n indeterminate\n size=\"small\"\n value={50}\n />\n ) : (\n \"Sign In\"\n )}\n </Button>\n </div>\n </form>\n </div>\n )}\n {isSignedIn && !jobStatus && (\n <div className=\"oclca-progress-radial-container\">\n <ProgressRadial indeterminate size=\"large\" value={50} />\n </div>\n )}\n {isSignedIn && jobStatus && getStatusComponent(jobStatus, jobLink?.href)}\n </Modal>\n );\n};\n\nexport default ExportModal;\n"]}
|
|
@@ -0,0 +1,85 @@
|
|
|
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
|
+
.oclca {
|
|
8
|
+
&-signin {
|
|
9
|
+
display: flex;
|
|
10
|
+
flex-direction: column;
|
|
11
|
+
align-items: center;
|
|
12
|
+
padding-bottom: 4 * $iui-baseline;
|
|
13
|
+
padding-top: 2 * $iui-baseline;
|
|
14
|
+
|
|
15
|
+
&-icon {
|
|
16
|
+
width: 2 * $iui-icons-3xl;
|
|
17
|
+
height: 1 * $iui-icons-3xl;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
&-prompt {
|
|
21
|
+
margin: $iui-l 0;
|
|
22
|
+
font-size: medium;
|
|
23
|
+
display: flex;
|
|
24
|
+
flex-direction: column;
|
|
25
|
+
align-items: center;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
&-form {
|
|
29
|
+
width: 70%;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
&-input {
|
|
33
|
+
width: 100%;
|
|
34
|
+
margin: $iui-xs 0;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
&-button-container {
|
|
38
|
+
margin: $iui-sm 0;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
&-button {
|
|
42
|
+
width: 100%;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
&-error {
|
|
46
|
+
height: $iui-xl;
|
|
47
|
+
font-size: small;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
&-wait {
|
|
51
|
+
vertical-align: middle;
|
|
52
|
+
line-height: normal;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
&-report-button {
|
|
57
|
+
margin: $iui-l;
|
|
58
|
+
text-decoration: none;
|
|
59
|
+
:hover {
|
|
60
|
+
cursor: pointer;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
&-status-text {
|
|
65
|
+
margin: $iui-s;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
&-progress-radial-container {
|
|
69
|
+
display: flex;
|
|
70
|
+
flex-direction: column;
|
|
71
|
+
align-items: center;
|
|
72
|
+
margin: $iui-l;
|
|
73
|
+
height: $iui-3xl;
|
|
74
|
+
place-content: space-evenly;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
&-progress-linear-container {
|
|
78
|
+
display: flex;
|
|
79
|
+
flex-direction: column;
|
|
80
|
+
text-align: center;
|
|
81
|
+
margin: $iui-l;
|
|
82
|
+
height: $iui-3xl;
|
|
83
|
+
place-content: space-evenly;
|
|
84
|
+
}
|
|
85
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
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
|
+
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
7
|
+
const Reports_1 = __importDefault(require("./Reports"));
|
|
8
|
+
require("./Reports.scss");
|
|
9
|
+
const OneClickLCA = () => {
|
|
10
|
+
return (jsx_runtime_1.jsx("div", Object.assign({ className: "oclca-container" }, { children: jsx_runtime_1.jsx(Reports_1.default, {}, void 0) }), void 0));
|
|
11
|
+
};
|
|
12
|
+
exports.default = OneClickLCA;
|
|
13
|
+
//# sourceMappingURL=OneClickLCA.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"OneClickLCA.js","sourceRoot":"","sources":["../../../src/components/OneClickLCA.tsx"],"names":[],"mappings":";;;;;;AAKA,wDAAgC;AAChC,0BAAwB;AAExB,MAAM,WAAW,GAAG,GAAG,EAAE;IACvB,OAAO,CACL,yCAAK,SAAS,EAAC,iBAAiB,gBAC9B,kBAAC,iBAAO,aAAG,YACP,CACP,CAAC;AACJ,CAAC,CAAC;AAEF,kBAAe,WAAW,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 Reports from \"./Reports\";\nimport \"./Reports.scss\";\n\nconst OneClickLCA = () => {\n return (\n <div className=\"oclca-container\">\n <Reports />\n </div>\n );\n};\n\nexport default OneClickLCA;\n"]}
|
|
@@ -0,0 +1,105 @@
|
|
|
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
|
+
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
7
|
+
/*---------------------------------------------------------------------------------------------
|
|
8
|
+
* Copyright (c) Bentley Systems, Incorporated. All rights reserved.
|
|
9
|
+
* See LICENSE.md in the project root for license terms and full copyright notice.
|
|
10
|
+
*--------------------------------------------------------------------------------------------*/
|
|
11
|
+
const react_1 = require("react");
|
|
12
|
+
const core_react_1 = require("@itwin/core-react");
|
|
13
|
+
const core_frontend_1 = require("@itwin/core-frontend");
|
|
14
|
+
const appui_react_1 = require("@itwin/appui-react");
|
|
15
|
+
const itwinui_react_1 = require("@itwin/itwinui-react");
|
|
16
|
+
const insights_client_1 = require("@itwin/insights-client");
|
|
17
|
+
const utils_1 = require("./utils");
|
|
18
|
+
const ExportModal_1 = __importDefault(require("./ExportModal"));
|
|
19
|
+
require("./Reports.scss");
|
|
20
|
+
const Reports = () => {
|
|
21
|
+
var _a;
|
|
22
|
+
const projectId = (_a = appui_react_1.useActiveIModelConnection()) === null || _a === void 0 ? void 0 : _a.iTwinId;
|
|
23
|
+
const reportingClientApi = react_1.useMemo(() => new insights_client_1.ReportingClient(), []);
|
|
24
|
+
const [isLoading, setIsLoading] = react_1.useState(true);
|
|
25
|
+
const [reports, setReports] = react_1.useState([]);
|
|
26
|
+
const [buttonIsDisabled, disableButton] = react_1.useState(true);
|
|
27
|
+
const [filteredReports, setFilteredReports] = react_1.useState(reports);
|
|
28
|
+
const [selectedReport, setSelectedReport] = react_1.useState();
|
|
29
|
+
const [modalIsOpen, openModal] = react_1.useState(false);
|
|
30
|
+
const reportsColumns = react_1.useMemo(() => [
|
|
31
|
+
{
|
|
32
|
+
Header: "Table",
|
|
33
|
+
columns: [
|
|
34
|
+
{
|
|
35
|
+
id: "displayName",
|
|
36
|
+
Header: "Name",
|
|
37
|
+
accessor: "displayName",
|
|
38
|
+
},
|
|
39
|
+
{
|
|
40
|
+
id: "description",
|
|
41
|
+
Header: "Description",
|
|
42
|
+
accessor: "description",
|
|
43
|
+
},
|
|
44
|
+
],
|
|
45
|
+
},
|
|
46
|
+
], []);
|
|
47
|
+
const onSearchBoxValueChanged = async (value) => {
|
|
48
|
+
disableButton(true);
|
|
49
|
+
const filterReports = reports.filter((x) => {
|
|
50
|
+
var _a;
|
|
51
|
+
return x.displayName &&
|
|
52
|
+
((_a = x.displayName.toLowerCase()) === null || _a === void 0 ? void 0 : _a.indexOf(value.toLowerCase())) > -1;
|
|
53
|
+
});
|
|
54
|
+
setFilteredReports(filterReports);
|
|
55
|
+
};
|
|
56
|
+
const tableStateSingleSelectReducer = (newState, action) => {
|
|
57
|
+
switch (action.type) {
|
|
58
|
+
case "toggleRowSelected": {
|
|
59
|
+
return { ...newState, selectedRowIds: { [action.id]: action.value } };
|
|
60
|
+
}
|
|
61
|
+
default:
|
|
62
|
+
break;
|
|
63
|
+
}
|
|
64
|
+
return newState;
|
|
65
|
+
};
|
|
66
|
+
const onReportRowClick = react_1.useMemo(() => (_, row) => {
|
|
67
|
+
if (row.original === selectedReport) {
|
|
68
|
+
disableButton(!buttonIsDisabled);
|
|
69
|
+
row.toggleRowSelected();
|
|
70
|
+
}
|
|
71
|
+
else {
|
|
72
|
+
disableButton(false);
|
|
73
|
+
row.toggleRowSelected(true);
|
|
74
|
+
}
|
|
75
|
+
setSelectedReport(row.original);
|
|
76
|
+
}, [buttonIsDisabled, selectedReport]);
|
|
77
|
+
react_1.useEffect(() => {
|
|
78
|
+
if (!core_frontend_1.IModelApp.authorizationClient)
|
|
79
|
+
throw new Error("AuthorizationClient is not defined. Most likely IModelApp.startup was not called yet.");
|
|
80
|
+
core_frontend_1.IModelApp.authorizationClient
|
|
81
|
+
.getAccessToken()
|
|
82
|
+
.then((token) => {
|
|
83
|
+
reportingClientApi
|
|
84
|
+
.getReports(token, projectId)
|
|
85
|
+
.then((data) => {
|
|
86
|
+
var _a;
|
|
87
|
+
if (data) {
|
|
88
|
+
const fetchedReports = (_a = data.reports) !== null && _a !== void 0 ? _a : [];
|
|
89
|
+
setReports(fetchedReports);
|
|
90
|
+
setFilteredReports(fetchedReports);
|
|
91
|
+
setIsLoading(false);
|
|
92
|
+
}
|
|
93
|
+
})
|
|
94
|
+
.catch((err) => {
|
|
95
|
+
throw new Error(err);
|
|
96
|
+
});
|
|
97
|
+
})
|
|
98
|
+
.catch((err) => {
|
|
99
|
+
throw new Error(err);
|
|
100
|
+
});
|
|
101
|
+
}, [projectId, reportingClientApi]);
|
|
102
|
+
return (jsx_runtime_1.jsxs(jsx_runtime_1.Fragment, { children: [jsx_runtime_1.jsx(utils_1.WidgetHeader, { title: "Reports" }, void 0), jsx_runtime_1.jsxs("div", Object.assign({ className: "oclca-reports-container" }, { children: [jsx_runtime_1.jsx("div", Object.assign({ className: "oclca-searchbox-container" }, { children: jsx_runtime_1.jsx(core_react_1.SearchBox, { onValueChanged: onSearchBoxValueChanged, placeholder: "Search reports" }, void 0) }), void 0), jsx_runtime_1.jsx("div", Object.assign({ className: "oclca-scrollable-table" }, { children: jsx_runtime_1.jsx(itwinui_react_1.Table, { className: "oclca-reports-table", data: filteredReports, density: "extra-condensed", columns: reportsColumns, emptyTableContent: "No reports available.", isSortable: true, onRowClick: onReportRowClick, stateReducer: tableStateSingleSelectReducer, isLoading: isLoading, selectRowOnClick: true, selectSubRows: false }, void 0) }), void 0)] }), void 0), jsx_runtime_1.jsx(itwinui_react_1.Button, Object.assign({ onClick: () => openModal(true), styleType: "cta", disabled: buttonIsDisabled, className: "oclca-button-center" }, { children: "One Click LCA Export" }), void 0), jsx_runtime_1.jsx(ExportModal_1.default, { isOpen: modalIsOpen, close: () => openModal(false), reportId: selectedReport === null || selectedReport === void 0 ? void 0 : selectedReport.id }, void 0)] }, void 0));
|
|
103
|
+
};
|
|
104
|
+
exports.default = Reports;
|
|
105
|
+
//# sourceMappingURL=Reports.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Reports.js","sourceRoot":"","sources":["../../../src/components/Reports.tsx"],"names":[],"mappings":";;;;;;AAAA;;;+FAG+F;AAC/F,iCAA4D;AAC5D,kDAA8C;AAC9C,wDAAiD;AACjD,oDAA+D;AAC/D,wDAAqD;AAErD,4DAAyD;AACzD,mCAAuC;AACvC,gEAAwC;AACxC,0BAAwB;AAQxB,MAAM,OAAO,GAAG,GAAG,EAAE;;IACnB,MAAM,SAAS,GAAG,MAAA,uCAAyB,EAAE,0CAAE,OAAiB,CAAC;IACjE,MAAM,kBAAkB,GAAG,eAAO,CAAC,GAAG,EAAE,CAAC,IAAI,iCAAe,EAAE,EAAE,EAAE,CAAC,CAAC;IAEpE,MAAM,CAAC,SAAS,EAAE,YAAY,CAAC,GAAG,gBAAQ,CAAU,IAAI,CAAC,CAAC;IAC1D,MAAM,CAAC,OAAO,EAAE,UAAU,CAAC,GAAG,gBAAQ,CAAW,EAAE,CAAC,CAAC;IACrD,MAAM,CAAC,gBAAgB,EAAE,aAAa,CAAC,GAAG,gBAAQ,CAAU,IAAI,CAAC,CAAC;IAClE,MAAM,CAAC,eAAe,EAAE,kBAAkB,CAAC,GAAG,gBAAQ,CAAW,OAAO,CAAC,CAAC;IAC1E,MAAM,CAAC,cAAc,EAAE,iBAAiB,CAAC,GAAG,gBAAQ,EAAa,CAAC;IAElE,MAAM,CAAC,WAAW,EAAE,SAAS,CAAC,GAAG,gBAAQ,CAAC,KAAK,CAAC,CAAC;IAEjD,MAAM,cAAc,GAAG,eAAO,CAC5B,GAAG,EAAE,CAAC;QACJ;YACE,MAAM,EAAE,OAAO;YACf,OAAO,EAAE;gBACP;oBACE,EAAE,EAAE,aAAa;oBACjB,MAAM,EAAE,MAAM;oBACd,QAAQ,EAAE,aAAa;iBACxB;gBACD;oBACE,EAAE,EAAE,aAAa;oBACjB,MAAM,EAAE,aAAa;oBACrB,QAAQ,EAAE,aAAa;iBACxB;aACF;SACF;KACF,EACD,EAAE,CACH,CAAC;IAEF,MAAM,uBAAuB,GAAG,KAAK,EAAE,KAAa,EAAE,EAAE;QACtD,aAAa,CAAC,IAAI,CAAC,CAAC;QACpB,MAAM,aAAa,GAAG,OAAO,CAAC,MAAM,CAClC,CAAC,CAAC,EAAE,EAAE;;YACJ,OAAA,CAAC,CAAC,WAAW;gBACb,CAAA,MAAA,CAAC,CAAC,WAAW,CAAC,WAAW,EAAE,0CAAE,OAAO,CAAC,KAAK,CAAC,WAAW,EAAE,CAAC,IAAG,CAAC,CAAC,CAAA;SAAA,CACjE,CAAC;QACF,kBAAkB,CAAC,aAAa,CAAC,CAAC;IACpC,CAAC,CAAC;IAEF,MAAM,6BAA6B,GAAG,CAAC,QAAa,EAAE,MAAW,EAAO,EAAE;QACxE,QAAQ,MAAM,CAAC,IAAI,EAAE;YACnB,KAAK,mBAAmB,CAAC,CAAC;gBACxB,OAAO,EAAE,GAAG,QAAQ,EAAE,cAAc,EAAE,EAAE,CAAC,MAAM,CAAC,EAAE,CAAC,EAAE,MAAM,CAAC,KAAK,EAAE,EAAE,CAAC;aACvE;YACD;gBACE,MAAM;SACT;QACD,OAAO,QAAQ,CAAC;IAClB,CAAC,CAAC;IAEF,MAAM,gBAAgB,GAAG,eAAO,CAC9B,GAAG,EAAE,CAAC,CAAC,CAAM,EAAE,GAAQ,EAAE,EAAE;QACzB,IAAI,GAAG,CAAC,QAAQ,KAAK,cAAc,EAAE;YACnC,aAAa,CAAC,CAAC,gBAAgB,CAAC,CAAC;YACjC,GAAG,CAAC,iBAAiB,EAAE,CAAC;SACzB;aAAM;YACL,aAAa,CAAC,KAAK,CAAC,CAAC;YACrB,GAAG,CAAC,iBAAiB,CAAC,IAAI,CAAC,CAAC;SAC7B;QACD,iBAAiB,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;IAClC,CAAC,EACD,CAAC,gBAAgB,EAAE,cAAc,CAAC,CACnC,CAAC;IAEF,iBAAS,CAAC,GAAG,EAAE;QACb,IAAI,CAAC,yBAAS,CAAC,mBAAmB;YAChC,MAAM,IAAI,KAAK,CACb,uFAAuF,CACxF,CAAC;QACJ,yBAAS,CAAC,mBAAmB;aAC1B,cAAc,EAAE;aAChB,IAAI,CAAC,CAAC,KAAa,EAAE,EAAE;YACtB,kBAAkB;iBACf,UAAU,CAAC,KAAK,EAAE,SAAS,CAAC;iBAC5B,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE;;gBACb,IAAI,IAAI,EAAE;oBACR,MAAM,cAAc,GAAG,MAAA,IAAI,CAAC,OAAO,mCAAI,EAAE,CAAC;oBAC1C,UAAU,CAAC,cAAc,CAAC,CAAC;oBAC3B,kBAAkB,CAAC,cAAc,CAAC,CAAC;oBACnC,YAAY,CAAC,KAAK,CAAC,CAAC;iBACrB;YACH,CAAC,CAAC;iBACD,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE;gBACb,MAAM,IAAI,KAAK,CAAC,GAAG,CAAC,CAAC;YACvB,CAAC,CAAC,CAAC;QACP,CAAC,CAAC;aACD,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE;YACb,MAAM,IAAI,KAAK,CAAC,GAAG,CAAC,CAAC;QACvB,CAAC,CAAC,CAAC;IACP,CAAC,EAAE,CAAC,SAAS,EAAE,kBAAkB,CAAC,CAAC,CAAC;IAEpC,OAAO,CACL,wDACE,kBAAC,oBAAY,IAAC,KAAK,EAAC,SAAS,WAAG,EAChC,0CAAK,SAAS,EAAC,yBAAyB,iBACtC,yCAAK,SAAS,EAAC,2BAA2B,gBACxC,kBAAC,sBAAS,IACR,cAAc,EAAE,uBAAuB,EACvC,WAAW,EAAE,gBAAgB,WAC7B,YACE,EACN,yCAAK,SAAS,EAAC,wBAAwB,gBACrC,kBAAC,qBAAK,IACJ,SAAS,EAAC,qBAAqB,EAC/B,IAAI,EAAE,eAAe,EACrB,OAAO,EAAC,iBAAiB,EACzB,OAAO,EAAE,cAAc,EACvB,iBAAiB,EAAC,uBAAuB,EACzC,UAAU,QACV,UAAU,EAAE,gBAAgB,EAC5B,YAAY,EAAE,6BAA6B,EAC3C,SAAS,EAAE,SAAS,EACpB,gBAAgB,EAAE,IAAI,EACtB,aAAa,EAAE,KAAK,WACpB,YACE,aACF,EACN,kBAAC,sBAAM,kBACL,OAAO,EAAE,GAAG,EAAE,CAAC,SAAS,CAAC,IAAI,CAAC,EAC9B,SAAS,EAAC,KAAK,EACf,QAAQ,EAAE,gBAAgB,EAC1B,SAAS,EAAC,qBAAqB,kDAGxB,EACT,kBAAC,qBAAW,IACV,MAAM,EAAE,WAAW,EACnB,KAAK,EAAE,GAAG,EAAE,CAAC,SAAS,CAAC,KAAK,CAAC,EAC7B,QAAQ,EAAE,cAAc,aAAd,cAAc,uBAAd,cAAc,CAAE,EAAE,WAC5B,YACD,CACJ,CAAC;AACJ,CAAC,CAAC;AAEF,kBAAe,OAAO,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, { useEffect, useMemo, useState } from \"react\";\nimport { SearchBox } from \"@itwin/core-react\";\nimport { IModelApp } from \"@itwin/core-frontend\";\nimport { useActiveIModelConnection } from \"@itwin/appui-react\";\nimport { Button, Table } from \"@itwin/itwinui-react\";\nimport type { Report} from \"@itwin/insights-client\";\nimport { ReportingClient } from \"@itwin/insights-client\";\nimport { WidgetHeader } from \"./utils\";\nimport ExportModal from \"./ExportModal\";\nimport \"./Reports.scss\";\n\ntype CreateTypeFromInterface<Interface> = {\n [Property in keyof Interface]: Interface[Property];\n};\n\ntype Reporting = CreateTypeFromInterface<Report>;\n\nconst Reports = () => {\n const projectId = useActiveIModelConnection()?.iTwinId as string;\n const reportingClientApi = useMemo(() => new ReportingClient(), []);\n\n const [isLoading, setIsLoading] = useState<boolean>(true);\n const [reports, setReports] = useState<Report[]>([]);\n const [buttonIsDisabled, disableButton] = useState<boolean>(true);\n const [filteredReports, setFilteredReports] = useState<Report[]>(reports);\n const [selectedReport, setSelectedReport] = useState<Reporting>();\n\n const [modalIsOpen, openModal] = useState(false);\n\n const reportsColumns = useMemo(\n () => [\n {\n Header: \"Table\",\n columns: [\n {\n id: \"displayName\",\n Header: \"Name\",\n accessor: \"displayName\",\n },\n {\n id: \"description\",\n Header: \"Description\",\n accessor: \"description\",\n },\n ],\n },\n ],\n []\n );\n\n const onSearchBoxValueChanged = async (value: string) => {\n disableButton(true);\n const filterReports = reports.filter(\n (x) =>\n x.displayName &&\n x.displayName.toLowerCase()?.indexOf(value.toLowerCase()) > -1\n );\n setFilteredReports(filterReports);\n };\n\n const tableStateSingleSelectReducer = (newState: any, action: any): any => {\n switch (action.type) {\n case \"toggleRowSelected\": {\n return { ...newState, selectedRowIds: { [action.id]: action.value } };\n }\n default:\n break;\n }\n return newState;\n };\n\n const onReportRowClick = useMemo(\n () => (_: any, row: any) => {\n if (row.original === selectedReport) {\n disableButton(!buttonIsDisabled);\n row.toggleRowSelected();\n } else {\n disableButton(false);\n row.toggleRowSelected(true);\n }\n setSelectedReport(row.original);\n },\n [buttonIsDisabled, selectedReport]\n );\n\n useEffect(() => {\n if (!IModelApp.authorizationClient)\n throw new Error(\n \"AuthorizationClient is not defined. Most likely IModelApp.startup was not called yet.\"\n );\n IModelApp.authorizationClient\n .getAccessToken()\n .then((token: string) => {\n reportingClientApi\n .getReports(token, projectId)\n .then((data) => {\n if (data) {\n const fetchedReports = data.reports ?? [];\n setReports(fetchedReports);\n setFilteredReports(fetchedReports);\n setIsLoading(false);\n }\n })\n .catch((err) => {\n throw new Error(err);\n });\n })\n .catch((err) => {\n throw new Error(err);\n });\n }, [projectId, reportingClientApi]);\n\n return (\n <>\n <WidgetHeader title=\"Reports\" />\n <div className=\"oclca-reports-container\">\n <div className=\"oclca-searchbox-container\">\n <SearchBox\n onValueChanged={onSearchBoxValueChanged}\n placeholder={\"Search reports\"}\n />\n </div>\n <div className=\"oclca-scrollable-table\">\n <Table<Reporting>\n className=\"oclca-reports-table\"\n data={filteredReports}\n density=\"extra-condensed\"\n columns={reportsColumns}\n emptyTableContent=\"No reports available.\"\n isSortable\n onRowClick={onReportRowClick}\n stateReducer={tableStateSingleSelectReducer}\n isLoading={isLoading}\n selectRowOnClick={true}\n selectSubRows={false}\n />\n </div>\n </div>\n <Button\n onClick={() => openModal(true)}\n styleType=\"cta\"\n disabled={buttonIsDisabled}\n className=\"oclca-button-center\"\n >\n One Click LCA Export\n </Button>\n <ExportModal\n isOpen={modalIsOpen}\n close={() => openModal(false)}\n reportId={selectedReport?.id}\n />\n </>\n );\n};\n\nexport default Reports;\n"]}
|
|
@@ -0,0 +1,44 @@
|
|
|
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
|
+
.oclca {
|
|
8
|
+
&-scrollable-table {
|
|
9
|
+
overflow-y: scroll;
|
|
10
|
+
max-height: 90%;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
&-reports-table {
|
|
14
|
+
:hover {
|
|
15
|
+
cursor: pointer;
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
&-searchbox-container {
|
|
20
|
+
display: inline-flex;
|
|
21
|
+
justify-content: right;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
&-reports-container {
|
|
25
|
+
display: flex;
|
|
26
|
+
flex-direction: column;
|
|
27
|
+
gap: $iui-baseline;
|
|
28
|
+
margin-bottom: $iui-line-height;
|
|
29
|
+
max-height: 80%;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
&-button-center {
|
|
33
|
+
align-self: center;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
&-container {
|
|
37
|
+
display: flex;
|
|
38
|
+
flex-direction: column;
|
|
39
|
+
padding: $iui-baseline $iui-m;
|
|
40
|
+
box-sizing: border-box;
|
|
41
|
+
height: 100%;
|
|
42
|
+
overflow: auto;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/// <reference types="react" />
|
|
2
|
+
import "./utils.scss";
|
|
3
|
+
export interface WidgetHeaderProps {
|
|
4
|
+
title: string;
|
|
5
|
+
disabled?: boolean;
|
|
6
|
+
returnFn?: () => Promise<void>;
|
|
7
|
+
}
|
|
8
|
+
export declare const WidgetHeader: ({ title, disabled, returnFn, }: WidgetHeaderProps) => JSX.Element;
|
|
9
|
+
//# sourceMappingURL=utils.d.ts.map
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.WidgetHeader = void 0;
|
|
4
|
+
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
5
|
+
/*---------------------------------------------------------------------------------------------
|
|
6
|
+
* Copyright (c) Bentley Systems, Incorporated. All rights reserved.
|
|
7
|
+
* See LICENSE.md in the project root for license terms and full copyright notice.
|
|
8
|
+
*--------------------------------------------------------------------------------------------*/
|
|
9
|
+
const itwinui_icons_react_1 = require("@itwin/itwinui-icons-react");
|
|
10
|
+
const itwinui_react_1 = require("@itwin/itwinui-react");
|
|
11
|
+
require("./utils.scss");
|
|
12
|
+
const WidgetHeader = ({ title, disabled = false, returnFn, }) => {
|
|
13
|
+
return (jsx_runtime_1.jsxs("div", Object.assign({ className: "oclca-widget-header-container" }, { children: [returnFn && (jsx_runtime_1.jsx("div", Object.assign({ className: disabled ? "oclca-chevron-disabled" : "oclca-chevron", onClick: disabled ? undefined : returnFn, onKeyUp: disabled ? undefined : returnFn }, { children: jsx_runtime_1.jsx(itwinui_icons_react_1.SvgChevronLeft, {}, void 0) }), void 0)), jsx_runtime_1.jsx(itwinui_react_1.Text, Object.assign({ className: "oclca-title", variant: "title" }, { children: title }), void 0)] }), void 0));
|
|
14
|
+
};
|
|
15
|
+
exports.WidgetHeader = WidgetHeader;
|
|
16
|
+
//# sourceMappingURL=utils.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"utils.js","sourceRoot":"","sources":["../../../src/components/utils.tsx"],"names":[],"mappings":";;;;AAAA;;;+FAG+F;AAC/F,oEAA4D;AAC5D,wDAA4C;AAC5C,wBAAsB;AASf,MAAM,YAAY,GAAG,CAAC,EAC3B,KAAK,EACL,QAAQ,GAAG,KAAK,EAChB,QAAQ,GACU,EAAE,EAAE;IACtB,OAAO,CACL,0CAAK,SAAS,EAAC,+BAA+B,iBAC3C,QAAQ,IAAI,CACX,yCACE,SAAS,EAAE,QAAQ,CAAC,CAAC,CAAC,wBAAwB,CAAC,CAAC,CAAC,eAAe,EAChE,OAAO,EAAE,QAAQ,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,QAAQ,EACxC,OAAO,EAAE,QAAQ,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,QAAQ,gBAExC,kBAAC,oCAAc,aAAG,YACd,CACP,EACD,kBAAC,oBAAI,kBAAC,SAAS,EAAC,aAAa,EAAC,OAAO,EAAC,OAAO,gBAC1C,KAAK,YACD,aACH,CACP,CAAC;AACJ,CAAC,CAAC;AArBW,QAAA,YAAY,gBAqBvB","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 { SvgChevronLeft } from \"@itwin/itwinui-icons-react\";\nimport { Text } from \"@itwin/itwinui-react\";\nimport \"./utils.scss\";\nimport React from \"react\";\n\nexport interface WidgetHeaderProps {\n title: string;\n disabled?: boolean;\n returnFn?: () => Promise<void>;\n}\n\nexport const WidgetHeader = ({\n title,\n disabled = false,\n returnFn,\n}: WidgetHeaderProps) => {\n return (\n <div className=\"oclca-widget-header-container\">\n {returnFn && (\n <div\n className={disabled ? \"oclca-chevron-disabled\" : \"oclca-chevron\"}\n onClick={disabled ? undefined : returnFn}\n onKeyUp={disabled ? undefined : returnFn}\n >\n <SvgChevronLeft />\n </div>\n )}\n <Text className=\"oclca-title\" variant=\"title\">\n {title}\n </Text>\n </div>\n );\n};\n"]}
|
|
@@ -0,0 +1,35 @@
|
|
|
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
|
+
@import "~@itwin/itwinui-css/scss/icon/index";
|
|
7
|
+
@import "~@itwin/itwinui-css/scss/button/index";
|
|
8
|
+
|
|
9
|
+
.oclca-widget-header-container {
|
|
10
|
+
display: flex;
|
|
11
|
+
margin-bottom: $iui-baseline * 3;
|
|
12
|
+
.oclca-chevron {
|
|
13
|
+
@include iui-icons-large();
|
|
14
|
+
cursor: pointer;
|
|
15
|
+
align-self: center;
|
|
16
|
+
margin-right: $iui-s;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
.oclca-chevron-disabled {
|
|
20
|
+
@include iui-icons-large();
|
|
21
|
+
@include themed {
|
|
22
|
+
fill: t(iui-icons-color-actionable-disabled);
|
|
23
|
+
}
|
|
24
|
+
cursor: not-allowed;
|
|
25
|
+
|
|
26
|
+
align-self: center;
|
|
27
|
+
margin-right: $iui-s;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
.oclca-title {
|
|
31
|
+
overflow: hidden;
|
|
32
|
+
white-space: nowrap;
|
|
33
|
+
text-overflow: ellipsis;
|
|
34
|
+
}
|
|
35
|
+
}
|