@itwin/saved-views-react 0.6.0 → 0.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +5 -20
- package/lib/SavedView.d.ts +20 -12
- package/lib/SavedViewTile/SavedViewOptions.js +10 -10
- package/lib/SavedViewTile/SavedViewTile.css +8 -1
- package/lib/SavedViewTile/SavedViewTile.d.ts +4 -3
- package/lib/SavedViewTile/SavedViewTile.js +4 -8
- package/lib/SavedViewTile/SavedViewTileContext.d.ts +0 -1
- package/lib/SavedViewTile/SavedViewTileContext.js +1 -1
- package/lib/SavedViewsClient/ITwinSavedViewsClient.d.ts +20 -22
- package/lib/SavedViewsClient/ITwinSavedViewsClient.js +79 -42
- package/lib/SavedViewsClient/SavedViewsClient.d.ts +55 -40
- package/lib/SavedViewsWidget/SavedViewGroupTile/SavedViewGroupTile.js +2 -3
- package/lib/SavedViewsWidget/SavedViewGroupTile/SavedViewGroupTileContext.d.ts +0 -1
- package/lib/SavedViewsWidget/SavedViewGroupTile/SavedViewGroupTileContext.js +1 -1
- package/lib/SavedViewsWidget/SavedViewsExpandableBlockWidget.d.ts +5 -3
- package/lib/SavedViewsWidget/SavedViewsExpandableBlockWidget.js +3 -3
- package/lib/SavedViewsWidget/SavedViewsFolderWidget.d.ts +5 -4
- package/lib/SavedViewsWidget/SavedViewsFolderWidget.js +7 -7
- package/lib/applySavedView.d.ts +33 -31
- package/lib/applySavedView.js +58 -23
- package/lib/captureSavedViewData.d.ts +12 -16
- package/lib/captureSavedViewData.js +76 -62
- package/lib/captureSavedViewThumbnail.d.ts +1 -1
- package/lib/captureSavedViewThumbnail.js +8 -7
- package/lib/createViewState.d.ts +8 -7
- package/lib/createViewState.js +16 -24
- package/lib/index.d.ts +10 -10
- package/lib/index.js +7 -7
- package/lib/translation/SavedViewTypes.d.ts +1 -1
- package/lib/translation/clipVectorsLegacyExtractor.js +4 -0
- package/lib/translation/displayStyleExtractor.js +8 -3
- package/lib/translation/extractionUtilities.d.ts +9 -1
- package/lib/translation/extractionUtilities.js +16 -0
- package/lib/useSavedViews.d.ts +171 -38
- package/lib/useSavedViews.js +373 -492
- package/lib/utils.d.ts +8 -1
- package/lib/utils.js +13 -0
- package/package.json +28 -21
package/README.md
CHANGED
|
@@ -8,24 +8,22 @@ A collection of utilities and React components for building iTwin applications t
|
|
|
8
8
|
|
|
9
9
|
### [captureSavedViewData](./src/captureSavedViewData.ts)
|
|
10
10
|
|
|
11
|
-
|
|
11
|
+
Capture current viewport state into serializable format. You can use this data later to restore the view.
|
|
12
12
|
|
|
13
13
|
```ts
|
|
14
|
-
const { viewData, extensions
|
|
15
|
-
extensions.push(myCustomExtension(viewport));
|
|
14
|
+
const { viewData, extensions } = await captureSavedViewData({ viewport });
|
|
16
15
|
console.log({ viewData, extensions }); /*
|
|
17
16
|
{
|
|
18
17
|
viewData: { itwin3dView: {...} },
|
|
19
18
|
extensions: {
|
|
20
19
|
{ extensionName: "EmphasizeElements", data: "{...}" },
|
|
21
|
-
{ extensionName: "MyCustomExtension", data: "my_custom_extension_data" },
|
|
22
20
|
}
|
|
23
21
|
} */
|
|
24
22
|
```
|
|
25
23
|
|
|
26
24
|
### [captureSavedViewThumbnail](./src/captureSavedViewThumbnail.ts)
|
|
27
25
|
|
|
28
|
-
|
|
26
|
+
Generate Saved View thumbnail based on what is currently displayed on the viewport.
|
|
29
27
|
|
|
30
28
|
```ts
|
|
31
29
|
const thumbnail = captureSavedViewThumbnail(viewport);
|
|
@@ -34,7 +32,7 @@ console.log(thumbnail); // "data:image/png;base64,iVBORw0KGoAAAANSUhEUg..."
|
|
|
34
32
|
|
|
35
33
|
### [applySavedView](./src/applySavedView.ts)
|
|
36
34
|
|
|
37
|
-
|
|
35
|
+
Update viewport state to match captured Saved View.
|
|
38
36
|
|
|
39
37
|
```ts
|
|
40
38
|
// Capture viewport state
|
|
@@ -43,18 +41,6 @@ const savedViewData = await captureSavedViewData({ viewport });
|
|
|
43
41
|
await applySavedView(iModel, viewport, savedViewData);
|
|
44
42
|
```
|
|
45
43
|
|
|
46
|
-
### [createViewState](./src/createViewState.ts)
|
|
47
|
-
|
|
48
|
-
Creates ViewState object out of Saved View data. It provides a lower-level access to view data for advanced use.
|
|
49
|
-
|
|
50
|
-
```ts
|
|
51
|
-
const viewState = await createViewState(iModel, savedViewData.viewData);
|
|
52
|
-
await applySavedView(iModel, viewport, savedViewData, { viewState });
|
|
53
|
-
|
|
54
|
-
// The two lines above are equivalent to
|
|
55
|
-
await applySavedView(iModel, viewport, savedViewData);
|
|
56
|
-
```
|
|
57
|
-
|
|
58
44
|
### React components
|
|
59
45
|
|
|
60
46
|
* [SavedViewTile](./src/SavedViewTile/SavedViewTile.tsx)
|
|
@@ -99,8 +85,7 @@ export function SavedViewsWidget(props) {
|
|
|
99
85
|
import { useSavedViews, ITwinSavedViewsClient } from "@itwin/saved-views-react";
|
|
100
86
|
|
|
101
87
|
const client = new ITwinSavedViewsClient({
|
|
102
|
-
|
|
103
|
-
getAccessToken: async () => "auth_token",
|
|
88
|
+
getAccessToken: async () => "itwin_platform_auth_token",
|
|
104
89
|
});
|
|
105
90
|
|
|
106
91
|
export function SavedViewsWidget(props) {
|
package/lib/SavedView.d.ts
CHANGED
|
@@ -1,19 +1,27 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
import type { ReactNode } from "react";
|
|
1
|
+
import type { ViewITwin3d, ViewITwinDrawing, ViewITwinSheet } from "@itwin/saved-views-client";
|
|
3
2
|
export interface SavedView {
|
|
4
|
-
|
|
3
|
+
savedViewId: string;
|
|
5
4
|
displayName: string;
|
|
6
|
-
viewData?: ViewData | undefined;
|
|
7
5
|
groupId?: string | undefined;
|
|
8
6
|
creatorId?: string | undefined;
|
|
9
7
|
tagIds?: string[] | undefined;
|
|
10
8
|
shared?: boolean | undefined;
|
|
11
|
-
|
|
9
|
+
creationTime?: Date | undefined;
|
|
10
|
+
lastModified?: Date | undefined;
|
|
11
|
+
}
|
|
12
|
+
export interface SavedViewData {
|
|
13
|
+
viewData: ViewData;
|
|
12
14
|
extensions?: SavedViewExtension[] | undefined;
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
15
|
+
}
|
|
16
|
+
export type ViewData = ITwin3dViewData | ITwinDrawingdata | ITwinSheetData;
|
|
17
|
+
export interface ITwin3dViewData extends ViewITwin3d {
|
|
18
|
+
type: "iTwin3d";
|
|
19
|
+
}
|
|
20
|
+
export interface ITwinDrawingdata extends ViewITwinDrawing {
|
|
21
|
+
type: "iTwinDrawing";
|
|
22
|
+
}
|
|
23
|
+
export interface ITwinSheetData extends ViewITwinSheet {
|
|
24
|
+
type: "iTwinSheet";
|
|
17
25
|
}
|
|
18
26
|
export interface SavedViewExtension {
|
|
19
27
|
/** Extension identifier. Saved View cannot contain multiple extensions that share the same `extensionName`. */
|
|
@@ -36,13 +44,13 @@ export interface SavedViewExtension {
|
|
|
36
44
|
data: string;
|
|
37
45
|
}
|
|
38
46
|
export interface SavedViewTag {
|
|
39
|
-
|
|
47
|
+
tagId: string;
|
|
40
48
|
displayName: string;
|
|
41
49
|
}
|
|
42
50
|
export interface SavedViewGroup {
|
|
43
|
-
|
|
51
|
+
groupId: string;
|
|
44
52
|
displayName: string;
|
|
45
53
|
creatorId?: string | undefined;
|
|
46
54
|
shared?: boolean | undefined;
|
|
47
55
|
}
|
|
48
|
-
export type WriteableSavedViewProperties =
|
|
56
|
+
export type WriteableSavedViewProperties = Pick<SavedView, "displayName" | "groupId" | "tagIds" | "shared">;
|
|
@@ -117,14 +117,14 @@ function MoveToGroup(props) {
|
|
|
117
117
|
function MoveToGroupSubmenu(props) {
|
|
118
118
|
const { localization: { moveToGroupMenu } } = useSavedViewsContext();
|
|
119
119
|
const handleMoveToGroup = (groupId) => {
|
|
120
|
-
props.moveToGroup(props.savedView.
|
|
120
|
+
props.moveToGroup(props.savedView.savedViewId, groupId);
|
|
121
121
|
};
|
|
122
122
|
const { moveToNewGroup } = props;
|
|
123
123
|
const handleCreate = moveToNewGroup && ((groupName) => {
|
|
124
|
-
moveToNewGroup(props.savedView.
|
|
124
|
+
moveToNewGroup(props.savedView.savedViewId, groupName);
|
|
125
125
|
});
|
|
126
|
-
return (_jsx(SearchableSubmenu, { collection: props.groups, placeholder: props.moveToNewGroup ? moveToGroupMenu.findOrCreateGroup : moveToGroupMenu.findGroup, creationLabel: moveToGroupMenu.createGroup, onCreate: handleCreate, children: (searchResults) => searchResults.map((group) => (_jsxs(MenuItem, { className: "svr-searchable-submenu-item", startIcon: group.shared ? _jsx(SvgShare, {}) : _jsx(SvgBlank, {}), onClick: () => handleMoveToGroup(group.
|
|
127
|
-
_jsx(Text, { style: { marginLeft: "var(--iui-size-xs)" }, as: "span", children: moveToGroupMenu.current })] }, group.
|
|
126
|
+
return (_jsx(SearchableSubmenu, { collection: props.groups, indexer: "groupId", placeholder: props.moveToNewGroup ? moveToGroupMenu.findOrCreateGroup : moveToGroupMenu.findGroup, creationLabel: moveToGroupMenu.createGroup, onCreate: handleCreate, children: (searchResults) => searchResults.map((group) => (_jsxs(MenuItem, { className: "svr-searchable-submenu-item", startIcon: group.shared ? _jsx(SvgShare, {}) : _jsx(SvgBlank, {}), onClick: () => handleMoveToGroup(group.groupId), disabled: group.groupId === props.savedView.groupId, children: [group.displayName, group.groupId === props.savedView.groupId &&
|
|
127
|
+
_jsx(Text, { style: { marginLeft: "var(--iui-size-xs)" }, as: "span", children: moveToGroupMenu.current })] }, group.groupId))) }));
|
|
128
128
|
}
|
|
129
129
|
function ManageTags(props) {
|
|
130
130
|
const { savedView } = useSavedViewTileContext();
|
|
@@ -135,21 +135,21 @@ function ManageTagsSubmenu(props) {
|
|
|
135
135
|
const { localization } = useSavedViewsContext();
|
|
136
136
|
const handleTagClick = (tagId) => {
|
|
137
137
|
if (props.savedView.tagIds?.includes(tagId)) {
|
|
138
|
-
props.removeTag(props.savedView.
|
|
138
|
+
props.removeTag(props.savedView.savedViewId, tagId);
|
|
139
139
|
}
|
|
140
140
|
else {
|
|
141
|
-
props.addTag(props.savedView.
|
|
141
|
+
props.addTag(props.savedView.savedViewId, tagId);
|
|
142
142
|
}
|
|
143
143
|
};
|
|
144
144
|
const { addNewTag } = props;
|
|
145
145
|
const handleCreate = addNewTag && ((tagName) => {
|
|
146
|
-
addNewTag(props.savedView.
|
|
146
|
+
addNewTag(props.savedView.savedViewId, tagName);
|
|
147
147
|
});
|
|
148
|
-
return (_jsx(SearchableSubmenu, { collection: props.tags, placeholder: props.addNewTag ? localization.tagsMenu.findOrCreateTag : localization.tagsMenu.findTag, creationLabel: localization.tagsMenu.createTag, onCreate: handleCreate, children: (searchResults) => searchResults.map((tag) => (_jsx(MenuItem, { className: "svr-searchable-submenu-item", startIcon: props.savedView.tagIds?.includes(tag.
|
|
148
|
+
return (_jsx(SearchableSubmenu, { collection: props.tags, indexer: "tagId", placeholder: props.addNewTag ? localization.tagsMenu.findOrCreateTag : localization.tagsMenu.findTag, creationLabel: localization.tagsMenu.createTag, onCreate: handleCreate, children: (searchResults) => searchResults.map((tag) => (_jsx(MenuItem, { className: "svr-searchable-submenu-item", startIcon: props.savedView.tagIds?.includes(tag.tagId) ? _jsx(SvgCheckmarkSmall, {}) : _jsx(SvgBlank, {}), onClick: () => handleTagClick(tag.tagId), children: tag.displayName }, tag.tagId))) }));
|
|
149
149
|
}
|
|
150
150
|
function SearchableSubmenu(props) {
|
|
151
151
|
const { localization } = useSavedViewsContext();
|
|
152
|
-
const fuse = useMemo(() => new Fuse(props.collection, { keys: [
|
|
152
|
+
const fuse = useMemo(() => new Fuse(props.collection, { keys: [props.indexer], threshold: 0.5 }), [props.collection, props.indexer]);
|
|
153
153
|
const [inputValue, setInputValue] = useState("");
|
|
154
154
|
const searchResults = useMemo(() => inputValue.length === 0 ? props.collection : fuse.search(inputValue, { limit: 6 }).map(({ item }) => item), [inputValue, props.collection, fuse]);
|
|
155
155
|
const handleSearchChange = (event) => {
|
|
@@ -169,5 +169,5 @@ function SearchableSubmenu(props) {
|
|
|
169
169
|
function Delete(props) {
|
|
170
170
|
const { savedView } = useSavedViewTileContext();
|
|
171
171
|
const { localization } = useSavedViewsContext();
|
|
172
|
-
return (_jsx(MenuItem, { className: props.className, startIcon: props.icon, onClick: () => props.deleteSavedView(savedView.
|
|
172
|
+
return (_jsx(MenuItem, { className: props.className, startIcon: props.icon, onClick: () => props.deleteSavedView(savedView.savedViewId), children: localization.delete }));
|
|
173
173
|
}
|
|
@@ -11,6 +11,13 @@
|
|
|
11
11
|
|
|
12
12
|
.svr-tile .svr-tile-thumbnail {
|
|
13
13
|
height: var(--itwin-svr-thumbnail-height, calc(4 * var(--iui-size-xl)));
|
|
14
|
+
|
|
15
|
+
> img {
|
|
16
|
+
object-fit: cover;
|
|
17
|
+
width: 100%;
|
|
18
|
+
max-width: 100%;
|
|
19
|
+
max-height: 100%;
|
|
20
|
+
}
|
|
14
21
|
}
|
|
15
22
|
|
|
16
23
|
.svr-tile .svr-tile-name {
|
|
@@ -96,4 +103,4 @@
|
|
|
96
103
|
}
|
|
97
104
|
}
|
|
98
105
|
|
|
99
|
-
/*# sourceMappingURL=data:application/json;base64,
|
|
106
|
+
/*# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9TYXZlZFZpZXdUaWxlL1NhdmVkVmlld1RpbGUuY3NzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBIiwiZmlsZSI6IlNhdmVkVmlld1RpbGUuY3NzIiwic291cmNlc0NvbnRlbnQiOlsiLyotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiogQ29weXJpZ2h0IChjKSBCZW50bGV5IFN5c3RlbXMsIEluY29ycG9yYXRlZC4gQWxsIHJpZ2h0cyByZXNlcnZlZC5cbiogU2VlIExJQ0VOU0UubWQgaW4gdGhlIHByb2plY3Qgcm9vdCBmb3IgbGljZW5zZSB0ZXJtcyBhbmQgZnVsbCBjb3B5cmlnaHQgbm90aWNlLlxuKi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tKi9cbkBsYXllciBpdHdpbnVpO1xuXG5AbGF5ZXIgaXR3aW4tc3ZyIHtcbiAgLnN2ci10aWxlIHtcbiAgICB3aWR0aDogdmFyKC0taXR3aW4tc3ZyLXRpbGUtd2lkdGgsIGNhbGMoOCAqIHZhcigtLWl1aS1zaXplLXhsKSkpO1xuICB9XG5cbiAgLnN2ci10aWxlIC5zdnItdGlsZS10aHVtYm5haWwge1xuICAgIGhlaWdodDogdmFyKC0taXR3aW4tc3ZyLXRodW1ibmFpbC1oZWlnaHQsIGNhbGMoNCAqIHZhcigtLWl1aS1zaXplLXhsKSkpO1xuXG4gICAgPiBpbWcge1xuICAgICAgb2JqZWN0LWZpdDogY292ZXI7XG4gICAgICB3aWR0aDogMTAwJTtcbiAgICAgIG1heC13aWR0aDogMTAwJTtcbiAgICAgIG1heC1oZWlnaHQ6IDEwMCU7XG4gICAgfVxuICB9XG5cbiAgLnN2ci10aWxlIC5zdnItdGlsZS1uYW1lIHtcbiAgICBoZWlnaHQ6IGNhbGModmFyKC0taXVpLXNpemUtbCkgKyAycHgpO1xuICAgIHVzZXItc2VsZWN0OiB1bnNldDtcbiAgICBtaW4td2lkdGg6IDA7XG4gICAgdGV4dC13cmFwOiBub3dyYXA7XG5cbiAgICA+IGRpdiB7XG4gICAgICBvdmVyZmxvdzogaGlkZGVuO1xuICAgICAgdGV4dC1vdmVyZmxvdzogZWxsaXBzaXM7XG4gICAgfVxuICB9XG5cbiAgLnN2ci10aWxlLS1tZXRhZGF0YSB7XG4gICAgZGlzcGxheTogZ3JpZDtcbiAgICBncmlkOiAxZnIgLyBhdXRvIG1pbm1heCgwLCAxZnIpIGF1dG87XG4gICAgYWxpZ24taXRlbXM6IGNlbnRlcjtcbiAgfVxuXG4gIC5zdnItdGlsZS0tbWV0YWRhdGEgPiBzdmcge1xuICAgIG1hcmdpbi1yaWdodDogdmFyKC0taXVpLXNpemUteHMpO1xuICB9XG5cbiAgLnN2ci10aWxlLS10YWctY29udGFpbmVyIHtcbiAgICBkaXNwbGF5OiBmbGV4O1xuICAgIGdhcDogdmFyKC0taXVpLXNpemUtcyk7XG4gIH1cblxuICAuc3ZyLXRpbGUtLXRhZyB7XG4gICAgYWxpZ24taXRlbXM6IGNlbnRlcjtcbiAgICB0ZXh0LW92ZXJmbG93OiBlbGxpcHNpcztcbiAgICB3aGl0ZS1zcGFjZTogbm93cmFwO1xuICAgIG92ZXJmbG93OiBoaWRkZW47XG4gICAgbWluLXdpZHRoOiAwO1xuICB9XG5cbiAgLnN2ci10aWxlLS10YWctb3ZlcmZsb3cge1xuICAgIG1hcmdpbi1sZWZ0OiB2YXIoLS1pdWktc2l6ZS1zKTtcbiAgfVxuXG4gIC5zdnItdGlsZS0tbW9yZS1vcHRpb25zIHtcbiAgICB6LWluZGV4OiAyO1xuICAgIGdyaWQtYXJlYTogMSAvIDEgLyAtMSAvIC0xO1xuICAgIHBsYWNlLXNlbGY6IGVuZDtcbiAgICBtYXJnaW46IDA7XG4gICAgbWFyZ2luLWlubGluZS1lbmQ6IGNhbGMoLTEqdmFyKC0taXVpLXNpemUtMnhzKSk7XG4gICAgZGlzcGxheTogZ3JpZDtcbiAgICBwb3NpdGlvbjogYWJzb2x1dGU7XG4gIH1cblxuICAuc3ZyLXRpbGU6bm90KDpob3ZlciwgOmZvY3VzLXdpdGhpbikgLnN2ci10aWxlLS1tb3JlLW9wdGlvbnM6d2hlcmUoOm5vdCguc3ZyLXZpc2libGUpKSB7XG4gICAgdmlzaWJpbGl0eTogaGlkZGVuO1xuICB9XG5cbiAgLnN2ci10aWxlLS1pY29uLWNvbnRhaW5lciB7XG4gICAgZGlzcGxheTogZmxleDtcbiAgICBtYXJnaW4tdG9wOiBjYWxjKDAuNSAqIHZhcigtLWl1aS1zaXplLXMpKTtcbiAgICBtYXJnaW4taW5saW5lOiB2YXIoLS1pdWktc2l6ZS14cyk7XG4gICAgZ2FwOiB2YXIoLS1pdWktc2l6ZS0yeHMpO1xuICAgIHotaW5kZXg6IDE7XG4gIH1cblxuICAuc3ZyLXRpbGUtLWljb24ge1xuICAgIGJvcmRlci1yYWRpdXM6IDUwJTtcbiAgICBiYWNrZ3JvdW5kOiByZ2IoMCwgMCwgMCwgdmFyKC0taXVpLW9wYWNpdHktMykpO1xuICAgIG1pbi13aWR0aDogdmFyKC0taXVpLWNvbXBvbmVudC1oZWlnaHQtc21hbGwpO1xuICAgIG1pbi1oZWlnaHQ6IHZhcigtLWl1aS1jb21wb25lbnQtaGVpZ2h0LXNtYWxsKTtcbiAgICBkaXNwbGF5OiBmbGV4O1xuICAgIHBsYWNlLWl0ZW1zOiBjZW50ZXI7XG4gICAgcGFkZGluZy1pbmxpbmU6IHZhcigtLWl1aS1zaXplLTJ4cyk7XG4gICAgYm9yZGVyOiAxcHggc29saWQgdHJhbnNwYXJlbnQ7XG4gIH1cblxuICAuc3ZyLXRpbGUtLWljb24gc3ZnIHtcbiAgICBmaWxsOiB2YXIoLS1pdWktY29sb3Itd2hpdGUpO1xuICB9XG5cbiAgLnN2ci10aWxlLS1lZGl0YWJsZS10aXRsZSA+IHNwYW4ge1xuICAgIGRpc3BsYXk6IGZsZXg7XG4gICAgYWxpZ24taXRlbXM6IGNlbnRlcjtcbiAgICBnYXA6IHZhcigtLWl1aS1zaXplLXMpO1xuICB9XG59XG4iXX0= */
|
|
@@ -4,6 +4,8 @@ import "./SavedViewTile.css";
|
|
|
4
4
|
interface SavedViewTileProps {
|
|
5
5
|
/** A Saved View that is being represented by the tile. */
|
|
6
6
|
savedView: SavedView;
|
|
7
|
+
/** Image to be displayed on the tile. */
|
|
8
|
+
thumbnail?: ReactNode | undefined;
|
|
7
9
|
/** A collection of available Saved View tags. Used for displaying tags on the tile. */
|
|
8
10
|
tags?: Map<string, SavedViewTag> | undefined;
|
|
9
11
|
/** When `true`, the tile becomes non-interactive and tile editing controls are shown. */
|
|
@@ -17,13 +19,12 @@ interface SavedViewTileProps {
|
|
|
17
19
|
/**
|
|
18
20
|
* Invoked when user submits a new name for the Saved View.
|
|
19
21
|
* @param savedViewId Id of the associated Saved View
|
|
20
|
-
* @param newName User-submitted string for the Saved View title
|
|
21
|
-
* operaton.
|
|
22
|
+
* @param newName User-submitted string for the Saved View title
|
|
22
23
|
*
|
|
23
24
|
* @example
|
|
24
25
|
* <SavedViewTile savedView={savedView} onRename={handleRename} editable />
|
|
25
26
|
*/
|
|
26
|
-
onRename?: ((savedViewId: string, newName: string
|
|
27
|
+
onRename?: ((savedViewId: string, newName: string) => void) | undefined;
|
|
27
28
|
/**
|
|
28
29
|
* Click handler meant for triggering the render of iModel onto the screen with the saved view applied
|
|
29
30
|
*/
|
|
@@ -34,7 +34,7 @@ export function SavedViewTile(props) {
|
|
|
34
34
|
}, [props.savedView.tagIds, props.tags]);
|
|
35
35
|
const [numShownTags, setNumShownTags] = useState(savedViewTags.length);
|
|
36
36
|
const metadataRef = useRef(null);
|
|
37
|
-
const metadata = (_jsxs("div", { className: "svr-tile--metadata", children: [savedViewTags.length > 0 && _jsx(SvgTag, {}), _jsx("div", { ref: metadataRef, className: "svr-tile--tag-container", children: savedViewTags.slice(0, numShownTags).map((tag, i) => (_jsx("div", { className: "svr-tile--tag", style: { flexShrink: i === numShownTags - 1 ? "unset" : 0 }, children: tag.displayName }, tag.
|
|
37
|
+
const metadata = (_jsxs("div", { className: "svr-tile--metadata", children: [savedViewTags.length > 0 && _jsx(SvgTag, {}), _jsx("div", { ref: metadataRef, className: "svr-tile--tag-container", children: savedViewTags.slice(0, numShownTags).map((tag, i) => (_jsx("div", { className: "svr-tile--tag", style: { flexShrink: i === numShownTags - 1 ? "unset" : 0 }, children: tag.displayName }, tag.tagId))) }), numShownTags < savedViewTags.length &&
|
|
38
38
|
_jsx(Text, { className: "svr-tile--tag-overflow", variant: "small", children: `+${savedViewTags.length - numShownTags} ${localization.tile.moreTags}` })] }));
|
|
39
39
|
useLayoutEffect(() => { setNumShownTags(savedViewTags.length); }, [savedViewTags]);
|
|
40
40
|
useLayoutEffect(() => {
|
|
@@ -57,17 +57,13 @@ export function SavedViewTile(props) {
|
|
|
57
57
|
}, [numShownTags]);
|
|
58
58
|
const rightIcons = props.rightIcons ?? (props.savedView.shared ? [_jsx(SvgShare, {}, "share")] : []);
|
|
59
59
|
const savedViewTileContext = useMemo(() => ({ savedView: props.savedView, setEditingName }), [props.savedView]);
|
|
60
|
-
return (_jsx(SavedViewTileContextProvider, { value: savedViewTileContext, children: _jsxs(Tile.Wrapper, { className: `svr-tile ${props.className || ""}`, onClick: () => props.onClick?.(props.savedView.
|
|
60
|
+
return (_jsx(SavedViewTileContextProvider, { value: savedViewTileContext, children: _jsxs(Tile.Wrapper, { className: `svr-tile ${props.className || ""}`, onClick: () => props.onClick?.(props.savedView.savedViewId), children: [!props.editable && _jsx(Tile.Action, {}), _jsx(Tile.Name, { className: "svr-tile-name", children: _jsx(EditableTileName, { displayName: props.savedView.displayName, editing: editingName, actions: {
|
|
61
61
|
onStartEditing: () => setEditingName(true),
|
|
62
62
|
onEndEditing: (newName, commit) => {
|
|
63
63
|
setEditingName(false);
|
|
64
|
-
props.onRename?.(props.savedView.
|
|
64
|
+
commit && props.onRename?.(props.savedView.savedViewId, newName);
|
|
65
65
|
},
|
|
66
|
-
}, editable: props.editable || editingName }) }), _jsxs(Tile.ThumbnailArea, { className: "svr-tile-thumbnail", children: [
|
|
67
|
-
? _jsx(Tile.ThumbnailPicture, { url: props.savedView.thumbnail })
|
|
68
|
-
: props.savedView.thumbnail
|
|
69
|
-
? props.savedView.thumbnail
|
|
70
|
-
: _jsx(Tile.ThumbnailPicture, { children: _jsx(SvgSavedView, {}) }), _jsx(TileIconContainer, { style: { placeSelf: "start" }, icons: props.leftIcons }), _jsx(TileIconContainer, { style: { placeSelf: "start end" }, icons: rightIcons })] }), _jsxs(Tile.ContentArea, { children: [_jsx(Tile.Metadata, { children: metadata }), (typeof props.options === "function" || (props.options && props.options.length > 0)) &&
|
|
66
|
+
}, editable: props.editable || editingName }) }), _jsxs(Tile.ThumbnailArea, { className: "svr-tile-thumbnail", children: [props.thumbnail ?? _jsx(Tile.ThumbnailPicture, { children: _jsx(SvgSavedView, {}) }), _jsx(TileIconContainer, { style: { placeSelf: "start" }, icons: props.leftIcons }), _jsx(TileIconContainer, { style: { placeSelf: "start end" }, icons: rightIcons })] }), _jsxs(Tile.ContentArea, { children: [_jsx(Tile.Metadata, { children: metadata }), (typeof props.options === "function" || (props.options && props.options.length > 0)) &&
|
|
71
67
|
_jsx("div", { className: "svr-tile--more-options", onClick: (ev) => ev.stopPropagation(), children: _jsx(LayeredDropdownMenu, { menuItems: props.options, children: _jsx(IconButton, { size: "small", styleType: "borderless", children: _jsx(SvgMore, {}) }) }) })] })] }) }));
|
|
72
68
|
}
|
|
73
69
|
function isOverflowing(element) {
|
|
@@ -14,7 +14,7 @@ export const SavedViewTileContextProvider = savedViewTileContext.Provider;
|
|
|
14
14
|
export function useSavedViewTileContext() {
|
|
15
15
|
const contextValue = useContext(savedViewTileContext);
|
|
16
16
|
return contextValue ?? {
|
|
17
|
-
savedView: {
|
|
17
|
+
savedView: { savedViewId: "SavedViewTileContext_NoContext", displayName: "" },
|
|
18
18
|
setEditingName: () => { },
|
|
19
19
|
};
|
|
20
20
|
}
|
|
@@ -1,31 +1,29 @@
|
|
|
1
|
-
import type { SavedView, SavedViewGroup, SavedViewTag } from "../SavedView.js";
|
|
2
|
-
import type {
|
|
1
|
+
import type { SavedView, SavedViewData, SavedViewGroup, SavedViewTag } from "../SavedView.js";
|
|
2
|
+
import type { CreateGroupArgs, CreateSavedViewArgs, CreateTagArgs, DeleteGroupArgs, DeleteSavedViewArgs, DeleteTagArgs, GetGroupsArgs, GetSavedViewByIdArgs, GetSavedViewDataByIdArgs, GetSavedViewsArgs, GetTagsArgs, GetThumbnailUrlArgs, SavedViewsClient, UpdateGroupArgs, UpdateSavedViewArgs, UpdateTagArgs, UploadThumbnailArgs } from "./SavedViewsClient.js";
|
|
3
3
|
interface ITwinSavedViewsClientParams {
|
|
4
|
-
/**
|
|
5
|
-
* Authorization token that grants access to iTwin Saved Views API. The token should be valid for `savedviews:read`
|
|
6
|
-
* and `savedviews:modify` OIDC scopes.
|
|
7
|
-
*/
|
|
4
|
+
/** Authorization token that grants access to iTwin Platform API. */
|
|
8
5
|
getAccessToken: () => Promise<string>;
|
|
9
|
-
/** @default "https://api.bentley.com/savedviews"
|
|
6
|
+
/** @default "https://api.bentley.com/savedviews" */
|
|
10
7
|
baseUrl?: string | undefined;
|
|
11
8
|
}
|
|
12
9
|
export declare class ITwinSavedViewsClient implements SavedViewsClient {
|
|
13
10
|
#private;
|
|
14
11
|
constructor(args: ITwinSavedViewsClientParams);
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
getThumbnailUrl(args:
|
|
19
|
-
uploadThumbnail(args:
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
12
|
+
getSavedViews(args: GetSavedViewsArgs): AsyncIterableIterator<SavedView[]>;
|
|
13
|
+
getGroups(args: GetGroupsArgs): Promise<SavedViewGroup[]>;
|
|
14
|
+
getTags(args: GetTagsArgs): Promise<SavedViewTag[]>;
|
|
15
|
+
getThumbnailUrl(args: GetThumbnailUrlArgs): Promise<string | undefined>;
|
|
16
|
+
uploadThumbnail(args: UploadThumbnailArgs): Promise<void>;
|
|
17
|
+
getSavedViewById(args: GetSavedViewByIdArgs): Promise<SavedView>;
|
|
18
|
+
getSavedViewDataById(args: GetSavedViewDataByIdArgs): Promise<SavedViewData>;
|
|
19
|
+
createSavedView(args: CreateSavedViewArgs): Promise<SavedView>;
|
|
20
|
+
updateSavedView(args: UpdateSavedViewArgs): Promise<SavedView>;
|
|
21
|
+
deleteSavedView(args: DeleteSavedViewArgs): Promise<void>;
|
|
22
|
+
createGroup(args: CreateGroupArgs): Promise<SavedViewGroup>;
|
|
23
|
+
updateGroup(args: UpdateGroupArgs): Promise<SavedViewGroup>;
|
|
24
|
+
deleteGroup(args: DeleteGroupArgs): Promise<void>;
|
|
25
|
+
createTag(args: CreateTagArgs): Promise<SavedViewTag>;
|
|
26
|
+
updateTag(args: UpdateTagArgs): Promise<SavedViewTag>;
|
|
27
|
+
deleteTag(args: DeleteTagArgs): Promise<void>;
|
|
30
28
|
}
|
|
31
29
|
export {};
|
|
@@ -2,23 +2,24 @@
|
|
|
2
2
|
* Copyright (c) Bentley Systems, Incorporated. All rights reserved.
|
|
3
3
|
* See LICENSE.md in the project root for license terms and full copyright notice.
|
|
4
4
|
*--------------------------------------------------------------------------------------------*/
|
|
5
|
-
import { ITwinSavedViewsClient as Client, } from "@itwin/saved-views-client";
|
|
5
|
+
import { ITwinSavedViewsClient as Client, isViewDataITwin3d, isViewDataITwinDrawing, } from "@itwin/saved-views-client";
|
|
6
6
|
export class ITwinSavedViewsClient {
|
|
7
7
|
#client;
|
|
8
8
|
constructor(args) {
|
|
9
9
|
this.#client = new Client(args);
|
|
10
10
|
}
|
|
11
|
-
async *
|
|
12
|
-
const iterable = this.#client.
|
|
11
|
+
async *getSavedViews(args) {
|
|
12
|
+
const iterable = this.#client.getAllSavedViewsMinimal({
|
|
13
13
|
iTwinId: args.iTwinId,
|
|
14
14
|
iModelId: args.iModelId,
|
|
15
|
+
groupId: args.groupId,
|
|
15
16
|
signal: args.signal,
|
|
16
17
|
});
|
|
17
18
|
for await (const page of iterable) {
|
|
18
19
|
yield page.savedViews.map(savedViewResponseToSavedView);
|
|
19
20
|
}
|
|
20
21
|
}
|
|
21
|
-
async
|
|
22
|
+
async getGroups(args) {
|
|
22
23
|
const response = await this.#client.getAllGroups({
|
|
23
24
|
iTwinId: args.iTwinId,
|
|
24
25
|
iModelId: args.iModelId,
|
|
@@ -26,7 +27,7 @@ export class ITwinSavedViewsClient {
|
|
|
26
27
|
});
|
|
27
28
|
return response.groups.map(groupResponseToSavedViewGroup);
|
|
28
29
|
}
|
|
29
|
-
async
|
|
30
|
+
async getTags(args) {
|
|
30
31
|
const response = await this.#client.getAllTags({
|
|
31
32
|
iTwinId: args.iTwinId,
|
|
32
33
|
iModelId: args.iModelId,
|
|
@@ -49,42 +50,55 @@ export class ITwinSavedViewsClient {
|
|
|
49
50
|
signal: args.signal,
|
|
50
51
|
});
|
|
51
52
|
}
|
|
52
|
-
async
|
|
53
|
-
const response = await this.#client.
|
|
53
|
+
async getSavedViewById(args) {
|
|
54
|
+
const response = await this.#client.getSavedViewMinimal({
|
|
54
55
|
savedViewId: args.savedViewId,
|
|
55
56
|
signal: args.signal,
|
|
56
57
|
});
|
|
57
58
|
return savedViewResponseToSavedView(response.savedView);
|
|
58
59
|
}
|
|
60
|
+
async getSavedViewDataById(args) {
|
|
61
|
+
const response = await this.#client.getSavedViewRepresentation({
|
|
62
|
+
savedViewId: args.savedViewId, signal: args.signal,
|
|
63
|
+
});
|
|
64
|
+
return {
|
|
65
|
+
viewData: getViewData(response.savedView),
|
|
66
|
+
extensions: response.savedView.extensions,
|
|
67
|
+
};
|
|
68
|
+
}
|
|
59
69
|
async createSavedView(args) {
|
|
70
|
+
const savedViewData = toApiSavedViewData(args.savedViewData.viewData);
|
|
60
71
|
const { savedView } = await this.#client.createSavedView({
|
|
61
72
|
iTwinId: args.iTwinId,
|
|
62
73
|
iModelId: args.iModelId,
|
|
63
|
-
displayName: args.
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
shared: args.
|
|
67
|
-
savedViewData
|
|
68
|
-
extensions: args.
|
|
74
|
+
displayName: args.displayName,
|
|
75
|
+
groupId: args.groupId,
|
|
76
|
+
tagIds: args.tagIds,
|
|
77
|
+
shared: args.shared,
|
|
78
|
+
savedViewData,
|
|
79
|
+
extensions: args.savedViewData.extensions,
|
|
69
80
|
signal: args.signal,
|
|
70
81
|
});
|
|
71
82
|
return savedViewResponseToSavedView(savedView);
|
|
72
83
|
}
|
|
73
84
|
async updateSavedView(args) {
|
|
85
|
+
const savedViewData = args.savedViewData && toApiSavedViewData(args.savedViewData.viewData);
|
|
74
86
|
const { savedView } = await this.#client.updateSavedView({
|
|
75
|
-
savedViewId: args.
|
|
76
|
-
displayName: args.
|
|
77
|
-
tagIds: args.
|
|
78
|
-
groupId: args.
|
|
79
|
-
shared: args.
|
|
80
|
-
savedViewData
|
|
87
|
+
savedViewId: args.savedViewId,
|
|
88
|
+
displayName: args.displayName,
|
|
89
|
+
tagIds: args.tagIds,
|
|
90
|
+
groupId: args.groupId,
|
|
91
|
+
shared: args.shared,
|
|
92
|
+
savedViewData,
|
|
81
93
|
signal: args.signal,
|
|
82
94
|
});
|
|
83
|
-
await Promise.all((args.
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
95
|
+
await Promise.all((args.savedViewData?.extensions ?? []).map(({ extensionName, data }) => {
|
|
96
|
+
this.#client.createExtension({
|
|
97
|
+
savedViewId: args.savedViewId,
|
|
98
|
+
extensionName,
|
|
99
|
+
data,
|
|
100
|
+
});
|
|
101
|
+
}));
|
|
88
102
|
return savedViewResponseToSavedView(savedView);
|
|
89
103
|
}
|
|
90
104
|
async deleteSavedView(args) {
|
|
@@ -94,25 +108,21 @@ export class ITwinSavedViewsClient {
|
|
|
94
108
|
const { group } = await this.#client.createGroup({
|
|
95
109
|
iTwinId: args.iTwinId,
|
|
96
110
|
iModelId: args.iModelId,
|
|
97
|
-
displayName: args.
|
|
111
|
+
displayName: args.displayName,
|
|
98
112
|
signal: args.signal,
|
|
99
113
|
});
|
|
100
114
|
return groupResponseToSavedViewGroup(group);
|
|
101
115
|
}
|
|
102
116
|
async updateGroup(args) {
|
|
103
117
|
const { group } = await this.#client.updateGroup({
|
|
104
|
-
groupId: args.
|
|
105
|
-
displayName: args.
|
|
106
|
-
shared: args.
|
|
118
|
+
groupId: args.groupId,
|
|
119
|
+
displayName: args.displayName,
|
|
120
|
+
shared: args.shared,
|
|
107
121
|
signal: args.signal,
|
|
108
122
|
});
|
|
109
123
|
return groupResponseToSavedViewGroup(group);
|
|
110
124
|
}
|
|
111
125
|
async deleteGroup(args) {
|
|
112
|
-
const savedViewPages = this.#client.getAllSavedViewsMinimal({ groupId: args.groupId, signal: args.signal });
|
|
113
|
-
for await (const savedViews of savedViewPages) {
|
|
114
|
-
await Promise.all(savedViews.savedViews.map(({ id }) => this.#client.deleteSavedView({ savedViewId: id, signal: args.signal })));
|
|
115
|
-
}
|
|
116
126
|
await this.#client.deleteGroup({ groupId: args.groupId, signal: args.signal });
|
|
117
127
|
}
|
|
118
128
|
async createTag(args) {
|
|
@@ -126,8 +136,8 @@ export class ITwinSavedViewsClient {
|
|
|
126
136
|
}
|
|
127
137
|
async updateTag(args) {
|
|
128
138
|
const { tag } = await this.#client.updateTag({
|
|
129
|
-
tagId: args.
|
|
130
|
-
displayName: args.
|
|
139
|
+
tagId: args.tagId,
|
|
140
|
+
displayName: args.displayName,
|
|
131
141
|
signal: args.signal,
|
|
132
142
|
});
|
|
133
143
|
return tagResponseToSavedViewTag(tag);
|
|
@@ -138,22 +148,19 @@ export class ITwinSavedViewsClient {
|
|
|
138
148
|
}
|
|
139
149
|
function savedViewResponseToSavedView(response) {
|
|
140
150
|
return {
|
|
141
|
-
|
|
151
|
+
savedViewId: response.id,
|
|
142
152
|
displayName: response.displayName,
|
|
143
|
-
viewData: response.savedViewData,
|
|
144
153
|
tagIds: response.tags?.map((tag) => tag.id),
|
|
145
154
|
groupId: response._links.group?.href.split("/").at(-1),
|
|
146
155
|
creatorId: response._links.creator?.href.split("/").at(-1),
|
|
147
156
|
shared: response.shared,
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
creationTime: response.creationTime,
|
|
151
|
-
lastModified: response.lastModified,
|
|
157
|
+
creationTime: new Date(response.creationTime),
|
|
158
|
+
lastModified: new Date(response.lastModified),
|
|
152
159
|
};
|
|
153
160
|
}
|
|
154
161
|
function groupResponseToSavedViewGroup(response) {
|
|
155
162
|
return {
|
|
156
|
-
|
|
163
|
+
groupId: response.id,
|
|
157
164
|
displayName: response.displayName,
|
|
158
165
|
creatorId: response._links.creator?.href.split("/").at(-1),
|
|
159
166
|
shared: response.shared,
|
|
@@ -161,7 +168,37 @@ function groupResponseToSavedViewGroup(response) {
|
|
|
161
168
|
}
|
|
162
169
|
function tagResponseToSavedViewTag(response) {
|
|
163
170
|
return {
|
|
164
|
-
|
|
171
|
+
tagId: response.id,
|
|
165
172
|
displayName: response.displayName,
|
|
166
173
|
};
|
|
167
174
|
}
|
|
175
|
+
function getViewData(savedView) {
|
|
176
|
+
if (isViewDataITwin3d(savedView.savedViewData)) {
|
|
177
|
+
return {
|
|
178
|
+
type: "iTwin3d",
|
|
179
|
+
...savedView.savedViewData.itwin3dView,
|
|
180
|
+
};
|
|
181
|
+
}
|
|
182
|
+
if (isViewDataITwinDrawing(savedView.savedViewData)) {
|
|
183
|
+
return {
|
|
184
|
+
type: "iTwinDrawing",
|
|
185
|
+
...savedView.savedViewData.itwinDrawingView,
|
|
186
|
+
};
|
|
187
|
+
}
|
|
188
|
+
return {
|
|
189
|
+
type: "iTwinSheet",
|
|
190
|
+
...savedView.savedViewData.itwinSheetView,
|
|
191
|
+
};
|
|
192
|
+
}
|
|
193
|
+
function toApiSavedViewData(viewData) {
|
|
194
|
+
if (viewData.type === "iTwin3d") {
|
|
195
|
+
const { type, ...rest } = viewData;
|
|
196
|
+
return { itwin3dView: rest };
|
|
197
|
+
}
|
|
198
|
+
if (viewData.type === "iTwinDrawing") {
|
|
199
|
+
const { type, ...rest } = viewData;
|
|
200
|
+
return { itwinDrawingView: rest };
|
|
201
|
+
}
|
|
202
|
+
const { type, ...rest } = viewData;
|
|
203
|
+
return { itwinSheetView: rest };
|
|
204
|
+
}
|