@itwin/map-layers 3.0.0-dev.180 → 3.0.0-dev.184
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/mapLayers.d.ts +2 -1
- package/lib/cjs/mapLayers.d.ts.map +1 -1
- package/lib/cjs/mapLayers.js +10 -5
- package/lib/cjs/mapLayers.js.map +1 -1
- package/lib/cjs/ui/widget/MapUrlDialog.d.ts.map +1 -1
- package/lib/cjs/ui/widget/MapUrlDialog.js +228 -165
- package/lib/cjs/ui/widget/MapUrlDialog.js.map +1 -1
- package/lib/esm/mapLayers.d.ts +2 -1
- package/lib/esm/mapLayers.d.ts.map +1 -1
- package/lib/esm/mapLayers.js +11 -6
- package/lib/esm/mapLayers.js.map +1 -1
- package/lib/esm/ui/widget/MapUrlDialog.d.ts.map +1 -1
- package/lib/esm/ui/widget/MapUrlDialog.js +230 -167
- package/lib/esm/ui/widget/MapUrlDialog.js.map +1 -1
- package/package.json +27 -29
|
@@ -7,9 +7,9 @@
|
|
|
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");
|
|
@@ -24,9 +24,8 @@ exports.MAP_TYPES = {
|
|
|
24
24
|
};
|
|
25
25
|
// eslint-disable-next-line @typescript-eslint/naming-convention
|
|
26
26
|
function MapUrlDialog(props) {
|
|
27
|
-
var _a, _b, _c, _d, _e
|
|
27
|
+
var _a, _b, _c, _d, _e;
|
|
28
28
|
const { isOverlay, onOkResult, mapTypesOptions } = props;
|
|
29
|
-
const supportWmsAuthentication = ((mapTypesOptions === null || mapTypesOptions === void 0 ? void 0 : mapTypesOptions.supportWmsAuthentication) ? true : false);
|
|
30
29
|
const getMapUrlFromProps = React.useCallback(() => {
|
|
31
30
|
var _a;
|
|
32
31
|
if (props.mapLayerSourceToEdit) {
|
|
@@ -67,10 +66,9 @@ function MapUrlDialog(props) {
|
|
|
67
66
|
const [modelSettingsLabel] = React.useState(MapLayersUiItemsProvider_1.MapLayersUiItemsProvider.localization.getLocalizedString("mapLayers:CustomAttach.StoreOnModelSettings"));
|
|
68
67
|
const [missingCredentialsLabel] = React.useState(MapLayersUiItemsProvider_1.MapLayersUiItemsProvider.localization.getLocalizedString("mapLayers:CustomAttach.MissingCredentials"));
|
|
69
68
|
const [invalidCredentialsLabel] = React.useState(MapLayersUiItemsProvider_1.MapLayersUiItemsProvider.localization.getLocalizedString("mapLayers:CustomAttach.InvalidCredentials"));
|
|
70
|
-
const [serverRequireCredentials, setServerRequireCredentials] = React.useState(
|
|
69
|
+
const [serverRequireCredentials, setServerRequireCredentials] = React.useState(false);
|
|
71
70
|
const [invalidCredentialsProvided, setInvalidCredentialsProvided] = React.useState(false);
|
|
72
71
|
const [layerAttachPending, setLayerAttachPending] = React.useState(false);
|
|
73
|
-
const [warningMessage, setWarningMessage] = React.useState(props.layerRequiringCredentials ? missingCredentialsLabel : undefined);
|
|
74
72
|
const [mapUrl, setMapUrl] = React.useState(getMapUrlFromProps());
|
|
75
73
|
const [mapName, setMapName] = React.useState(getMapNameFromProps());
|
|
76
74
|
const [userName, setUserName] = React.useState("");
|
|
@@ -81,7 +79,8 @@ function MapUrlDialog(props) {
|
|
|
81
79
|
const [userNameLabel] = React.useState(MapLayersUiItemsProvider_1.MapLayersUiItemsProvider.localization.getLocalizedString("mapLayers:AuthenticationInputs.Username"));
|
|
82
80
|
const [userNameRequiredLabel] = React.useState(MapLayersUiItemsProvider_1.MapLayersUiItemsProvider.localization.getLocalizedString("mapLayers:AuthenticationInputs.UsernameRequired"));
|
|
83
81
|
const [settingsStorage, setSettingsStorageRadio] = React.useState("iTwin");
|
|
84
|
-
const [
|
|
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);
|
|
85
84
|
// 'isMounted' is used to prevent any async operation once the hook has been
|
|
86
85
|
// unloaded. Otherwise we get a 'Can't perform a React state update on an unmounted component.' warning in the console.
|
|
87
86
|
const isMounted = React.useRef(false);
|
|
@@ -101,15 +100,10 @@ function MapUrlDialog(props) {
|
|
|
101
100
|
types.push({ value: exports.MAP_TYPES.tileUrl, label: exports.MAP_TYPES.tileUrl });
|
|
102
101
|
return types;
|
|
103
102
|
});
|
|
104
|
-
const [isSettingsStorageAvailable] = React.useState(mapLayers_1.MapLayersUI.iTwinConfig && ((
|
|
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));
|
|
105
104
|
// Even though the settings storage is available,
|
|
106
105
|
// we don't always want to enable it in the UI.
|
|
107
106
|
const [settingsStorageDisabled] = React.useState(!isSettingsStorageAvailable || props.mapLayerSourceToEdit !== undefined || props.layerRequiringCredentials !== undefined);
|
|
108
|
-
const isAuthSupported = React.useCallback(() => {
|
|
109
|
-
return ((mapType === exports.MAP_TYPES.wms || mapType === exports.MAP_TYPES.wms) && supportWmsAuthentication)
|
|
110
|
-
|| mapType === exports.MAP_TYPES.arcGis;
|
|
111
|
-
}, [mapType, supportWmsAuthentication]);
|
|
112
|
-
// const [layerIdxToEdit] = React.useState((): number | undefined => {
|
|
113
107
|
const [layerRequiringCredentialsIdx] = React.useState(() => {
|
|
114
108
|
var _a;
|
|
115
109
|
if (props.layerRequiringCredentials === undefined || !props.layerRequiringCredentials.name || !props.layerRequiringCredentials.url) {
|
|
@@ -124,20 +118,15 @@ function MapUrlDialog(props) {
|
|
|
124
118
|
}
|
|
125
119
|
});
|
|
126
120
|
// Update warning message based on the dialog state and server response
|
|
127
|
-
React.useEffect(() => {
|
|
128
|
-
if (invalidCredentialsProvided) {
|
|
129
|
-
setWarningMessage(invalidCredentialsLabel);
|
|
130
|
-
}
|
|
131
|
-
else if (serverRequireCredentials && (!userName || !password)) {
|
|
132
|
-
setWarningMessage(missingCredentialsLabel);
|
|
133
|
-
}
|
|
134
|
-
else {
|
|
135
|
-
setWarningMessage(undefined);
|
|
136
|
-
}
|
|
137
|
-
}, [invalidCredentialsProvided, invalidCredentialsLabel, missingCredentialsLabel, serverRequireCredentials, userName, password, setWarningMessage]);
|
|
138
121
|
const handleMapTypeSelection = React.useCallback((newValue) => {
|
|
139
122
|
setMapType(newValue);
|
|
140
|
-
|
|
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]);
|
|
141
130
|
const handleCancel = React.useCallback(() => {
|
|
142
131
|
if (props.onCancelResult) {
|
|
143
132
|
props.onCancelResult();
|
|
@@ -155,88 +144,109 @@ function MapUrlDialog(props) {
|
|
|
155
144
|
if (invalidCredentialsProvided)
|
|
156
145
|
setInvalidCredentialsProvided(false);
|
|
157
146
|
}, [setPassword, invalidCredentialsProvided, setInvalidCredentialsProvided]);
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
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) {
|
|
166
198
|
const storeOnIModel = "Model" === settingsStorage;
|
|
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
|
-
}
|
|
198
|
-
}
|
|
199
|
-
else {
|
|
200
|
-
// Update service settings if storage is available and we are not prompting user for credentials
|
|
201
|
-
if (!settingsStorageDisabled && !props.layerRequiringCredentials) {
|
|
202
|
-
if (!(await MapLayerPreferences_1.MapLayerPreferences.storeSource(source, storeOnIModel, vp.iModel.iTwinId, vp.iModel.iModelId))) {
|
|
203
|
-
const msgError = MapLayersUiItemsProvider_1.MapLayersUiItemsProvider.localization.getLocalizedString("mapLayers:Messages.MapLayerPreferencesStoreFailed");
|
|
204
|
-
core_frontend_1.IModelApp.notifications.outputMessage(new core_frontend_1.NotifyMessageDetails(core_frontend_1.OutputMessagePriority.Error, msgError));
|
|
205
|
-
}
|
|
206
|
-
}
|
|
207
|
-
const layerSettings = source.toLayerSettings(validation.subLayers);
|
|
208
|
-
if (layerSettings) {
|
|
209
|
-
vp.displayStyle.attachMapLayerSettings(layerSettings, isOverlay, undefined);
|
|
210
|
-
const msg = core_frontend_1.IModelApp.localization.getLocalizedString("mapLayers:Messages.MapLayerAttached", { sourceName: source.name, sourceUrl: source.url });
|
|
211
|
-
core_frontend_1.IModelApp.notifications.outputMessage(new core_frontend_1.NotifyMessageDetails(core_frontend_1.OutputMessagePriority.Info, msg));
|
|
212
|
-
}
|
|
213
|
-
else {
|
|
214
|
-
const msgError = MapLayersUiItemsProvider_1.MapLayersUiItemsProvider.localization.getLocalizedString("mapLayers:Messages.MapLayerLayerSettingsConversionError");
|
|
215
|
-
const msg = MapLayersUiItemsProvider_1.MapLayersUiItemsProvider.localization.getLocalizedString("mapLayers:CustomAttach.MapLayerAttachError", { error: msgError, sourceUrl: source.url });
|
|
216
|
-
core_frontend_1.IModelApp.notifications.outputMessage(new core_frontend_1.NotifyMessageDetails(core_frontend_1.OutputMessagePriority.Error, msg));
|
|
217
|
-
}
|
|
218
|
-
}
|
|
219
|
-
vp.invalidateRenderPlan();
|
|
220
|
-
}
|
|
221
|
-
if (closeDialog) {
|
|
222
|
-
// This handler will close the layer source handler, and therefore the MapUrl dialog.
|
|
223
|
-
// don't call it if the dialog needs to remains open.
|
|
224
|
-
onOkResult();
|
|
225
|
-
}
|
|
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);
|
|
226
229
|
}
|
|
227
230
|
else {
|
|
228
|
-
|
|
229
|
-
core_frontend_1.IModelApp.notifications.outputMessage(new core_frontend_1.NotifyMessageDetails(core_frontend_1.OutputMessagePriority.Error, `${msg} ${source.url}`));
|
|
230
|
-
resolve(true);
|
|
231
|
+
return await updateAttachedLayer(source, validation);
|
|
231
232
|
}
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
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]);
|
|
240
250
|
const onNameChange = React.useCallback((event) => {
|
|
241
251
|
setMapName(event.target.value);
|
|
242
252
|
}, [setMapName]);
|
|
@@ -246,73 +256,101 @@ function MapUrlDialog(props) {
|
|
|
246
256
|
const onUrlChange = React.useCallback((event) => {
|
|
247
257
|
setMapUrl(event.target.value);
|
|
248
258
|
}, [setMapUrl]);
|
|
249
|
-
const
|
|
259
|
+
const createSource = React.useCallback(() => {
|
|
250
260
|
let source;
|
|
251
261
|
if (mapUrl && mapName) {
|
|
252
262
|
source = core_frontend_1.MapLayerSource.fromJSON({
|
|
253
263
|
url: mapUrl,
|
|
254
264
|
name: mapName,
|
|
255
265
|
formatId: mapType,
|
|
256
|
-
userName,
|
|
257
|
-
password
|
|
266
|
+
userName: userName || undefined,
|
|
267
|
+
password: password || undefined
|
|
258
268
|
});
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
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;
|
|
282
296
|
}
|
|
283
|
-
}
|
|
284
|
-
|
|
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();
|
|
285
314
|
}
|
|
286
315
|
}
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
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) {
|
|
292
329
|
try {
|
|
293
|
-
const
|
|
294
|
-
if (
|
|
295
|
-
setLayerAttachPending(
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
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);
|
|
301
338
|
}
|
|
302
339
|
}
|
|
303
|
-
catch (_error) {
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
}, [
|
|
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
|
+
}, []);
|
|
309
346
|
const dialogContainer = React.useRef(null);
|
|
310
347
|
const readyToSave = React.useCallback(() => {
|
|
311
348
|
const credentialsSet = !!userName && !!password;
|
|
312
349
|
return (!!mapUrl && !!mapName)
|
|
313
|
-
&&
|
|
350
|
+
&& !layerAttachPending
|
|
351
|
+
&& (!serverRequireCredentials || credentialsSet)
|
|
314
352
|
&& !invalidCredentialsProvided;
|
|
315
|
-
}, [mapUrl, mapName,
|
|
353
|
+
}, [userName, password, mapUrl, mapName, serverRequireCredentials, layerAttachPending, invalidCredentialsProvided]);
|
|
316
354
|
const buttonCluster = React.useMemo(() => [
|
|
317
355
|
{ type: appui_abstract_1.DialogButtonType.OK, onClick: handleOk, disabled: !readyToSave() },
|
|
318
356
|
{ type: appui_abstract_1.DialogButtonType.Cancel, onClick: handleCancel },
|
|
@@ -323,33 +361,58 @@ function MapUrlDialog(props) {
|
|
|
323
361
|
handleOk();
|
|
324
362
|
}
|
|
325
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
|
+
}
|
|
326
393
|
return (React.createElement("div", { ref: dialogContainer },
|
|
327
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 },
|
|
328
395
|
React.createElement("div", { className: "map-layer-url-dialog-content" },
|
|
329
396
|
React.createElement("div", { className: "map-layer-source-url" },
|
|
330
397
|
React.createElement("span", { className: "map-layer-source-label" }, typeLabel),
|
|
331
|
-
React.createElement(itwinui_react_1.Select, { className: "map-layer-source-select", options: mapTypes, value: mapType, disabled: props.layerRequiringCredentials !== undefined || props.mapLayerSourceToEdit !== undefined, onChange: handleMapTypeSelection, size: "small" }),
|
|
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" }),
|
|
332
399
|
React.createElement("span", { className: "map-layer-source-label" }, nameLabel),
|
|
333
|
-
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 }),
|
|
334
401
|
React.createElement("span", { className: "map-layer-source-label" }, urlLabel),
|
|
335
|
-
React.createElement(itwinui_react_1.Input, { className: "map-layer-source-input", placeholder: urlInputPlaceHolder, onKeyPress: handleOnKeyDown, onChange: onUrlChange, disabled: props.mapLayerSourceToEdit !== undefined, value: mapUrl
|
|
336
|
-
|
|
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 &&
|
|
337
406
|
React.createElement(React.Fragment, null,
|
|
338
407
|
React.createElement("span", { className: "map-layer-source-label" }, userNameLabel),
|
|
339
|
-
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" }),
|
|
340
409
|
React.createElement("span", { className: "map-layer-source-label" }, passwordLabel),
|
|
341
|
-
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" })),
|
|
342
411
|
isSettingsStorageAvailable && React.createElement("div", { title: settingsStorageDisabled ? noSaveSettingsWarning : "" },
|
|
343
412
|
React.createElement(itwinui_react_1.Radio, { disabled: settingsStorageDisabled, name: "settingsStorage", value: "iTwin", label: iTwinSettingsLabel, checked: settingsStorage === "iTwin", onChange: onRadioChange }),
|
|
344
413
|
React.createElement(itwinui_react_1.Radio, { disabled: settingsStorageDisabled, name: "settingsStorage", value: "Model", label: modelSettingsLabel, checked: settingsStorage === "Model", onChange: onRadioChange })))),
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
React.createElement(core_react_1.Icon, { className: "map-layer-source-warnMessage-icon", iconSpec: "icon-status-warning" }),
|
|
348
|
-
React.createElement("span", { className: "map-layer-source-warnMessage-label" }, warningMessage))
|
|
349
|
-
:
|
|
350
|
-
// Place holder to avoid dialog resize
|
|
351
|
-
React.createElement("span", { className: "map-layer-source-placeholder" }, "\u00A0")),
|
|
352
|
-
layerAttachPending &&
|
|
414
|
+
renderWarningMessage(),
|
|
415
|
+
(layerAttachPending) &&
|
|
353
416
|
React.createElement("div", { className: "map-layer-source-progressBar" },
|
|
354
417
|
React.createElement(itwinui_react_1.ProgressLinear, { indeterminate: true })))));
|
|
355
418
|
}
|