@itwin/map-layers 3.0.0-extension.1 → 3.1.0-dev.6
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 +82 -1
- package/lib/cjs/MapLayerPreferences.d.ts +89 -0
- package/lib/cjs/MapLayerPreferences.d.ts.map +1 -0
- package/lib/cjs/MapLayerPreferences.js +312 -0
- package/lib/cjs/MapLayerPreferences.js.map +1 -0
- package/lib/cjs/mapLayers.d.ts +18 -13
- package/lib/cjs/mapLayers.d.ts.map +1 -1
- package/lib/cjs/mapLayers.js +25 -17
- package/lib/cjs/mapLayers.js.map +1 -1
- package/lib/cjs/public/locales/en/mapLayers.json +5 -2
- package/lib/cjs/ui/MapLayersUiItemsProvider.js +1 -1
- package/lib/cjs/ui/MapLayersUiItemsProvider.js.map +1 -1
- package/lib/cjs/ui/widget/AttachLayerPopupButton.d.ts.map +1 -1
- package/lib/cjs/ui/widget/AttachLayerPopupButton.js +5 -3
- 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 +5 -4
- package/lib/cjs/ui/widget/BasemapPanel.js.map +1 -1
- package/lib/cjs/ui/widget/MapLayerManager.d.ts +2 -2
- package/lib/cjs/ui/widget/MapLayerManager.d.ts.map +1 -1
- package/lib/cjs/ui/widget/MapLayerManager.js +24 -10
- package/lib/cjs/ui/widget/MapLayerManager.js.map +1 -1
- package/lib/cjs/ui/widget/MapLayerManager.scss +0 -7
- package/lib/cjs/ui/widget/MapManagerSettings.d.ts.map +1 -1
- package/lib/cjs/ui/widget/MapManagerSettings.js +51 -22
- package/lib/cjs/ui/widget/MapManagerSettings.js.map +1 -1
- package/lib/cjs/ui/widget/MapManagerSettings.scss +1 -1
- package/lib/cjs/ui/widget/MapUrlDialog.d.ts.map +1 -1
- package/lib/cjs/ui/widget/MapUrlDialog.js +231 -161
- package/lib/cjs/ui/widget/MapUrlDialog.js.map +1 -1
- package/lib/cjs/ui/widget/SubLayersTree.d.ts.map +1 -1
- package/lib/cjs/ui/widget/SubLayersTree.js +1 -1
- package/lib/cjs/ui/widget/SubLayersTree.js.map +1 -1
- package/lib/cjs/ui/widget/TransparencyPopupButton.js +2 -2
- package/lib/cjs/ui/widget/TransparencyPopupButton.js.map +1 -1
- package/lib/esm/MapLayerPreferences.d.ts +89 -0
- package/lib/esm/MapLayerPreferences.d.ts.map +1 -0
- package/lib/esm/MapLayerPreferences.js +308 -0
- package/lib/esm/MapLayerPreferences.js.map +1 -0
- package/lib/esm/mapLayers.d.ts +18 -13
- package/lib/esm/mapLayers.d.ts.map +1 -1
- package/lib/esm/mapLayers.js +26 -18
- package/lib/esm/mapLayers.js.map +1 -1
- package/lib/esm/public/locales/en/mapLayers.json +5 -2
- package/lib/esm/ui/MapLayersUiItemsProvider.js +1 -1
- package/lib/esm/ui/MapLayersUiItemsProvider.js.map +1 -1
- package/lib/esm/ui/widget/AttachLayerPopupButton.d.ts.map +1 -1
- package/lib/esm/ui/widget/AttachLayerPopupButton.js +6 -4
- 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 +6 -5
- package/lib/esm/ui/widget/BasemapPanel.js.map +1 -1
- package/lib/esm/ui/widget/MapLayerManager.d.ts +2 -2
- package/lib/esm/ui/widget/MapLayerManager.d.ts.map +1 -1
- package/lib/esm/ui/widget/MapLayerManager.js +21 -7
- package/lib/esm/ui/widget/MapLayerManager.js.map +1 -1
- package/lib/esm/ui/widget/MapLayerManager.scss +0 -7
- package/lib/esm/ui/widget/MapManagerSettings.d.ts.map +1 -1
- package/lib/esm/ui/widget/MapManagerSettings.js +53 -24
- package/lib/esm/ui/widget/MapManagerSettings.js.map +1 -1
- package/lib/esm/ui/widget/MapManagerSettings.scss +1 -1
- package/lib/esm/ui/widget/MapUrlDialog.d.ts.map +1 -1
- package/lib/esm/ui/widget/MapUrlDialog.js +233 -163
- package/lib/esm/ui/widget/MapUrlDialog.js.map +1 -1
- package/lib/esm/ui/widget/SubLayersTree.d.ts.map +1 -1
- package/lib/esm/ui/widget/SubLayersTree.js +1 -1
- package/lib/esm/ui/widget/SubLayersTree.js.map +1 -1
- package/lib/esm/ui/widget/TransparencyPopupButton.js +2 -2
- package/lib/esm/ui/widget/TransparencyPopupButton.js.map +1 -1
- package/lib/public/locales/en/mapLayers.json +5 -2
- package/package.json +33 -38
|
@@ -7,13 +7,15 @@
|
|
|
7
7
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
8
8
|
exports.MapUrlDialog = exports.MAP_TYPES = void 0;
|
|
9
9
|
const React = require("react");
|
|
10
|
-
const itwinui_react_1 = require("@itwin/itwinui-react");
|
|
11
10
|
const core_react_1 = require("@itwin/core-react");
|
|
12
11
|
const appui_react_1 = require("@itwin/appui-react");
|
|
12
|
+
const itwinui_react_1 = require("@itwin/itwinui-react");
|
|
13
13
|
const MapLayersUiItemsProvider_1 = require("../MapLayersUiItemsProvider");
|
|
14
14
|
const core_frontend_1 = require("@itwin/core-frontend");
|
|
15
15
|
require("./MapUrlDialog.scss");
|
|
16
16
|
const appui_abstract_1 = require("@itwin/appui-abstract");
|
|
17
|
+
const MapLayerPreferences_1 = require("../../MapLayerPreferences");
|
|
18
|
+
const mapLayers_1 = require("../../mapLayers");
|
|
17
19
|
exports.MAP_TYPES = {
|
|
18
20
|
wms: "WMS",
|
|
19
21
|
arcGis: "ArcGIS",
|
|
@@ -22,9 +24,8 @@ exports.MAP_TYPES = {
|
|
|
22
24
|
};
|
|
23
25
|
// eslint-disable-next-line @typescript-eslint/naming-convention
|
|
24
26
|
function MapUrlDialog(props) {
|
|
25
|
-
var _a, _b, _c, _d, _e
|
|
27
|
+
var _a, _b, _c, _d, _e;
|
|
26
28
|
const { isOverlay, onOkResult, mapTypesOptions } = props;
|
|
27
|
-
const supportWmsAuthentication = ((mapTypesOptions === null || mapTypesOptions === void 0 ? void 0 : mapTypesOptions.supportWmsAuthentication) ? true : false);
|
|
28
29
|
const getMapUrlFromProps = React.useCallback(() => {
|
|
29
30
|
var _a;
|
|
30
31
|
if (props.mapLayerSourceToEdit) {
|
|
@@ -65,10 +66,9 @@ function MapUrlDialog(props) {
|
|
|
65
66
|
const [modelSettingsLabel] = React.useState(MapLayersUiItemsProvider_1.MapLayersUiItemsProvider.localization.getLocalizedString("mapLayers:CustomAttach.StoreOnModelSettings"));
|
|
66
67
|
const [missingCredentialsLabel] = React.useState(MapLayersUiItemsProvider_1.MapLayersUiItemsProvider.localization.getLocalizedString("mapLayers:CustomAttach.MissingCredentials"));
|
|
67
68
|
const [invalidCredentialsLabel] = React.useState(MapLayersUiItemsProvider_1.MapLayersUiItemsProvider.localization.getLocalizedString("mapLayers:CustomAttach.InvalidCredentials"));
|
|
68
|
-
const [serverRequireCredentials, setServerRequireCredentials] = React.useState(
|
|
69
|
+
const [serverRequireCredentials, setServerRequireCredentials] = React.useState(false);
|
|
69
70
|
const [invalidCredentialsProvided, setInvalidCredentialsProvided] = React.useState(false);
|
|
70
71
|
const [layerAttachPending, setLayerAttachPending] = React.useState(false);
|
|
71
|
-
const [warningMessage, setWarningMessage] = React.useState(props.layerRequiringCredentials ? missingCredentialsLabel : undefined);
|
|
72
72
|
const [mapUrl, setMapUrl] = React.useState(getMapUrlFromProps());
|
|
73
73
|
const [mapName, setMapName] = React.useState(getMapNameFromProps());
|
|
74
74
|
const [userName, setUserName] = React.useState("");
|
|
@@ -78,8 +78,9 @@ function MapUrlDialog(props) {
|
|
|
78
78
|
const [passwordRequiredLabel] = React.useState(MapLayersUiItemsProvider_1.MapLayersUiItemsProvider.localization.getLocalizedString("mapLayers:AuthenticationInputs.PasswordRequired"));
|
|
79
79
|
const [userNameLabel] = React.useState(MapLayersUiItemsProvider_1.MapLayersUiItemsProvider.localization.getLocalizedString("mapLayers:AuthenticationInputs.Username"));
|
|
80
80
|
const [userNameRequiredLabel] = React.useState(MapLayersUiItemsProvider_1.MapLayersUiItemsProvider.localization.getLocalizedString("mapLayers:AuthenticationInputs.UsernameRequired"));
|
|
81
|
-
const [settingsStorage, setSettingsStorageRadio] = React.useState("
|
|
82
|
-
const [
|
|
81
|
+
const [settingsStorage, setSettingsStorageRadio] = React.useState("iTwin");
|
|
82
|
+
const [layerAuthMethod, setLayerAuthMethod] = React.useState(core_frontend_1.MapLayerAuthType.None);
|
|
83
|
+
const [mapType, setMapType] = React.useState((_a = getFormatFromProps()) !== null && _a !== void 0 ? _a : exports.MAP_TYPES.arcGis);
|
|
83
84
|
// 'isMounted' is used to prevent any async operation once the hook has been
|
|
84
85
|
// unloaded. Otherwise we get a 'Can't perform a React state update on an unmounted component.' warning in the console.
|
|
85
86
|
const isMounted = React.useRef(false);
|
|
@@ -99,15 +100,10 @@ function MapUrlDialog(props) {
|
|
|
99
100
|
types.push({ value: exports.MAP_TYPES.tileUrl, label: exports.MAP_TYPES.tileUrl });
|
|
100
101
|
return types;
|
|
101
102
|
});
|
|
102
|
-
const [isSettingsStorageAvailable] = React.useState(((
|
|
103
|
+
const [isSettingsStorageAvailable] = React.useState(mapLayers_1.MapLayersUI.iTwinConfig && ((_c = (_b = props === null || props === void 0 ? void 0 : props.activeViewport) === null || _b === void 0 ? void 0 : _b.iModel) === null || _c === void 0 ? void 0 : _c.iTwinId) && ((_e = (_d = props === null || props === void 0 ? void 0 : props.activeViewport) === null || _d === void 0 ? void 0 : _d.iModel) === null || _e === void 0 ? void 0 : _e.iModelId));
|
|
103
104
|
// Even though the settings storage is available,
|
|
104
105
|
// we don't always want to enable it in the UI.
|
|
105
106
|
const [settingsStorageDisabled] = React.useState(!isSettingsStorageAvailable || props.mapLayerSourceToEdit !== undefined || props.layerRequiringCredentials !== undefined);
|
|
106
|
-
const isAuthSupported = React.useCallback(() => {
|
|
107
|
-
return ((mapType === exports.MAP_TYPES.wms || mapType === exports.MAP_TYPES.wms) && supportWmsAuthentication)
|
|
108
|
-
|| mapType === exports.MAP_TYPES.arcGis;
|
|
109
|
-
}, [mapType, supportWmsAuthentication]);
|
|
110
|
-
// const [layerIdxToEdit] = React.useState((): number | undefined => {
|
|
111
107
|
const [layerRequiringCredentialsIdx] = React.useState(() => {
|
|
112
108
|
var _a;
|
|
113
109
|
if (props.layerRequiringCredentials === undefined || !props.layerRequiringCredentials.name || !props.layerRequiringCredentials.url) {
|
|
@@ -122,20 +118,15 @@ function MapUrlDialog(props) {
|
|
|
122
118
|
}
|
|
123
119
|
});
|
|
124
120
|
// Update warning message based on the dialog state and server response
|
|
125
|
-
React.useEffect(() => {
|
|
126
|
-
if (invalidCredentialsProvided) {
|
|
127
|
-
setWarningMessage(invalidCredentialsLabel);
|
|
128
|
-
}
|
|
129
|
-
else if (serverRequireCredentials && (!userName || !password)) {
|
|
130
|
-
setWarningMessage(missingCredentialsLabel);
|
|
131
|
-
}
|
|
132
|
-
else {
|
|
133
|
-
setWarningMessage(undefined);
|
|
134
|
-
}
|
|
135
|
-
}, [invalidCredentialsProvided, invalidCredentialsLabel, missingCredentialsLabel, serverRequireCredentials, userName, password, setWarningMessage]);
|
|
136
121
|
const handleMapTypeSelection = React.useCallback((newValue) => {
|
|
137
122
|
setMapType(newValue);
|
|
138
|
-
|
|
123
|
+
// Reset few states
|
|
124
|
+
if (invalidCredentialsProvided)
|
|
125
|
+
setInvalidCredentialsProvided(false);
|
|
126
|
+
if (layerAuthMethod !== core_frontend_1.MapLayerAuthType.None) {
|
|
127
|
+
setLayerAuthMethod(core_frontend_1.MapLayerAuthType.None);
|
|
128
|
+
}
|
|
129
|
+
}, [invalidCredentialsProvided, layerAuthMethod]);
|
|
139
130
|
const handleCancel = React.useCallback(() => {
|
|
140
131
|
if (props.onCancelResult) {
|
|
141
132
|
props.onCancelResult();
|
|
@@ -153,86 +144,109 @@ function MapUrlDialog(props) {
|
|
|
153
144
|
if (invalidCredentialsProvided)
|
|
154
145
|
setInvalidCredentialsProvided(false);
|
|
155
146
|
}, [setPassword, invalidCredentialsProvided, setInvalidCredentialsProvided]);
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
147
|
+
// return true if authorization is needed
|
|
148
|
+
const updateAuthState = React.useCallback((sourceValidation) => {
|
|
149
|
+
var _a, _b;
|
|
150
|
+
const sourceRequireAuth = (sourceValidation.status === core_frontend_1.MapLayerSourceStatus.RequireAuth);
|
|
151
|
+
const invalidCredentials = (sourceValidation.status === core_frontend_1.MapLayerSourceStatus.InvalidCredentials);
|
|
152
|
+
if (sourceRequireAuth && ((_a = sourceValidation.authInfo) === null || _a === void 0 ? void 0 : _a.authMethod) !== undefined) {
|
|
153
|
+
setLayerAuthMethod((_b = sourceValidation.authInfo) === null || _b === void 0 ? void 0 : _b.authMethod);
|
|
154
|
+
}
|
|
155
|
+
if (invalidCredentials) {
|
|
156
|
+
setInvalidCredentialsProvided(true);
|
|
157
|
+
}
|
|
158
|
+
else if (invalidCredentialsProvided) {
|
|
159
|
+
setInvalidCredentialsProvided(false); // flag reset
|
|
160
|
+
}
|
|
161
|
+
return sourceRequireAuth || invalidCredentials;
|
|
162
|
+
}, [invalidCredentialsProvided]);
|
|
163
|
+
const updateAttachedLayer = React.useCallback(async (source, validation) => {
|
|
164
|
+
const vp = props === null || props === void 0 ? void 0 : props.activeViewport;
|
|
165
|
+
if (vp === undefined || source === undefined || layerRequiringCredentialsIdx === undefined) {
|
|
166
|
+
const error = MapLayersUiItemsProvider_1.MapLayersUiItemsProvider.localization.getLocalizedString("mapLayers:Messages.MapLayerAttachMissingViewOrSource");
|
|
167
|
+
const msg = MapLayersUiItemsProvider_1.MapLayersUiItemsProvider.localization.getLocalizedString("mapLayers:Messages.MapLayerAttachError", { error, sourceUrl: source.url });
|
|
168
|
+
core_frontend_1.IModelApp.notifications.outputMessage(new core_frontend_1.NotifyMessageDetails(core_frontend_1.OutputMessagePriority.Error, msg));
|
|
169
|
+
return true;
|
|
170
|
+
}
|
|
171
|
+
// Layer is already attached,
|
|
172
|
+
vp.displayStyle.changeMapLayerProps({
|
|
173
|
+
subLayers: validation.subLayers,
|
|
174
|
+
}, layerRequiringCredentialsIdx, isOverlay);
|
|
175
|
+
vp.displayStyle.changeMapLayerCredentials(layerRequiringCredentialsIdx, isOverlay, source.userName, source.password);
|
|
176
|
+
// Reset the provider's status
|
|
177
|
+
const provider = vp.getMapLayerImageryProvider(layerRequiringCredentialsIdx, isOverlay);
|
|
178
|
+
if (provider && provider.status !== core_frontend_1.MapLayerImageryProviderStatus.Valid) {
|
|
179
|
+
provider.status = core_frontend_1.MapLayerImageryProviderStatus.Valid;
|
|
180
|
+
}
|
|
181
|
+
vp.invalidateRenderPlan();
|
|
182
|
+
// This handler will close the layer source handler, and therefore the MapUrl dialog.
|
|
183
|
+
// don't call it if the dialog needs to remains open.
|
|
184
|
+
onOkResult();
|
|
185
|
+
return true;
|
|
186
|
+
}, [isOverlay, layerRequiringCredentialsIdx, onOkResult, props.activeViewport]);
|
|
187
|
+
// Returns true if no further input is needed from end-user.
|
|
188
|
+
const doAttach = React.useCallback(async (source, validation) => {
|
|
189
|
+
const vp = props === null || props === void 0 ? void 0 : props.activeViewport;
|
|
190
|
+
if (vp === undefined || source === undefined) {
|
|
191
|
+
const error = MapLayersUiItemsProvider_1.MapLayersUiItemsProvider.localization.getLocalizedString("mapLayers:Messages.MapLayerAttachMissingViewOrSource");
|
|
192
|
+
const msg = MapLayersUiItemsProvider_1.MapLayersUiItemsProvider.localization.getLocalizedString("mapLayers:Messages.MapLayerAttachError", { error, sourceUrl: source.url });
|
|
193
|
+
core_frontend_1.IModelApp.notifications.outputMessage(new core_frontend_1.NotifyMessageDetails(core_frontend_1.OutputMessagePriority.Error, msg));
|
|
194
|
+
return true;
|
|
195
|
+
}
|
|
196
|
+
// Update service settings if storage is available and we are not prompting user for credentials
|
|
197
|
+
if (!settingsStorageDisabled && !props.layerRequiringCredentials) {
|
|
164
198
|
const storeOnIModel = "Model" === settingsStorage;
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
}
|
|
196
|
-
}
|
|
197
|
-
else {
|
|
198
|
-
// Update service settings if storage is available and we are not prompting user for credentials
|
|
199
|
-
if (!settingsStorageDisabled && !props.layerRequiringCredentials) {
|
|
200
|
-
if (!(await core_frontend_1.MapLayerSettingsService.storeSourceInSettingsService(source, storeOnIModel, vp.iModel.iTwinId, vp.iModel.iModelId)))
|
|
201
|
-
return;
|
|
202
|
-
}
|
|
203
|
-
const layerSettings = source.toLayerSettings(validation.subLayers);
|
|
204
|
-
if (layerSettings) {
|
|
205
|
-
vp.displayStyle.attachMapLayerSettings(layerSettings, isOverlay, undefined);
|
|
206
|
-
const msg = core_frontend_1.IModelApp.localization.getLocalizedString("mapLayers:Messages.MapLayerAttached", { sourceName: source.name, sourceUrl: source.url });
|
|
207
|
-
core_frontend_1.IModelApp.notifications.outputMessage(new core_frontend_1.NotifyMessageDetails(core_frontend_1.OutputMessagePriority.Info, msg));
|
|
208
|
-
}
|
|
209
|
-
else {
|
|
210
|
-
const msgError = MapLayersUiItemsProvider_1.MapLayersUiItemsProvider.localization.getLocalizedString("mapLayers:Messages.MapLayerLayerSettingsConversionError");
|
|
211
|
-
const msg = MapLayersUiItemsProvider_1.MapLayersUiItemsProvider.localization.getLocalizedString("mapLayers:CustomAttach.MapLayerAttachError", { error: msgError, sourceUrl: source.url });
|
|
212
|
-
core_frontend_1.IModelApp.notifications.outputMessage(new core_frontend_1.NotifyMessageDetails(core_frontend_1.OutputMessagePriority.Error, msg));
|
|
213
|
-
}
|
|
214
|
-
}
|
|
215
|
-
vp.invalidateRenderPlan();
|
|
216
|
-
}
|
|
217
|
-
if (closeDialog) {
|
|
218
|
-
// This handler will close the layer source handler, and therefore the MapUrl dialog.
|
|
219
|
-
// don't call it if the dialog needs to remains open.
|
|
220
|
-
onOkResult();
|
|
221
|
-
}
|
|
199
|
+
if (!(await MapLayerPreferences_1.MapLayerPreferences.storeSource(source, storeOnIModel, vp.iModel.iTwinId, vp.iModel.iModelId))) {
|
|
200
|
+
const msgError = MapLayersUiItemsProvider_1.MapLayersUiItemsProvider.localization.getLocalizedString("mapLayers:Messages.MapLayerPreferencesStoreFailed");
|
|
201
|
+
core_frontend_1.IModelApp.notifications.outputMessage(new core_frontend_1.NotifyMessageDetails(core_frontend_1.OutputMessagePriority.Error, msgError));
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
const layerSettings = source.toLayerSettings(validation.subLayers);
|
|
205
|
+
if (layerSettings) {
|
|
206
|
+
vp.displayStyle.attachMapLayerSettings(layerSettings, isOverlay, undefined);
|
|
207
|
+
const msg = core_frontend_1.IModelApp.localization.getLocalizedString("mapLayers:Messages.MapLayerAttached", { sourceName: source.name, sourceUrl: source.url });
|
|
208
|
+
core_frontend_1.IModelApp.notifications.outputMessage(new core_frontend_1.NotifyMessageDetails(core_frontend_1.OutputMessagePriority.Info, msg));
|
|
209
|
+
}
|
|
210
|
+
else {
|
|
211
|
+
const msgError = MapLayersUiItemsProvider_1.MapLayersUiItemsProvider.localization.getLocalizedString("mapLayers:Messages.MapLayerLayerSettingsConversionError");
|
|
212
|
+
const msg = MapLayersUiItemsProvider_1.MapLayersUiItemsProvider.localization.getLocalizedString("mapLayers:CustomAttach.MapLayerAttachError", { error: msgError, sourceUrl: source.url });
|
|
213
|
+
core_frontend_1.IModelApp.notifications.outputMessage(new core_frontend_1.NotifyMessageDetails(core_frontend_1.OutputMessagePriority.Error, msg));
|
|
214
|
+
}
|
|
215
|
+
vp.invalidateRenderPlan();
|
|
216
|
+
// This handler will close the layer source handler, and therefore the MapUrl dialog.
|
|
217
|
+
// don't call it if the dialog needs to remains open.
|
|
218
|
+
onOkResult();
|
|
219
|
+
return true;
|
|
220
|
+
}, [isOverlay, onOkResult, props === null || props === void 0 ? void 0 : props.activeViewport, props.layerRequiringCredentials, settingsStorage, settingsStorageDisabled]);
|
|
221
|
+
// Validate the layer source and attempt to attach (or update) the layer.
|
|
222
|
+
// Returns true if no further input is needed from end-user (i.e. close the dialog)
|
|
223
|
+
const attemptAttachSource = React.useCallback(async (source) => {
|
|
224
|
+
try {
|
|
225
|
+
const validation = await source.validateSource(true);
|
|
226
|
+
if (validation.status === core_frontend_1.MapLayerSourceStatus.Valid) {
|
|
227
|
+
if (layerRequiringCredentialsIdx === undefined) {
|
|
228
|
+
return await doAttach(source, validation);
|
|
222
229
|
}
|
|
223
230
|
else {
|
|
224
|
-
|
|
225
|
-
core_frontend_1.IModelApp.notifications.outputMessage(new core_frontend_1.NotifyMessageDetails(core_frontend_1.OutputMessagePriority.Error, `${msg} ${source.url}`));
|
|
226
|
-
resolve(true);
|
|
231
|
+
return await updateAttachedLayer(source, validation);
|
|
227
232
|
}
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
233
|
+
}
|
|
234
|
+
else if (updateAuthState(validation)) {
|
|
235
|
+
return false;
|
|
236
|
+
}
|
|
237
|
+
else {
|
|
238
|
+
const msg = MapLayersUiItemsProvider_1.MapLayersUiItemsProvider.localization.getLocalizedString("mapLayers:CustomAttach.ValidationError");
|
|
239
|
+
core_frontend_1.IModelApp.notifications.outputMessage(new core_frontend_1.NotifyMessageDetails(core_frontend_1.OutputMessagePriority.Error, `${msg} ${source.url}`));
|
|
240
|
+
return true;
|
|
241
|
+
}
|
|
242
|
+
return false;
|
|
243
|
+
}
|
|
244
|
+
catch (error) {
|
|
245
|
+
const msg = MapLayersUiItemsProvider_1.MapLayersUiItemsProvider.localization.getLocalizedString("mapLayers:Messages.MapLayerAttachError", { error, sourceUrl: source.url });
|
|
246
|
+
core_frontend_1.IModelApp.notifications.outputMessage(new core_frontend_1.NotifyMessageDetails(core_frontend_1.OutputMessagePriority.Error, msg));
|
|
247
|
+
return true;
|
|
248
|
+
}
|
|
249
|
+
}, [updateAuthState, doAttach, layerRequiringCredentialsIdx, updateAttachedLayer]);
|
|
236
250
|
const onNameChange = React.useCallback((event) => {
|
|
237
251
|
setMapName(event.target.value);
|
|
238
252
|
}, [setMapName]);
|
|
@@ -242,70 +256,101 @@ function MapUrlDialog(props) {
|
|
|
242
256
|
const onUrlChange = React.useCallback((event) => {
|
|
243
257
|
setMapUrl(event.target.value);
|
|
244
258
|
}, [setMapUrl]);
|
|
245
|
-
const
|
|
259
|
+
const createSource = React.useCallback(() => {
|
|
246
260
|
let source;
|
|
247
261
|
if (mapUrl && mapName) {
|
|
248
262
|
source = core_frontend_1.MapLayerSource.fromJSON({
|
|
249
263
|
url: mapUrl,
|
|
250
264
|
name: mapName,
|
|
251
265
|
formatId: mapType,
|
|
252
|
-
userName,
|
|
253
|
-
password
|
|
266
|
+
userName: userName || undefined,
|
|
267
|
+
password: password || undefined
|
|
254
268
|
});
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
269
|
+
}
|
|
270
|
+
return source;
|
|
271
|
+
}, [mapName, mapType, mapUrl, password, userName]);
|
|
272
|
+
const handleOk = React.useCallback(() => {
|
|
273
|
+
const source = createSource();
|
|
274
|
+
if (source === undefined || props.mapLayerSourceToEdit) {
|
|
275
|
+
appui_react_1.ModalDialogManager.closeDialog();
|
|
276
|
+
if (source === undefined) {
|
|
277
|
+
// Close the dialog and inform end user something went wrong.
|
|
278
|
+
const msgError = MapLayersUiItemsProvider_1.MapLayersUiItemsProvider.localization.getLocalizedString("mapLayers:Messages.MapLayerLayerSourceCreationFailed");
|
|
279
|
+
const msg = MapLayersUiItemsProvider_1.MapLayersUiItemsProvider.localization.getLocalizedString("mapLayers:Messages.MapLayerAttachError", { error: msgError, sourceUrl: mapUrl });
|
|
280
|
+
core_frontend_1.IModelApp.notifications.outputMessage(new core_frontend_1.NotifyMessageDetails(core_frontend_1.OutputMessagePriority.Error, msg));
|
|
281
|
+
return;
|
|
282
|
+
}
|
|
283
|
+
// Simply change the source definition in the setting service
|
|
284
|
+
if (props.mapLayerSourceToEdit !== undefined) {
|
|
285
|
+
const vp = props.activeViewport;
|
|
286
|
+
void (async () => {
|
|
287
|
+
var _a;
|
|
288
|
+
if (isSettingsStorageAvailable && vp) {
|
|
289
|
+
try {
|
|
290
|
+
await MapLayerPreferences_1.MapLayerPreferences.replaceSource(props.mapLayerSourceToEdit, source, vp.iModel.iTwinId, vp.iModel.iModelId);
|
|
291
|
+
}
|
|
292
|
+
catch (err) {
|
|
293
|
+
const errorMessage = core_frontend_1.IModelApp.localization.getLocalizedString("mapLayers:Messages.MapLayerEditError", { layerName: (_a = props.mapLayerSourceToEdit) === null || _a === void 0 ? void 0 : _a.name });
|
|
294
|
+
core_frontend_1.IModelApp.notifications.outputMessage(new core_frontend_1.NotifyMessageDetails(core_frontend_1.OutputMessagePriority.Error, errorMessage));
|
|
295
|
+
return;
|
|
275
296
|
}
|
|
276
|
-
}
|
|
277
|
-
|
|
297
|
+
}
|
|
298
|
+
})();
|
|
299
|
+
return;
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
setLayerAttachPending(true);
|
|
303
|
+
// Attach source asynchronously.
|
|
304
|
+
void (async () => {
|
|
305
|
+
try {
|
|
306
|
+
const closeDialog = await attemptAttachSource(source);
|
|
307
|
+
if (isMounted.current) {
|
|
308
|
+
setLayerAttachPending(false);
|
|
309
|
+
}
|
|
310
|
+
// In theory the modal dialog should always get closed by the parent
|
|
311
|
+
// AttachLayerPanel's 'onOkResult' handler. We close it here just in case.
|
|
312
|
+
if (closeDialog) {
|
|
313
|
+
appui_react_1.ModalDialogManager.closeDialog();
|
|
278
314
|
}
|
|
279
315
|
}
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
316
|
+
catch (_error) {
|
|
317
|
+
appui_react_1.ModalDialogManager.closeDialog();
|
|
318
|
+
}
|
|
319
|
+
})();
|
|
320
|
+
}, [createSource, props.mapLayerSourceToEdit, props.activeViewport, mapUrl, isSettingsStorageAvailable, attemptAttachSource]);
|
|
321
|
+
// The first time the dialog is loaded and we already know the layer requires auth. (i.e ImageryProvider already made an attempt)
|
|
322
|
+
// makes a request to discover the authentification types and adjust UI accordingly (i.e. username/password fields, Oauth popup)
|
|
323
|
+
// Without this effect, user would have to manually click the 'OK' button in order to trigger the layer connection.
|
|
324
|
+
React.useEffect(() => {
|
|
325
|
+
// Attach source asynchronously.
|
|
326
|
+
void (async () => {
|
|
327
|
+
var _a, _b;
|
|
328
|
+
if (((_a = props.layerRequiringCredentials) === null || _a === void 0 ? void 0 : _a.url) !== undefined && ((_b = props.layerRequiringCredentials) === null || _b === void 0 ? void 0 : _b.name) !== undefined) {
|
|
285
329
|
try {
|
|
286
|
-
const
|
|
287
|
-
if (
|
|
288
|
-
setLayerAttachPending(
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
330
|
+
const source = core_frontend_1.MapLayerSource.fromJSON({ url: props.layerRequiringCredentials.url, name: props.layerRequiringCredentials.name, formatId: props.layerRequiringCredentials.formatId });
|
|
331
|
+
if (source !== undefined) {
|
|
332
|
+
setLayerAttachPending(true);
|
|
333
|
+
const validation = await source.validateSource(true);
|
|
334
|
+
if (isMounted.current) {
|
|
335
|
+
setLayerAttachPending(false);
|
|
336
|
+
}
|
|
337
|
+
updateAuthState(validation);
|
|
294
338
|
}
|
|
295
339
|
}
|
|
296
|
-
catch (_error) {
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
}, [
|
|
340
|
+
catch (_error) { }
|
|
341
|
+
}
|
|
342
|
+
})();
|
|
343
|
+
// Only run this effect when the dialog is initialized, otherwise it will it creates undesirable side-effects when 'OK' button is clicked.
|
|
344
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
345
|
+
}, []);
|
|
302
346
|
const dialogContainer = React.useRef(null);
|
|
303
347
|
const readyToSave = React.useCallback(() => {
|
|
304
348
|
const credentialsSet = !!userName && !!password;
|
|
305
349
|
return (!!mapUrl && !!mapName)
|
|
306
|
-
&&
|
|
350
|
+
&& !layerAttachPending
|
|
351
|
+
&& (!serverRequireCredentials || credentialsSet)
|
|
307
352
|
&& !invalidCredentialsProvided;
|
|
308
|
-
}, [mapUrl, mapName,
|
|
353
|
+
}, [userName, password, mapUrl, mapName, serverRequireCredentials, layerAttachPending, invalidCredentialsProvided]);
|
|
309
354
|
const buttonCluster = React.useMemo(() => [
|
|
310
355
|
{ type: appui_abstract_1.DialogButtonType.OK, onClick: handleOk, disabled: !readyToSave() },
|
|
311
356
|
{ type: appui_abstract_1.DialogButtonType.Cancel, onClick: handleCancel },
|
|
@@ -316,33 +361,58 @@ function MapUrlDialog(props) {
|
|
|
316
361
|
handleOk();
|
|
317
362
|
}
|
|
318
363
|
}, [handleOk, readyToSave]);
|
|
364
|
+
//
|
|
365
|
+
// Monitors authentication method changes
|
|
366
|
+
React.useEffect(() => {
|
|
367
|
+
setServerRequireCredentials(layerAuthMethod === core_frontend_1.MapLayerAuthType.Basic || layerAuthMethod === core_frontend_1.MapLayerAuthType.EsriToken);
|
|
368
|
+
}, [layerAuthMethod]);
|
|
369
|
+
// Utility function to get warning message section
|
|
370
|
+
function renderWarningMessage() {
|
|
371
|
+
let node;
|
|
372
|
+
let warningMessage;
|
|
373
|
+
// Get the proper warning message
|
|
374
|
+
if (invalidCredentialsProvided) {
|
|
375
|
+
warningMessage = invalidCredentialsLabel;
|
|
376
|
+
}
|
|
377
|
+
else if (serverRequireCredentials && (!userName || !password)) {
|
|
378
|
+
warningMessage = missingCredentialsLabel;
|
|
379
|
+
}
|
|
380
|
+
// Sometimes we want to add an extra node, such as a button
|
|
381
|
+
let extraNode;
|
|
382
|
+
if (warningMessage !== undefined) {
|
|
383
|
+
return (React.createElement("div", { className: "map-layer-source-warnMessage" },
|
|
384
|
+
React.createElement(core_react_1.Icon, { className: "map-layer-source-warnMessage-icon", iconSpec: "icon-status-warning" }),
|
|
385
|
+
React.createElement("span", { className: "map-layer-source-warnMessage-label" }, warningMessage),
|
|
386
|
+
extraNode));
|
|
387
|
+
}
|
|
388
|
+
else {
|
|
389
|
+
return (React.createElement("span", { className: "map-layer-source-placeholder" }, "\u00A0"));
|
|
390
|
+
}
|
|
391
|
+
return node;
|
|
392
|
+
}
|
|
319
393
|
return (React.createElement("div", { ref: dialogContainer },
|
|
320
394
|
React.createElement(core_react_1.Dialog, { className: "map-layer-url-dialog", title: dialogTitle, opened: true, resizable: true, movable: true, modal: true, buttonCluster: buttonCluster, onClose: handleCancel, onEscape: handleCancel, minHeight: 120, maxWidth: 600, titleStyle: { paddingLeft: "10px" }, footerStyle: { paddingBottom: "10px", paddingRight: "10px" }, trapFocus: false },
|
|
321
395
|
React.createElement("div", { className: "map-layer-url-dialog-content" },
|
|
322
396
|
React.createElement("div", { className: "map-layer-source-url" },
|
|
323
397
|
React.createElement("span", { className: "map-layer-source-label" }, typeLabel),
|
|
324
|
-
React.createElement(itwinui_react_1.Select, { className: "map-layer-source-select", options: mapTypes, value: mapType, disabled: props.layerRequiringCredentials !== undefined || props.mapLayerSourceToEdit !== undefined, onChange: handleMapTypeSelection }),
|
|
398
|
+
React.createElement(itwinui_react_1.Select, { className: "map-layer-source-select", options: mapTypes, value: mapType, disabled: props.layerRequiringCredentials !== undefined || props.mapLayerSourceToEdit !== undefined || layerAttachPending, onChange: handleMapTypeSelection, size: "small" }),
|
|
325
399
|
React.createElement("span", { className: "map-layer-source-label" }, nameLabel),
|
|
326
|
-
React.createElement(itwinui_react_1.Input, { className: "map-layer-source-input", placeholder: nameInputPlaceHolder, onChange: onNameChange, value: mapName, disabled: props.layerRequiringCredentials !== undefined }),
|
|
400
|
+
React.createElement(itwinui_react_1.Input, { className: "map-layer-source-input", placeholder: nameInputPlaceHolder, onChange: onNameChange, value: mapName, disabled: props.layerRequiringCredentials !== undefined || layerAttachPending }),
|
|
327
401
|
React.createElement("span", { className: "map-layer-source-label" }, urlLabel),
|
|
328
|
-
React.createElement(itwinui_react_1.Input, { className: "map-layer-source-input", placeholder: urlInputPlaceHolder, onKeyPress: handleOnKeyDown, onChange: onUrlChange, disabled: props.mapLayerSourceToEdit !== undefined, value: mapUrl }),
|
|
329
|
-
|
|
402
|
+
React.createElement(itwinui_react_1.Input, { className: "map-layer-source-input", placeholder: urlInputPlaceHolder, onKeyPress: handleOnKeyDown, onChange: onUrlChange, disabled: props.mapLayerSourceToEdit !== undefined || layerAttachPending, value: mapUrl }),
|
|
403
|
+
serverRequireCredentials
|
|
404
|
+
&& (layerAuthMethod === core_frontend_1.MapLayerAuthType.Basic || layerAuthMethod === core_frontend_1.MapLayerAuthType.EsriToken)
|
|
405
|
+
&& props.mapLayerSourceToEdit === undefined &&
|
|
330
406
|
React.createElement(React.Fragment, null,
|
|
331
407
|
React.createElement("span", { className: "map-layer-source-label" }, userNameLabel),
|
|
332
|
-
React.createElement(itwinui_react_1.LabeledInput, { className: "map-layer-source-input", displayStyle: "inline", placeholder: serverRequireCredentials ? userNameRequiredLabel : userNameLabel, status: !userName && serverRequireCredentials ?
|
|
408
|
+
React.createElement(itwinui_react_1.LabeledInput, { className: "map-layer-source-input", displayStyle: "inline", placeholder: serverRequireCredentials ? userNameRequiredLabel : userNameLabel, status: !userName && serverRequireCredentials ? "warning" : undefined, disabled: layerAttachPending, onChange: onUsernameChange, size: "small" }),
|
|
333
409
|
React.createElement("span", { className: "map-layer-source-label" }, passwordLabel),
|
|
334
|
-
React.createElement(itwinui_react_1.LabeledInput, { className: "map-layer-source-input", displayStyle: "inline", type: "password", placeholder: serverRequireCredentials ? passwordRequiredLabel : passwordLabel, status: !password && serverRequireCredentials ?
|
|
410
|
+
React.createElement(itwinui_react_1.LabeledInput, { className: "map-layer-source-input", displayStyle: "inline", type: "password", placeholder: serverRequireCredentials ? passwordRequiredLabel : passwordLabel, status: !password && serverRequireCredentials ? "warning" : undefined, disabled: layerAttachPending, onChange: onPasswordChange, onKeyPress: handleOnKeyDown, size: "small" })),
|
|
335
411
|
isSettingsStorageAvailable && React.createElement("div", { title: settingsStorageDisabled ? noSaveSettingsWarning : "" },
|
|
336
412
|
React.createElement(itwinui_react_1.Radio, { disabled: settingsStorageDisabled, name: "settingsStorage", value: "iTwin", label: iTwinSettingsLabel, checked: settingsStorage === "iTwin", onChange: onRadioChange }),
|
|
337
413
|
React.createElement(itwinui_react_1.Radio, { disabled: settingsStorageDisabled, name: "settingsStorage", value: "Model", label: modelSettingsLabel, checked: settingsStorage === "Model", onChange: onRadioChange })))),
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
React.createElement(core_react_1.Icon, { className: "map-layer-source-warnMessage-icon", iconSpec: "icon-status-warning" }),
|
|
341
|
-
React.createElement("span", { className: "map-layer-source-warnMessage-label" }, warningMessage))
|
|
342
|
-
:
|
|
343
|
-
// Place holder to avoid dialog resize
|
|
344
|
-
React.createElement("span", { className: "map-layer-source-placeholder" }, "\u00A0")),
|
|
345
|
-
layerAttachPending &&
|
|
414
|
+
renderWarningMessage(),
|
|
415
|
+
(layerAttachPending) &&
|
|
346
416
|
React.createElement("div", { className: "map-layer-source-progressBar" },
|
|
347
417
|
React.createElement(itwinui_react_1.ProgressLinear, { indeterminate: true })))));
|
|
348
418
|
}
|