@itwin/map-layers 5.0.0-dev.3 → 5.1.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/CHANGELOG.md +20 -1
- package/lib/cjs/MapLayerPreferences.js +1 -1
- package/lib/cjs/MapLayerPreferences.js.map +1 -1
- package/lib/cjs/MapLayersPrefBrowserStorage.d.ts +5 -0
- package/lib/cjs/MapLayersPrefBrowserStorage.d.ts.map +1 -0
- package/lib/cjs/MapLayersPrefBrowserStorage.js +16 -0
- package/lib/cjs/MapLayersPrefBrowserStorage.js.map +1 -0
- package/lib/cjs/PreferencesBrowserStorage.d.ts +36 -0
- package/lib/cjs/PreferencesBrowserStorage.d.ts.map +1 -0
- package/lib/cjs/PreferencesBrowserStorage.js +92 -0
- package/lib/cjs/PreferencesBrowserStorage.js.map +1 -0
- package/lib/cjs/map-layers.d.ts +1 -0
- package/lib/cjs/map-layers.d.ts.map +1 -1
- package/lib/cjs/map-layers.js +1 -0
- package/lib/cjs/map-layers.js.map +1 -1
- package/lib/cjs/public/locales/en/mapLayers.json +7 -2
- package/lib/cjs/ui/widget/AttachLayerPopupButton.d.ts.map +1 -1
- package/lib/cjs/ui/widget/AttachLayerPopupButton.js +144 -64
- package/lib/cjs/ui/widget/AttachLayerPopupButton.js.map +1 -1
- package/lib/cjs/ui/widget/BasemapPanel.d.ts.map +1 -1
- package/lib/cjs/ui/widget/BasemapPanel.js +44 -15
- package/lib/cjs/ui/widget/BasemapPanel.js.map +1 -1
- package/lib/cjs/ui/widget/MapLayerDroppable.d.ts.map +1 -1
- package/lib/cjs/ui/widget/MapLayerDroppable.js +31 -3
- package/lib/cjs/ui/widget/MapLayerDroppable.js.map +1 -1
- package/lib/cjs/ui/widget/MapLayerManager.d.ts.map +1 -1
- package/lib/cjs/ui/widget/MapLayerManager.js +35 -57
- package/lib/cjs/ui/widget/MapLayerManager.js.map +1 -1
- package/lib/cjs/ui/widget/MapLayerManager.scss +2 -8
- package/lib/cjs/ui/widget/MapSelectFeaturesDialog.d.ts +11 -0
- package/lib/cjs/ui/widget/MapSelectFeaturesDialog.d.ts.map +1 -0
- package/lib/cjs/ui/widget/MapSelectFeaturesDialog.js +58 -0
- package/lib/cjs/ui/widget/MapSelectFeaturesDialog.js.map +1 -0
- package/lib/cjs/ui/widget/MapSelectFeaturesDialog.scss +17 -0
- package/lib/cjs/ui/widget/MapUrlDialog.d.ts +7 -2
- package/lib/cjs/ui/widget/MapUrlDialog.d.ts.map +1 -1
- package/lib/cjs/ui/widget/MapUrlDialog.js +38 -134
- package/lib/cjs/ui/widget/MapUrlDialog.js.map +1 -1
- package/lib/cjs/ui/widget/MapUrlDialog.scss +10 -10
- package/lib/cjs/ui/widget/SubLayersDataProvider.d.ts +3 -3
- package/lib/cjs/ui/widget/SubLayersDataProvider.d.ts.map +1 -1
- package/lib/cjs/ui/widget/SubLayersDataProvider.js +4 -5
- package/lib/cjs/ui/widget/SubLayersDataProvider.js.map +1 -1
- package/lib/cjs/ui/widget/SubLayersPopupButton.d.ts +3 -7
- package/lib/cjs/ui/widget/SubLayersPopupButton.d.ts.map +1 -1
- package/lib/cjs/ui/widget/SubLayersPopupButton.js +2 -2
- package/lib/cjs/ui/widget/SubLayersPopupButton.js.map +1 -1
- package/lib/cjs/ui/widget/SubLayersTree.d.ts +17 -9
- package/lib/cjs/ui/widget/SubLayersTree.d.ts.map +1 -1
- package/lib/cjs/ui/widget/SubLayersTree.js +59 -112
- package/lib/cjs/ui/widget/SubLayersTree.js.map +1 -1
- package/lib/cjs/ui/widget/SubLayersTree.scss +12 -3
- package/lib/esm/MapLayerPreferences.js +1 -1
- package/lib/esm/MapLayerPreferences.js.map +1 -1
- package/lib/esm/MapLayersPrefBrowserStorage.d.ts +5 -0
- package/lib/esm/MapLayersPrefBrowserStorage.d.ts.map +1 -0
- package/lib/esm/MapLayersPrefBrowserStorage.js +12 -0
- package/lib/esm/MapLayersPrefBrowserStorage.js.map +1 -0
- package/lib/esm/PreferencesBrowserStorage.d.ts +36 -0
- package/lib/esm/PreferencesBrowserStorage.d.ts.map +1 -0
- package/lib/esm/PreferencesBrowserStorage.js +88 -0
- package/lib/esm/PreferencesBrowserStorage.js.map +1 -0
- package/lib/esm/map-layers.d.ts +1 -0
- package/lib/esm/map-layers.d.ts.map +1 -1
- package/lib/esm/map-layers.js +1 -0
- package/lib/esm/map-layers.js.map +1 -1
- package/lib/esm/public/locales/en/mapLayers.json +7 -2
- package/lib/esm/ui/widget/AttachLayerPopupButton.d.ts.map +1 -1
- package/lib/esm/ui/widget/AttachLayerPopupButton.js +145 -65
- package/lib/esm/ui/widget/AttachLayerPopupButton.js.map +1 -1
- package/lib/esm/ui/widget/BasemapPanel.d.ts.map +1 -1
- package/lib/esm/ui/widget/BasemapPanel.js +44 -15
- package/lib/esm/ui/widget/BasemapPanel.js.map +1 -1
- package/lib/esm/ui/widget/MapLayerDroppable.d.ts.map +1 -1
- package/lib/esm/ui/widget/MapLayerDroppable.js +32 -4
- package/lib/esm/ui/widget/MapLayerDroppable.js.map +1 -1
- package/lib/esm/ui/widget/MapLayerManager.d.ts.map +1 -1
- package/lib/esm/ui/widget/MapLayerManager.js +36 -58
- package/lib/esm/ui/widget/MapLayerManager.js.map +1 -1
- package/lib/esm/ui/widget/MapLayerManager.scss +2 -8
- package/lib/esm/ui/widget/MapSelectFeaturesDialog.d.ts +11 -0
- package/lib/esm/ui/widget/MapSelectFeaturesDialog.d.ts.map +1 -0
- package/lib/esm/ui/widget/MapSelectFeaturesDialog.js +54 -0
- package/lib/esm/ui/widget/MapSelectFeaturesDialog.js.map +1 -0
- package/lib/esm/ui/widget/MapSelectFeaturesDialog.scss +17 -0
- package/lib/esm/ui/widget/MapUrlDialog.d.ts +7 -2
- package/lib/esm/ui/widget/MapUrlDialog.d.ts.map +1 -1
- package/lib/esm/ui/widget/MapUrlDialog.js +38 -134
- package/lib/esm/ui/widget/MapUrlDialog.js.map +1 -1
- package/lib/esm/ui/widget/MapUrlDialog.scss +10 -10
- package/lib/esm/ui/widget/SubLayersDataProvider.d.ts +3 -3
- package/lib/esm/ui/widget/SubLayersDataProvider.d.ts.map +1 -1
- package/lib/esm/ui/widget/SubLayersDataProvider.js +4 -5
- package/lib/esm/ui/widget/SubLayersDataProvider.js.map +1 -1
- package/lib/esm/ui/widget/SubLayersPopupButton.d.ts +3 -7
- package/lib/esm/ui/widget/SubLayersPopupButton.d.ts.map +1 -1
- package/lib/esm/ui/widget/SubLayersPopupButton.js +2 -2
- package/lib/esm/ui/widget/SubLayersPopupButton.js.map +1 -1
- package/lib/esm/ui/widget/SubLayersTree.d.ts +17 -9
- package/lib/esm/ui/widget/SubLayersTree.d.ts.map +1 -1
- package/lib/esm/ui/widget/SubLayersTree.js +60 -113
- package/lib/esm/ui/widget/SubLayersTree.js.map +1 -1
- package/lib/esm/ui/widget/SubLayersTree.scss +12 -3
- package/lib/public/locales/en/mapLayers.json +7 -2
- package/package.json +26 -25
|
@@ -0,0 +1,12 @@
|
|
|
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 { PreferencesBrowserStorage } from "./PreferencesBrowserStorage";
|
|
6
|
+
export class MapLayersPrefBrowserStorage extends PreferencesBrowserStorage {
|
|
7
|
+
constructor() {
|
|
8
|
+
super("itwinjs.mapLayers", { throwOnDeleteMissingKey: true } // 'MapLayerPreferences.replaceSource' expect 'delete' to throw when there is no match for the provided key.
|
|
9
|
+
);
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
//# sourceMappingURL=MapLayersPrefBrowserStorage.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"MapLayersPrefBrowserStorage.js","sourceRoot":"","sources":["../../src/MapLayersPrefBrowserStorage.ts"],"names":[],"mappings":"AAAA;;;+FAG+F;AAE/F,OAAO,EAAE,yBAAyB,EAAE,MAAM,6BAA6B,CAAC;AAExE,MAAM,OAAO,2BAA4B,SAAQ,yBAAyB;IACxE;QACE,KAAK,CAAC,mBAAmB,EACvB,EAAE,uBAAuB,EAAE,IAAI,EAAE,CAAG,4GAA4G;SACjJ,CAAC;IACJ,CAAC;CACF","sourcesContent":["/*---------------------------------------------------------------------------------------------\n* Copyright (c) Bentley Systems, Incorporated. All rights reserved.\n* See LICENSE.md in the project root for license terms and full copyright notice.\n*--------------------------------------------------------------------------------------------*/\n\nimport { PreferencesBrowserStorage } from \"./PreferencesBrowserStorage\";\n\nexport class MapLayersPrefBrowserStorage extends PreferencesBrowserStorage {\n constructor() {\n super(\"itwinjs.mapLayers\",\n { throwOnDeleteMissingKey: true } // 'MapLayerPreferences.replaceSource' expect 'delete' to throw when there is no match for the provided key.\n );\n }\n}\n"]}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { ITwinIdArg, PreferenceArg, PreferenceKeyArg, UserPreferencesAccess } from "@itwin/core-frontend";
|
|
2
|
+
/**
|
|
3
|
+
* @beta
|
|
4
|
+
*/
|
|
5
|
+
export interface PreferencesBrowserStorageOptions {
|
|
6
|
+
/** indicate whether or not delete function should throw an error if the provided key cannot be found. */
|
|
7
|
+
throwOnDeleteMissingKey?: boolean;
|
|
8
|
+
}
|
|
9
|
+
/** User preferences implementation using browser's local storage.
|
|
10
|
+
* It creates storage item key in the form of:
|
|
11
|
+
* <storageItemKeyPrefix>.<itwin_guid?>.<imodel_guid?>
|
|
12
|
+
*
|
|
13
|
+
* <itwin_guid> and <imodel_guid> being optional.
|
|
14
|
+
*
|
|
15
|
+
* Each entry in the storage is a serialized JSON of the following index signature:
|
|
16
|
+
* {
|
|
17
|
+
* "<preference_namespace?>.<preference_key>": {
|
|
18
|
+
* ...
|
|
19
|
+
* <preferences_json_content>
|
|
20
|
+
* },
|
|
21
|
+
* ...
|
|
22
|
+
* }
|
|
23
|
+
* @beta
|
|
24
|
+
*/
|
|
25
|
+
export declare class PreferencesBrowserStorage implements UserPreferencesAccess {
|
|
26
|
+
private readonly _options;
|
|
27
|
+
private readonly _storageItemKeyPrefix;
|
|
28
|
+
constructor(storageItemKeyPrefix: string, opts?: PreferencesBrowserStorageOptions);
|
|
29
|
+
private getStorageItemKey;
|
|
30
|
+
private static getPreferenceKey;
|
|
31
|
+
private loadFromStorage;
|
|
32
|
+
get(arg: PreferenceKeyArg & ITwinIdArg): Promise<any[] | undefined>;
|
|
33
|
+
delete(arg: PreferenceKeyArg & ITwinIdArg): Promise<void>;
|
|
34
|
+
save(arg: PreferenceArg & ITwinIdArg): Promise<void>;
|
|
35
|
+
}
|
|
36
|
+
//# sourceMappingURL=PreferencesBrowserStorage.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"PreferencesBrowserStorage.d.ts","sourceRoot":"","sources":["../../src/PreferencesBrowserStorage.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,UAAU,EAAE,aAAa,EAAE,gBAAgB,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAC;AAU1G;;EAEE;AACF,MAAM,WAAW,gCAAgC;IAC/C,yGAAyG;IACzG,uBAAuB,CAAC,EAAE,OAAO,CAAC;CACnC;AAED;;;;;;;;;;;;;;;EAeE;AACF,qBAAa,yBAA0B,YAAW,qBAAqB;IAErE,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAA+C;IACxE,OAAO,CAAC,QAAQ,CAAC,qBAAqB,CAAS;gBAEnC,oBAAoB,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,gCAAgC;IAKjF,OAAO,CAAC,iBAAiB;IAMzB,OAAO,CAAC,MAAM,CAAC,gBAAgB;IAK/B,OAAO,CAAC,eAAe;IAeV,GAAG,CAAC,GAAG,EAAE,gBAAgB,GAAG,UAAU;IAoBtC,MAAM,CAAC,GAAG,EAAE,gBAAgB,GAAG,UAAU;IAoBzC,IAAI,CAAC,GAAG,EAAE,aAAa,GAAG,UAAU;CAUlD"}
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
/** User preferences implementation using browser's local storage.
|
|
2
|
+
* It creates storage item key in the form of:
|
|
3
|
+
* <storageItemKeyPrefix>.<itwin_guid?>.<imodel_guid?>
|
|
4
|
+
*
|
|
5
|
+
* <itwin_guid> and <imodel_guid> being optional.
|
|
6
|
+
*
|
|
7
|
+
* Each entry in the storage is a serialized JSON of the following index signature:
|
|
8
|
+
* {
|
|
9
|
+
* "<preference_namespace?>.<preference_key>": {
|
|
10
|
+
* ...
|
|
11
|
+
* <preferences_json_content>
|
|
12
|
+
* },
|
|
13
|
+
* ...
|
|
14
|
+
* }
|
|
15
|
+
* @beta
|
|
16
|
+
*/
|
|
17
|
+
export class PreferencesBrowserStorage {
|
|
18
|
+
constructor(storageItemKeyPrefix, opts) {
|
|
19
|
+
this._options = opts;
|
|
20
|
+
this._storageItemKeyPrefix = storageItemKeyPrefix;
|
|
21
|
+
}
|
|
22
|
+
getStorageItemKey(arg) {
|
|
23
|
+
const itwinIdStr = arg.iTwinId ? `.${arg.iTwinId}` : "";
|
|
24
|
+
const imodelIdStr = arg.iModelId ? `.${arg.iModelId}` : "";
|
|
25
|
+
return `${this._storageItemKeyPrefix}${itwinIdStr}${imodelIdStr}`;
|
|
26
|
+
}
|
|
27
|
+
static getPreferenceKey(arg) {
|
|
28
|
+
const nsStr = arg.namespace ? `${arg.namespace}.` : "";
|
|
29
|
+
return `${nsStr}${arg.key}`;
|
|
30
|
+
}
|
|
31
|
+
loadFromStorage(arg) {
|
|
32
|
+
const storage = window.localStorage;
|
|
33
|
+
let map = {};
|
|
34
|
+
const itemStr = storage.getItem(this.getStorageItemKey(arg));
|
|
35
|
+
if (itemStr === null) {
|
|
36
|
+
return undefined;
|
|
37
|
+
}
|
|
38
|
+
if (!itemStr || itemStr === "{}")
|
|
39
|
+
return map;
|
|
40
|
+
map = JSON.parse(itemStr);
|
|
41
|
+
return map;
|
|
42
|
+
}
|
|
43
|
+
async get(arg) {
|
|
44
|
+
const map = this.loadFromStorage(arg);
|
|
45
|
+
if (map === undefined)
|
|
46
|
+
return undefined;
|
|
47
|
+
if (arg.key) {
|
|
48
|
+
if (!Object.keys(map).includes(arg.key))
|
|
49
|
+
return undefined;
|
|
50
|
+
const nsStr = arg.namespace ? `${arg.namespace}.` : "";
|
|
51
|
+
const prefKey = `${nsStr}${arg.key}`;
|
|
52
|
+
return [map[prefKey]];
|
|
53
|
+
}
|
|
54
|
+
else { // No key provided, return all objects
|
|
55
|
+
const values = [];
|
|
56
|
+
for (const [_key, value] of Object.entries(map))
|
|
57
|
+
values.push(value);
|
|
58
|
+
return values;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
async delete(arg) {
|
|
62
|
+
const map = this.loadFromStorage(arg);
|
|
63
|
+
if (map === undefined) {
|
|
64
|
+
if (this._options?.throwOnDeleteMissingKey)
|
|
65
|
+
throw new Error("Could not find key from storage.");
|
|
66
|
+
else
|
|
67
|
+
return;
|
|
68
|
+
}
|
|
69
|
+
const prefKey = PreferencesBrowserStorage.getPreferenceKey(arg);
|
|
70
|
+
if (!Object.keys(map).includes(prefKey)) {
|
|
71
|
+
if (this._options?.throwOnDeleteMissingKey)
|
|
72
|
+
throw Error("Could not find key from storage.");
|
|
73
|
+
else
|
|
74
|
+
return;
|
|
75
|
+
}
|
|
76
|
+
delete map[prefKey];
|
|
77
|
+
window.localStorage.setItem(this.getStorageItemKey(arg), JSON.stringify(map));
|
|
78
|
+
}
|
|
79
|
+
async save(arg) {
|
|
80
|
+
let map = this.loadFromStorage(arg);
|
|
81
|
+
if (map === undefined)
|
|
82
|
+
map = {};
|
|
83
|
+
map[PreferencesBrowserStorage.getPreferenceKey(arg)] = arg.content;
|
|
84
|
+
const itemValue = JSON.stringify(map);
|
|
85
|
+
window.localStorage.setItem(this.getStorageItemKey(arg), itemValue);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
//# sourceMappingURL=PreferencesBrowserStorage.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"PreferencesBrowserStorage.js","sourceRoot":"","sources":["../../src/PreferencesBrowserStorage.ts"],"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 { ITwinIdArg, PreferenceArg, PreferenceKeyArg, UserPreferencesAccess } from \"@itwin/core-frontend\";\n\n/** Index signature holding preferences content\n *\n * @internal\n */\ninterface KeyContentProps {\n [preferenceKey: string]: any;\n}\n\n/**\n* @beta\n*/\nexport interface PreferencesBrowserStorageOptions {\n /** indicate whether or not delete function should throw an error if the provided key cannot be found. */\n throwOnDeleteMissingKey?: boolean;\n}\n\n/** User preferences implementation using browser's local storage.\n * It creates storage item key in the form of:\n * <storageItemKeyPrefix>.<itwin_guid?>.<imodel_guid?>\n *\n * <itwin_guid> and <imodel_guid> being optional.\n *\n * Each entry in the storage is a serialized JSON of the following index signature:\n * {\n * \"<preference_namespace?>.<preference_key>\": {\n * ...\n * <preferences_json_content>\n * },\n * ...\n * }\n * @beta\n*/\nexport class PreferencesBrowserStorage implements UserPreferencesAccess {\n\n private readonly _options: PreferencesBrowserStorageOptions | undefined;\n private readonly _storageItemKeyPrefix: string;\n\n constructor(storageItemKeyPrefix: string, opts?: PreferencesBrowserStorageOptions) {\n this._options = opts;\n this._storageItemKeyPrefix = storageItemKeyPrefix;\n }\n\n private getStorageItemKey(arg: ITwinIdArg) {\n const itwinIdStr = arg.iTwinId ? `.${arg.iTwinId}` : \"\";\n const imodelIdStr = arg.iModelId ? `.${arg.iModelId}` : \"\";\n return `${this._storageItemKeyPrefix}${itwinIdStr}${imodelIdStr}`;\n }\n\n private static getPreferenceKey(arg: PreferenceKeyArg) {\n const nsStr = arg.namespace ? `${arg.namespace}.` : \"\";\n return `${nsStr}${arg.key}`;\n }\n\n private loadFromStorage(arg: PreferenceKeyArg & ITwinIdArg) {\n const storage = window.localStorage;\n\n let map: KeyContentProps = {};\n const itemStr = storage.getItem(this.getStorageItemKey(arg));\n if (itemStr === null) {\n return undefined;\n }\n if (!itemStr || itemStr === \"{}\")\n return map;\n\n map = JSON.parse(itemStr);\n return map;\n }\n\n public async get(arg: PreferenceKeyArg & ITwinIdArg) {\n const map = this.loadFromStorage(arg);\n if (map === undefined)\n return undefined;\n\n if (arg.key) {\n if (!Object.keys(map).includes(arg.key))\n return undefined;\n\n const nsStr = arg.namespace ? `${arg.namespace}.` : \"\";\n const prefKey = `${nsStr}${arg.key}`;\n return [map[prefKey]];\n } else { // No key provided, return all objects\n const values = [];\n for (const [_key, value] of Object.entries(map))\n values.push(value);\n return values;\n }\n }\n\n public async delete(arg: PreferenceKeyArg & ITwinIdArg) {\n const map = this.loadFromStorage(arg);\n if (map === undefined) {\n if (this._options?.throwOnDeleteMissingKey)\n throw new Error(\"Could not find key from storage.\");\n else\n return;\n }\n\n const prefKey = PreferencesBrowserStorage.getPreferenceKey(arg);\n if (!Object.keys(map).includes(prefKey)) {\n if (this._options?.throwOnDeleteMissingKey)\n throw Error(\"Could not find key from storage.\");\n else\n return;\n }\n delete map[prefKey];\n window.localStorage.setItem(this.getStorageItemKey(arg), JSON.stringify(map));\n }\n\n public async save(arg: PreferenceArg & ITwinIdArg) {\n let map = this.loadFromStorage(arg);\n if (map === undefined)\n map = {};\n\n map[PreferencesBrowserStorage.getPreferenceKey(arg)] = arg.content;\n\n const itemValue = JSON.stringify(map);\n window.localStorage.setItem(this.getStorageItemKey(arg), itemValue);\n }\n}\n"]}
|
package/lib/esm/map-layers.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"map-layers.d.ts","sourceRoot":"","sources":["../../src/map-layers.ts"],"names":[],"mappings":"AAIA,cAAc,aAAa,CAAC;AAC5B,cAAc,iBAAiB,CAAC;AAChC,cAAc,+BAA+B,CAAC;AAC9C,cAAc,iCAAiC,CAAC;AAChD,cAAc,yBAAyB,CAAC;AACxC,cAAc,6BAA6B,CAAC"}
|
|
1
|
+
{"version":3,"file":"map-layers.d.ts","sourceRoot":"","sources":["../../src/map-layers.ts"],"names":[],"mappings":"AAIA,cAAc,aAAa,CAAC;AAC5B,cAAc,+BAA+B,CAAC;AAC9C,cAAc,iBAAiB,CAAC;AAChC,cAAc,+BAA+B,CAAC;AAC9C,cAAc,iCAAiC,CAAC;AAChD,cAAc,yBAAyB,CAAC;AACxC,cAAc,6BAA6B,CAAC"}
|
package/lib/esm/map-layers.js
CHANGED
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
* See LICENSE.md in the project root for license terms and full copyright notice.
|
|
4
4
|
*--------------------------------------------------------------------------------------------*/
|
|
5
5
|
export * from "./mapLayers";
|
|
6
|
+
export * from "./MapLayersPrefBrowserStorage";
|
|
6
7
|
export * from "./ui/Interfaces";
|
|
7
8
|
export * from "./ui/MapLayersUiItemsProvider";
|
|
8
9
|
export * from "./ui/FeatureInfoUiItemsProvider";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"map-layers.js","sourceRoot":"","sources":["../../src/map-layers.ts"],"names":[],"mappings":"AAAA;;;+FAG+F;AAC/F,cAAc,aAAa,CAAC;AAC5B,cAAc,iBAAiB,CAAC;AAChC,cAAc,+BAA+B,CAAC;AAC9C,cAAc,iCAAiC,CAAC;AAChD,cAAc,yBAAyB,CAAC;AACxC,cAAc,6BAA6B,CAAC","sourcesContent":["/*---------------------------------------------------------------------------------------------\r\n* Copyright (c) Bentley Systems, Incorporated. All rights reserved.\r\n* See LICENSE.md in the project root for license terms and full copyright notice.\r\n*--------------------------------------------------------------------------------------------*/\r\nexport * from \"./mapLayers\";\r\nexport * from \"./ui/Interfaces\";\r\nexport * from \"./ui/MapLayersUiItemsProvider\";\r\nexport * from \"./ui/FeatureInfoUiItemsProvider\";\r\nexport * from \"./ui/MapFeatureInfoTool\";\r\nexport * from \"./ui/widget/MapLayersWidget\";\r\n"]}
|
|
1
|
+
{"version":3,"file":"map-layers.js","sourceRoot":"","sources":["../../src/map-layers.ts"],"names":[],"mappings":"AAAA;;;+FAG+F;AAC/F,cAAc,aAAa,CAAC;AAC5B,cAAc,+BAA+B,CAAC;AAC9C,cAAc,iBAAiB,CAAC;AAChC,cAAc,+BAA+B,CAAC;AAC9C,cAAc,iCAAiC,CAAC;AAChD,cAAc,yBAAyB,CAAC;AACxC,cAAc,6BAA6B,CAAC","sourcesContent":["/*---------------------------------------------------------------------------------------------\r\n* Copyright (c) Bentley Systems, Incorporated. All rights reserved.\r\n* See LICENSE.md in the project root for license terms and full copyright notice.\r\n*--------------------------------------------------------------------------------------------*/\r\nexport * from \"./mapLayers\";\r\nexport * from \"./MapLayersPrefBrowserStorage\";\r\nexport * from \"./ui/Interfaces\";\r\nexport * from \"./ui/MapLayersUiItemsProvider\";\r\nexport * from \"./ui/FeatureInfoUiItemsProvider\";\r\nexport * from \"./ui/MapFeatureInfoTool\";\r\nexport * from \"./ui/widget/MapLayersWidget\";\r\n"]}
|
|
@@ -39,15 +39,18 @@
|
|
|
39
39
|
"MissingCredentials": "This layer requires credentials to be provided",
|
|
40
40
|
"Name": "Name",
|
|
41
41
|
"NameInputPlaceHolder": "Enter Map Name",
|
|
42
|
+
"NoLayersSelected": "Please select at least one layer",
|
|
42
43
|
"RemoveLayerDefButtonTitle": "Delete layer definition",
|
|
43
44
|
"RemoveLayerDefDialogMessage": "Are you sure you want to delete {{layerName}} ?",
|
|
44
45
|
"RemoveLayerDefDialogTitle": "Delete layer definition",
|
|
45
46
|
"RemoveLayerDefError": "Could not delete map layer definition: {{layerName}}",
|
|
46
47
|
"RemoveLayerDefSuccess": "Successfully deleted map layer definition: {{layerName}}",
|
|
47
48
|
"SearchPlaceholder": "Search...",
|
|
49
|
+
"SelectLayersToCreate": "Select layers to be created",
|
|
48
50
|
"StoreOnModelSettings": "Store on Model Settings",
|
|
49
51
|
"StoreOnITwinSettings": "Store on iTwin Settings",
|
|
50
52
|
"TechPreviewBadgeTooltip": "Technology preview",
|
|
53
|
+
"TooManyLayersSelected": "There are currently {{layerCount}} layers selected; Adding too many layers may impact performance.",
|
|
51
54
|
"Type": "Type",
|
|
52
55
|
"URL": "URL",
|
|
53
56
|
"UrlInputPlaceHolder": "Enter Map Source URL",
|
|
@@ -64,9 +67,10 @@
|
|
|
64
67
|
"NotSupported": "No active viewport or geo-located iModel available.",
|
|
65
68
|
"NoRangeDefined": "No range is defined for Map Layer",
|
|
66
69
|
"Start": "Map Layers Extension Loaded",
|
|
67
|
-
"MapLayerAttached": "Map layer {{
|
|
70
|
+
"MapLayerAttached": "Map layer {{layerNames}} attached",
|
|
71
|
+
"MapLayersAttached": "Map layers ({{sourceName}}) attached",
|
|
68
72
|
"MapLayerAttachedRequiresAuth": "Map layer {{sourceName}} attached, but requires credentials to be provided",
|
|
69
|
-
"MapLayerAttachError": "Error '{{error}}' occurred attaching MapLayer
|
|
73
|
+
"MapLayerAttachError": "Error '{{error}}' occurred attaching MapLayer '{{sourceName}}'",
|
|
70
74
|
"MapLayerAttachMissingViewOrSource": "Missing view or source",
|
|
71
75
|
"MapLayerEditError": "Failed to edit '{{layerName}}'",
|
|
72
76
|
"MapLayerLayerSettingsConversionError": "Conversion to layer settings failed",
|
|
@@ -119,6 +123,7 @@
|
|
|
119
123
|
"AllOn": "Turn on all Sub-layers",
|
|
120
124
|
"AllOff": "Turn off all Sub-layers",
|
|
121
125
|
"Hide": "Hide Sub-layers",
|
|
126
|
+
"NoResults": "No Results",
|
|
122
127
|
"NoSubLayers": "No Sub-layers Available",
|
|
123
128
|
"SearchPlaceholder": "Search...",
|
|
124
129
|
"Show": "Show Sub-layers"
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AttachLayerPopupButton.d.ts","sourceRoot":"","sources":["../../../../src/ui/widget/AttachLayerPopupButton.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"AttachLayerPopupButton.d.ts","sourceRoot":"","sources":["../../../../src/ui/widget/AttachLayerPopupButton.tsx"],"names":[],"mappings":"AAocA,gBAAgB;AAChB,oBAAY,qBAAqB;IAC/B,OAAO,IAAA;IACP,IAAI,IAAA;IACJ,IAAI,IAAA;CACL;AACD,MAAM,WAAW,2BAA2B;IAC1C,SAAS,EAAE,OAAO,CAAC;IACnB,UAAU,CAAC,EAAE,qBAAqB,CAAC;IACnC,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAED,gBAAgB;AAEhB,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,2BAA2B,eAkHxE"}
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
* See LICENSE.md in the project root for license terms and full copyright notice.
|
|
4
4
|
*--------------------------------------------------------------------------------------------*/
|
|
5
5
|
import * as React from "react";
|
|
6
|
-
import { IModelApp, MapLayerSourceStatus, NotifyMessageDetails, OutputMessagePriority } from "@itwin/core-frontend";
|
|
6
|
+
import { IModelApp, MapLayerSource, MapLayerSourceStatus, NotifyMessageDetails, OutputMessagePriority } from "@itwin/core-frontend";
|
|
7
7
|
import { RelativePosition } from "@itwin/appui-abstract";
|
|
8
8
|
import * as UiCore from "@itwin/core-react";
|
|
9
9
|
import { UiFramework } from "@itwin/appui-react";
|
|
@@ -13,11 +13,12 @@ import { ConfirmMessageDialog } from "./ConfirmMessageDialog";
|
|
|
13
13
|
import { Button, Input } from "@itwin/itwinui-react";
|
|
14
14
|
import { MapLayerPreferences } from "../../MapLayerPreferences";
|
|
15
15
|
import { MapLayersUI } from "../../mapLayers";
|
|
16
|
+
import { MapSelectFeaturesDialog } from "./MapSelectFeaturesDialog";
|
|
16
17
|
// cSpell:ignore droppable Sublayer
|
|
17
18
|
var LayerAction;
|
|
18
19
|
(function (LayerAction) {
|
|
19
|
-
LayerAction[LayerAction["
|
|
20
|
-
LayerAction[LayerAction["
|
|
20
|
+
LayerAction[LayerAction["New"] = 0] = "New";
|
|
21
|
+
LayerAction[LayerAction["Edit"] = 1] = "Edit";
|
|
21
22
|
})(LayerAction || (LayerAction = {}));
|
|
22
23
|
// eslint-disable-next-line @typescript-eslint/naming-convention
|
|
23
24
|
function AttachLayerPanel({ isOverlay, onLayerAttached, onHandleOutsideClick }) {
|
|
@@ -60,93 +61,172 @@ function AttachLayerPanel({ isOverlay, onLayerAttached, onHandleOutsideClick })
|
|
|
60
61
|
const mapTypesOptions = mapLayerOptions?.mapTypeOptions;
|
|
61
62
|
const iTwinId = activeViewport?.iModel?.iTwinId;
|
|
62
63
|
const iModelId = activeViewport?.iModel?.iModelId;
|
|
63
|
-
const
|
|
64
|
-
if (
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
64
|
+
const attachLayer = React.useCallback((source, subLayers, oneMapLayerPerSubLayer) => {
|
|
65
|
+
if (activeViewport) {
|
|
66
|
+
const generateUniqueMapLayerName = (layerName) => {
|
|
67
|
+
let uniqueLayerName = layerName;
|
|
68
|
+
let layerNameIdx = 1;
|
|
69
|
+
while ((backgroundLayers && backgroundLayers.some((layer) => uniqueLayerName === layer.name))
|
|
70
|
+
|| (overlayLayers && overlayLayers.some((layer) => uniqueLayerName === layer.name))) {
|
|
71
|
+
uniqueLayerName = `${layerName} (${layerNameIdx++})`;
|
|
72
|
+
}
|
|
73
|
+
return { layerNameUpdate: layerNameIdx > 1, uniqueLayerName };
|
|
74
|
+
};
|
|
75
|
+
const doAttachLayer = (layerName, subLayer) => {
|
|
76
|
+
const generatedName = generateUniqueMapLayerName(layerName);
|
|
77
|
+
let sourceToAdd = source;
|
|
78
|
+
if (generatedName.layerNameUpdate || sourceToAdd.name !== generatedName.uniqueLayerName) {
|
|
79
|
+
// create a source with a unique name
|
|
80
|
+
const clonedSource = MapLayerSource.fromJSON({ ...source.toJSON(), name: generatedName.uniqueLayerName });
|
|
81
|
+
if (clonedSource !== undefined) {
|
|
82
|
+
clonedSource.userName = source.userName;
|
|
83
|
+
clonedSource.password = source.password;
|
|
84
|
+
sourceToAdd = clonedSource;
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
const settings = sourceToAdd.toLayerSettings(subLayer ? [subLayer] : subLayers);
|
|
88
|
+
if (settings) {
|
|
89
|
+
activeViewport.displayStyle.attachMapLayer({ settings, mapLayerIndex: { index: -1, isOverlay } });
|
|
90
|
+
return generatedName.uniqueLayerName;
|
|
91
|
+
}
|
|
92
|
+
return undefined;
|
|
93
|
+
};
|
|
94
|
+
if (oneMapLayerPerSubLayer && subLayers) {
|
|
95
|
+
const layerNamesAttached = [];
|
|
96
|
+
for (const subLayer of subLayers) {
|
|
97
|
+
const attachedLayerName = doAttachLayer(`${source.name} - ${subLayer.name}`, subLayer);
|
|
98
|
+
if (attachedLayerName !== undefined) {
|
|
99
|
+
layerNamesAttached.push(attachedLayerName);
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
if (layerNamesAttached.length > 0) {
|
|
103
|
+
const msg = IModelApp.localization.getLocalizedString("mapLayers:Messages.MapLayersAttached", { layerNames: layerNamesAttached.join(", ") });
|
|
104
|
+
IModelApp.notifications.outputMessage(new NotifyMessageDetails(OutputMessagePriority.Info, msg));
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
else {
|
|
108
|
+
const attachedLayerName = doAttachLayer(source.name);
|
|
109
|
+
if (attachedLayerName !== undefined) {
|
|
110
|
+
const msg = IModelApp.localization.getLocalizedString("mapLayers:Messages.MapLayerAttached", { sourceName: attachedLayerName });
|
|
111
|
+
IModelApp.notifications.outputMessage(new NotifyMessageDetails(OutputMessagePriority.Info, msg));
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
if (isMounted.current) {
|
|
115
|
+
setLoading(false);
|
|
116
|
+
}
|
|
71
117
|
}
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
118
|
+
onLayerAttached();
|
|
119
|
+
resumeOutsideClick();
|
|
120
|
+
}, [activeViewport, backgroundLayers, isOverlay, onLayerAttached, overlayLayers, resumeOutsideClick]);
|
|
121
|
+
const handleSelectFeaturesCancel = React.useCallback(() => {
|
|
122
|
+
if (isMounted.current) {
|
|
123
|
+
setLoading(false);
|
|
78
124
|
}
|
|
79
125
|
resumeOutsideClick();
|
|
80
|
-
|
|
126
|
+
UiFramework.dialogs.modal.close();
|
|
127
|
+
}, [resumeOutsideClick, setLoading]);
|
|
128
|
+
const handleSelectFeaturesOk = React.useCallback((source, sourceSubLayers, selectedSubLayers) => {
|
|
129
|
+
// keep only visible subLayers
|
|
130
|
+
const visibleSubLayers = selectedSubLayers.filter((value) => value.visible);
|
|
131
|
+
// Re-apply default visibility from the source validation
|
|
132
|
+
visibleSubLayers.forEach((visible) => {
|
|
133
|
+
const found = sourceSubLayers.find((value) => { visible.name === value.name; });
|
|
134
|
+
if (found)
|
|
135
|
+
visible.visible = found?.visible;
|
|
136
|
+
});
|
|
137
|
+
attachLayer(source, visibleSubLayers, true);
|
|
138
|
+
}, [attachLayer]);
|
|
139
|
+
const openFeatureSelectionDialog = React.useCallback((subLayers, source) => {
|
|
140
|
+
// Keep leafs sub-layers and force default visibility to false
|
|
141
|
+
const noGroupLayers = subLayers.filter((value) => value.children === undefined);
|
|
142
|
+
const visibleLayers = noGroupLayers.map((value) => { return { ...value, visible: false }; });
|
|
143
|
+
UiFramework.dialogs.modal.open(React.createElement(MapSelectFeaturesDialog, { handleOk: (selectedLayers) => { handleSelectFeaturesOk(source, subLayers, selectedLayers); }, handleCancel: handleSelectFeaturesCancel, source: source, subLayers: visibleLayers }));
|
|
144
|
+
}, [handleSelectFeaturesCancel, handleSelectFeaturesOk]);
|
|
145
|
+
const needsFeatureSelection = React.useCallback((source, validation) => {
|
|
146
|
+
return (source.formatId === "ArcGISFeature" || source.formatId === "WMTS") // TODO, replace this with a flag in MapLayerSourceStatus
|
|
147
|
+
&& validation.subLayers
|
|
148
|
+
&& validation.subLayers.length > 1;
|
|
149
|
+
}, []);
|
|
150
|
+
const handleModalUrlDialogOk = React.useCallback((action, sourceState) => {
|
|
151
|
+
UiFramework.dialogs.modal.close();
|
|
152
|
+
if (LayerAction.New === action
|
|
153
|
+
&& sourceState
|
|
154
|
+
&& (sourceState.validation.status === MapLayerSourceStatus.Valid)) {
|
|
155
|
+
if (needsFeatureSelection(sourceState.source, sourceState.validation)) {
|
|
156
|
+
openFeatureSelectionDialog(sourceState.validation.subLayers, sourceState.source);
|
|
157
|
+
}
|
|
158
|
+
else {
|
|
159
|
+
attachLayer(sourceState.source, sourceState.validation.subLayers, false);
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
else {
|
|
163
|
+
resumeOutsideClick();
|
|
164
|
+
}
|
|
165
|
+
}, [attachLayer, needsFeatureSelection, openFeatureSelectionDialog, resumeOutsideClick]);
|
|
81
166
|
const handleModalUrlDialogCancel = React.useCallback(() => {
|
|
82
167
|
// close popup and refresh UI
|
|
83
168
|
setLoading(false);
|
|
84
169
|
UiFramework.dialogs.modal.close();
|
|
85
170
|
resumeOutsideClick();
|
|
86
|
-
}, [resumeOutsideClick]);
|
|
171
|
+
}, [setLoading, resumeOutsideClick]);
|
|
87
172
|
React.useEffect(() => {
|
|
88
|
-
async function attemptToAddLayer(
|
|
89
|
-
if (
|
|
173
|
+
async function attemptToAddLayer() {
|
|
174
|
+
if (layerNameToAdd && activeViewport) {
|
|
90
175
|
// if the layer is not in the style add it now.
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
176
|
+
const mapLayerSettings = sources?.find((source) => source.name === layerNameToAdd);
|
|
177
|
+
if (mapLayerSettings === undefined) {
|
|
178
|
+
return;
|
|
179
|
+
}
|
|
180
|
+
try {
|
|
181
|
+
if (isMounted.current) {
|
|
182
|
+
setLoading(true);
|
|
95
183
|
}
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
if (status === MapLayerSourceStatus.Valid || status === MapLayerSourceStatus.RequireAuth) {
|
|
102
|
-
if (status === MapLayerSourceStatus.Valid) {
|
|
103
|
-
const settings = mapLayerSettings.toLayerSettings(subLayers);
|
|
104
|
-
if (settings) {
|
|
105
|
-
activeViewport.displayStyle.attachMapLayer({ settings, mapLayerIndex: { index: -1, isOverlay } });
|
|
106
|
-
const msg = IModelApp.localization.getLocalizedString("mapLayers:Messages.MapLayerAttached", { sourceName: settings.name, sourceUrl: settings.url });
|
|
107
|
-
IModelApp.notifications.outputMessage(new NotifyMessageDetails(OutputMessagePriority.Info, msg));
|
|
108
|
-
}
|
|
109
|
-
if (isMounted.current) {
|
|
110
|
-
setLoading(false);
|
|
111
|
-
}
|
|
112
|
-
if (onLayerAttached) {
|
|
113
|
-
onLayerAttached();
|
|
114
|
-
}
|
|
115
|
-
}
|
|
116
|
-
else if (status === MapLayerSourceStatus.RequireAuth && isMounted.current) {
|
|
117
|
-
UiFramework.dialogs.modal.open(React.createElement(MapUrlDialog, { activeViewport: activeViewport, isOverlay: isOverlay, layerRequiringCredentials: mapLayerSettings.toJSON(), onOkResult: () => handleModalUrlDialogOk(LayerAction.Attached), onCancelResult: handleModalUrlDialogCancel, mapTypesOptions: mapTypesOptions }));
|
|
184
|
+
const sourceValidation = await mapLayerSettings.validateSource();
|
|
185
|
+
if (sourceValidation.status === MapLayerSourceStatus.Valid || sourceValidation.status === MapLayerSourceStatus.RequireAuth) {
|
|
186
|
+
if (sourceValidation.status === MapLayerSourceStatus.Valid) {
|
|
187
|
+
if (sourceValidation.subLayers && needsFeatureSelection(mapLayerSettings, sourceValidation)) {
|
|
188
|
+
openFeatureSelectionDialog(sourceValidation.subLayers, mapLayerSettings);
|
|
118
189
|
if (onHandleOutsideClick) {
|
|
119
190
|
onHandleOutsideClick(false);
|
|
120
191
|
}
|
|
121
192
|
}
|
|
193
|
+
else {
|
|
194
|
+
attachLayer(mapLayerSettings, sourceValidation.subLayers, false);
|
|
195
|
+
}
|
|
122
196
|
}
|
|
123
|
-
else {
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
setLoading(false);
|
|
197
|
+
else if (sourceValidation.status === MapLayerSourceStatus.RequireAuth && isMounted.current) {
|
|
198
|
+
UiFramework.dialogs.modal.open(React.createElement(MapUrlDialog, { activeViewport: activeViewport, isOverlay: isOverlay, layerRequiringCredentials: mapLayerSettings.toJSON(), onOkResult: (sourceState) => handleModalUrlDialogOk(LayerAction.New, sourceState), onCancelResult: handleModalUrlDialogCancel, mapTypesOptions: mapTypesOptions }));
|
|
199
|
+
if (onHandleOutsideClick) {
|
|
200
|
+
onHandleOutsideClick(false);
|
|
128
201
|
}
|
|
129
202
|
}
|
|
130
203
|
}
|
|
131
|
-
|
|
204
|
+
else {
|
|
205
|
+
const msg = IModelApp.localization.getLocalizedString("mapLayers:Messages.MapLayerValidationFailed", { sourceUrl: mapLayerSettings.url });
|
|
206
|
+
IModelApp.notifications.outputMessage(new NotifyMessageDetails(OutputMessagePriority.Error, msg));
|
|
132
207
|
if (isMounted.current) {
|
|
133
208
|
setLoading(false);
|
|
134
209
|
}
|
|
135
|
-
const msg = IModelApp.localization.getLocalizedString("mapLayers:Messages.MapLayerAttachError", { error: err, sourceUrl: mapLayerSettings.url });
|
|
136
|
-
IModelApp.notifications.outputMessage(new NotifyMessageDetails(OutputMessagePriority.Error, msg));
|
|
137
210
|
}
|
|
138
211
|
}
|
|
212
|
+
catch (err) {
|
|
213
|
+
if (isMounted.current) {
|
|
214
|
+
setLoading(false);
|
|
215
|
+
}
|
|
216
|
+
const msg = IModelApp.localization.getLocalizedString("mapLayers:Messages.MapLayerAttachError", { error: err, sourceName: mapLayerSettings.name });
|
|
217
|
+
IModelApp.notifications.outputMessage(new NotifyMessageDetails(OutputMessagePriority.Error, msg));
|
|
218
|
+
}
|
|
139
219
|
}
|
|
140
220
|
return;
|
|
141
221
|
}
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
setLayerNameToAdd(undefined);
|
|
146
|
-
}
|
|
222
|
+
attemptToAddLayer(); // eslint-disable-line @typescript-eslint/no-floating-promises
|
|
223
|
+
if (isMounted.current) {
|
|
224
|
+
setLayerNameToAdd(undefined);
|
|
147
225
|
}
|
|
148
|
-
}, [setLayerNameToAdd, layerNameToAdd, activeViewport, sources, backgroundLayers, isOverlay, overlayLayers,
|
|
149
|
-
|
|
226
|
+
}, [attachLayer, needsFeatureSelection, setLayerNameToAdd, layerNameToAdd, activeViewport, sources, backgroundLayers, isOverlay, overlayLayers,
|
|
227
|
+
onLayerAttached, handleModalUrlDialogOk, handleSelectFeaturesCancel, handleSelectFeaturesOk, mapTypesOptions,
|
|
228
|
+
handleModalUrlDialogCancel, onHandleOutsideClick, openFeatureSelectionDialog]);
|
|
229
|
+
const options = React.useMemo(() => sources, [sources]);
|
|
150
230
|
const filteredOptions = React.useMemo(() => {
|
|
151
231
|
if (undefined === sourceFilterString || 0 === sourceFilterString.length) {
|
|
152
232
|
return options;
|
|
@@ -156,7 +236,7 @@ function AttachLayerPanel({ isOverlay, onLayerAttached, onHandleOutsideClick })
|
|
|
156
236
|
}
|
|
157
237
|
}, [options, sourceFilterString]);
|
|
158
238
|
const handleAddNewMapSource = React.useCallback(() => {
|
|
159
|
-
UiFramework.dialogs.modal.open(React.createElement(MapUrlDialog, { activeViewport: activeViewport, isOverlay: isOverlay, onOkResult: () => handleModalUrlDialogOk(LayerAction.
|
|
239
|
+
UiFramework.dialogs.modal.open(React.createElement(MapUrlDialog, { activeViewport: activeViewport, isOverlay: isOverlay, onOkResult: (result) => handleModalUrlDialogOk(LayerAction.New, result), onCancelResult: handleModalUrlDialogCancel, mapTypesOptions: mapTypesOptions }));
|
|
160
240
|
if (onHandleOutsideClick) {
|
|
161
241
|
onHandleOutsideClick(false);
|
|
162
242
|
}
|
|
@@ -221,7 +301,7 @@ function AttachLayerPanel({ isOverlay, onLayerAttached, onHandleOutsideClick })
|
|
|
221
301
|
if (matchingSource === undefined) {
|
|
222
302
|
return;
|
|
223
303
|
}
|
|
224
|
-
UiFramework.dialogs.modal.open(React.createElement(MapUrlDialog, { activeViewport: activeViewport, isOverlay: isOverlay, mapLayerSourceToEdit: matchingSource, onOkResult: () => handleModalUrlDialogOk(LayerAction.
|
|
304
|
+
UiFramework.dialogs.modal.open(React.createElement(MapUrlDialog, { activeViewport: activeViewport, isOverlay: isOverlay, mapLayerSourceToEdit: matchingSource, onOkResult: (result) => handleModalUrlDialogOk(LayerAction.Edit, result), onCancelResult: handleModalUrlDialogCancel, mapTypesOptions: mapTypesOptions }));
|
|
225
305
|
if (onHandleOutsideClick) {
|
|
226
306
|
onHandleOutsideClick(false);
|
|
227
307
|
}
|
|
@@ -324,7 +404,7 @@ export function AttachLayerPopupButton(props) {
|
|
|
324
404
|
}
|
|
325
405
|
return (React.createElement(React.Fragment, null,
|
|
326
406
|
renderButton(),
|
|
327
|
-
React.createElement(UiCore.Popup, { isOpen: popupOpen, position: RelativePosition.BottomRight, onClose: handleClosePopup, onOutsideClick: onHandleOutsideClick, target: buttonRef.current, closeOnEnter: false, closeOnContextMenu: false },
|
|
407
|
+
React.createElement(UiCore.Popup, { isOpen: popupOpen, position: RelativePosition.BottomRight, onClose: handleClosePopup, onOutsideClick: onHandleOutsideClick, closeOnWheel: false, target: buttonRef.current, closeOnEnter: false, closeOnContextMenu: false },
|
|
328
408
|
React.createElement("div", { ref: panelRef, className: "map-sources-popup-panel" },
|
|
329
409
|
React.createElement(AttachLayerPanel, { isOverlay: props.isOverlay, onLayerAttached: handleLayerAttached, onHandleOutsideClick: setHandleOutsideClick })))));
|
|
330
410
|
}
|